TileOrientedBoundingBox.js 6.8 KB

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