TileOrientedBoundingBox.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import BoundingSphere from '../Core/BoundingSphere.js';
  2. import BoxOutlineGeometry from '../Core/BoxOutlineGeometry.js';
  3. import Cartesian3 from '../Core/Cartesian3.js';
  4. import Check from '../Core/Check.js';
  5. import ColorGeometryInstanceAttribute from '../Core/ColorGeometryInstanceAttribute.js';
  6. import defineProperties from '../Core/defineProperties.js';
  7. import GeometryInstance from '../Core/GeometryInstance.js';
  8. import Matrix3 from '../Core/Matrix3.js';
  9. import Matrix4 from '../Core/Matrix4.js';
  10. import CesiumMath from '../Core/Math.js';
  11. import OrientedBoundingBox from '../Core/OrientedBoundingBox.js';
  12. import PerInstanceColorAppearance from './PerInstanceColorAppearance.js';
  13. import Primitive from './Primitive.js';
  14. var scratchU = new Cartesian3();
  15. var scratchV = new Cartesian3();
  16. var scratchW = new Cartesian3();
  17. var scratchCartesian = new Cartesian3();
  18. function computeMissingVector(a, b, result) {
  19. result = Cartesian3.cross(a, b, result);
  20. var magnitude = Cartesian3.magnitude(result);
  21. return Cartesian3.multiplyByScalar(result, CesiumMath.EPSILON7 / magnitude, result);
  22. }
  23. function findOrthogonalVector(a, result) {
  24. var temp = Cartesian3.normalize(a, scratchCartesian);
  25. var b = Cartesian3.equalsEpsilon(temp, Cartesian3.UNIT_X, CesiumMath.EPSILON6) ? Cartesian3.UNIT_Y : Cartesian3.UNIT_X;
  26. return computeMissingVector(a, b, result);
  27. }
  28. function checkHalfAxes(halfAxes) {
  29. var u = Matrix3.getColumn(halfAxes, 0, scratchU);
  30. var v = Matrix3.getColumn(halfAxes, 1, scratchV);
  31. var w = Matrix3.getColumn(halfAxes, 2, scratchW);
  32. var uZero = Cartesian3.equals(u, Cartesian3.ZERO);
  33. var vZero = Cartesian3.equals(v, Cartesian3.ZERO);
  34. var wZero = Cartesian3.equals(w, Cartesian3.ZERO);
  35. if (!uZero && !vZero && !wZero) {
  36. return halfAxes;
  37. }
  38. if (uZero && vZero && wZero) {
  39. halfAxes[0] = CesiumMath.EPSILON7;
  40. halfAxes[4] = CesiumMath.EPSILON7;
  41. halfAxes[8] = CesiumMath.EPSILON7;
  42. return halfAxes;
  43. }
  44. if (uZero && !vZero && !wZero) {
  45. u = computeMissingVector(v, w, u);
  46. } else if (!uZero && vZero && !wZero) {
  47. v = computeMissingVector(u, w, v);
  48. } else if (!uZero && !vZero && wZero) {
  49. w = computeMissingVector(v, u, w);
  50. } else if (!uZero) {
  51. v = findOrthogonalVector(u, v);
  52. w = computeMissingVector(v, u, w);
  53. } else if (!vZero) {
  54. u = findOrthogonalVector(v, u);
  55. w = computeMissingVector(v, u, w);
  56. } else if (!wZero) {
  57. u = findOrthogonalVector(w, u);
  58. v = computeMissingVector(w, u, v);
  59. }
  60. Matrix3.setColumn(halfAxes, 0, u, halfAxes);
  61. Matrix3.setColumn(halfAxes, 1, v, halfAxes);
  62. Matrix3.setColumn(halfAxes, 2, w, halfAxes);
  63. return halfAxes;
  64. }
  65. /**
  66. * A tile bounding volume specified as an oriented bounding box.
  67. * @alias TileOrientedBoundingBox
  68. * @constructor
  69. *
  70. * @param {Cartesian3} [center=Cartesian3.ZERO] The center of the box.
  71. * @param {Matrix3} [halfAxes=Matrix3.ZERO] The three orthogonal half-axes of the bounding box.
  72. * Equivalently, the transformation matrix, to rotate and scale a 2x2x2
  73. * cube centered at the origin.
  74. *
  75. * @private
  76. */
  77. function TileOrientedBoundingBox(center, halfAxes) {
  78. halfAxes = checkHalfAxes(halfAxes);
  79. this._orientedBoundingBox = new OrientedBoundingBox(center, halfAxes);
  80. this._boundingSphere = BoundingSphere.fromOrientedBoundingBox(this._orientedBoundingBox);
  81. }
  82. defineProperties(TileOrientedBoundingBox.prototype, {
  83. /**
  84. * The underlying bounding volume.
  85. *
  86. * @memberof TileOrientedBoundingBox.prototype
  87. *
  88. * @type {Object}
  89. * @readonly
  90. */
  91. boundingVolume : {
  92. get : function() {
  93. return this._orientedBoundingBox;
  94. }
  95. },
  96. /**
  97. * The underlying bounding sphere.
  98. *
  99. * @memberof TileOrientedBoundingBox.prototype
  100. *
  101. * @type {BoundingSphere}
  102. * @readonly
  103. */
  104. boundingSphere : {
  105. get : function() {
  106. return this._boundingSphere;
  107. }
  108. }
  109. });
  110. /**
  111. * Computes the distance between this bounding box and the camera attached to frameState.
  112. *
  113. * @param {FrameState} frameState The frameState to which the camera is attached.
  114. * @returns {Number} The distance between the camera and the bounding box in meters. Returns 0 if the camera is inside the bounding volume.
  115. */
  116. TileOrientedBoundingBox.prototype.distanceToCamera = function(frameState) {
  117. //>>includeStart('debug', pragmas.debug);
  118. Check.defined('frameState', frameState);
  119. //>>includeEnd('debug');
  120. return Math.sqrt(this._orientedBoundingBox.distanceSquaredTo(frameState.camera.positionWC));
  121. };
  122. /**
  123. * Determines which side of a plane this box is located.
  124. *
  125. * @param {Plane} plane The plane to test against.
  126. * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane
  127. * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is
  128. * on the opposite side, and {@link Intersect.INTERSECTING} if the box
  129. * intersects the plane.
  130. */
  131. TileOrientedBoundingBox.prototype.intersectPlane = function(plane) {
  132. //>>includeStart('debug', pragmas.debug);
  133. Check.defined('plane', plane);
  134. //>>includeEnd('debug');
  135. return this._orientedBoundingBox.intersectPlane(plane);
  136. };
  137. /**
  138. * Update the bounding box after the tile is transformed.
  139. *
  140. * @param {Cartesian3} center The center of the box.
  141. * @param {Matrix3} halfAxes The three orthogonal half-axes of the bounding box.
  142. * Equivalently, the transformation matrix, to rotate and scale a 2x2x2
  143. * cube centered at the origin.
  144. */
  145. TileOrientedBoundingBox.prototype.update = function(center, halfAxes) {
  146. Cartesian3.clone(center, this._orientedBoundingBox.center);
  147. halfAxes = checkHalfAxes(halfAxes);
  148. Matrix3.clone(halfAxes, this._orientedBoundingBox.halfAxes);
  149. BoundingSphere.fromOrientedBoundingBox(this._orientedBoundingBox, this._boundingSphere);
  150. };
  151. /**
  152. * Creates a debug primitive that shows the outline of the box.
  153. *
  154. * @param {Color} color The desired color of the primitive's mesh
  155. * @return {Primitive}
  156. */
  157. TileOrientedBoundingBox.prototype.createDebugVolume = function(color) {
  158. //>>includeStart('debug', pragmas.debug);
  159. Check.defined('color', color);
  160. //>>includeEnd('debug');
  161. var geometry = new BoxOutlineGeometry({
  162. // Make a 2x2x2 cube
  163. minimum : new Cartesian3(-1.0, -1.0, -1.0),
  164. maximum : new Cartesian3(1.0, 1.0, 1.0)
  165. });
  166. var modelMatrix = Matrix4.fromRotationTranslation(this.boundingVolume.halfAxes, this.boundingVolume.center);
  167. var instance = new GeometryInstance({
  168. geometry : geometry,
  169. id : 'outline',
  170. modelMatrix : modelMatrix,
  171. attributes : {
  172. color : ColorGeometryInstanceAttribute.fromColor(color)
  173. }
  174. });
  175. return new Primitive({
  176. geometryInstances : instance,
  177. appearance : new PerInstanceColorAppearance({
  178. translucent : false,
  179. flat : true
  180. }),
  181. asynchronous : false
  182. });
  183. };
  184. export default TileOrientedBoundingBox;