boundingSphere.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import { ArrayTools } from "../Misc/arrayTools.js";
  2. import { Matrix, Vector3 } from "../Maths/math.vector.js";
  3. /**
  4. * Class used to store bounding sphere information
  5. */
  6. export class BoundingSphere {
  7. /**
  8. * Creates a new bounding sphere
  9. * @param min defines the minimum vector (in local space)
  10. * @param max defines the maximum vector (in local space)
  11. * @param worldMatrix defines the new world matrix
  12. */
  13. constructor(min, max, worldMatrix) {
  14. /**
  15. * Gets the center of the bounding sphere in local space
  16. */
  17. this.center = Vector3.Zero();
  18. /**
  19. * Gets the center of the bounding sphere in world space
  20. */
  21. this.centerWorld = Vector3.Zero();
  22. /**
  23. * Gets the minimum vector in local space
  24. */
  25. this.minimum = Vector3.Zero();
  26. /**
  27. * Gets the maximum vector in local space
  28. */
  29. this.maximum = Vector3.Zero();
  30. this.reConstruct(min, max, worldMatrix);
  31. }
  32. /**
  33. * Recreates the entire bounding sphere from scratch as if we call the constructor in place
  34. * @param min defines the new minimum vector (in local space)
  35. * @param max defines the new maximum vector (in local space)
  36. * @param worldMatrix defines the new world matrix
  37. */
  38. reConstruct(min, max, worldMatrix) {
  39. this.minimum.copyFrom(min);
  40. this.maximum.copyFrom(max);
  41. const distance = Vector3.Distance(min, max);
  42. max.addToRef(min, this.center).scaleInPlace(0.5);
  43. this.radius = distance * 0.5;
  44. this._update(worldMatrix || Matrix.IdentityReadOnly);
  45. }
  46. /**
  47. * Scale the current bounding sphere by applying a scale factor
  48. * @param factor defines the scale factor to apply
  49. * @returns the current bounding box
  50. */
  51. scale(factor) {
  52. const newRadius = this.radius * factor;
  53. const tmpVectors = BoundingSphere._TmpVector3;
  54. const tempRadiusVector = tmpVectors[0].setAll(newRadius);
  55. const min = this.center.subtractToRef(tempRadiusVector, tmpVectors[1]);
  56. const max = this.center.addToRef(tempRadiusVector, tmpVectors[2]);
  57. this.reConstruct(min, max, this._worldMatrix);
  58. return this;
  59. }
  60. /**
  61. * Gets the world matrix of the bounding box
  62. * @returns a matrix
  63. */
  64. getWorldMatrix() {
  65. return this._worldMatrix;
  66. }
  67. // Methods
  68. /**
  69. * @internal
  70. */
  71. _update(worldMatrix) {
  72. if (!worldMatrix.isIdentity()) {
  73. Vector3.TransformCoordinatesToRef(this.center, worldMatrix, this.centerWorld);
  74. const tempVector = BoundingSphere._TmpVector3[0];
  75. Vector3.TransformNormalFromFloatsToRef(1.0, 1.0, 1.0, worldMatrix, tempVector);
  76. this.radiusWorld = Math.max(Math.abs(tempVector.x), Math.abs(tempVector.y), Math.abs(tempVector.z)) * this.radius;
  77. }
  78. else {
  79. this.centerWorld.copyFrom(this.center);
  80. this.radiusWorld = this.radius;
  81. }
  82. }
  83. /**
  84. * Tests if the bounding sphere is intersecting the frustum planes
  85. * @param frustumPlanes defines the frustum planes to test
  86. * @returns true if there is an intersection
  87. */
  88. isInFrustum(frustumPlanes) {
  89. const center = this.centerWorld;
  90. const radius = this.radiusWorld;
  91. for (let i = 0; i < 6; i++) {
  92. if (frustumPlanes[i].dotCoordinate(center) <= -radius) {
  93. return false;
  94. }
  95. }
  96. return true;
  97. }
  98. /**
  99. * Tests if the bounding sphere center is in between the frustum planes.
  100. * Used for optimistic fast inclusion.
  101. * @param frustumPlanes defines the frustum planes to test
  102. * @returns true if the sphere center is in between the frustum planes
  103. */
  104. isCenterInFrustum(frustumPlanes) {
  105. const center = this.centerWorld;
  106. for (let i = 0; i < 6; i++) {
  107. if (frustumPlanes[i].dotCoordinate(center) < 0) {
  108. return false;
  109. }
  110. }
  111. return true;
  112. }
  113. /**
  114. * Tests if a point is inside the bounding sphere
  115. * @param point defines the point to test
  116. * @returns true if the point is inside the bounding sphere
  117. */
  118. intersectsPoint(point) {
  119. const squareDistance = Vector3.DistanceSquared(this.centerWorld, point);
  120. if (this.radiusWorld * this.radiusWorld < squareDistance) {
  121. return false;
  122. }
  123. return true;
  124. }
  125. // Statics
  126. /**
  127. * Checks if two sphere intersect
  128. * @param sphere0 sphere 0
  129. * @param sphere1 sphere 1
  130. * @returns true if the spheres intersect
  131. */
  132. static Intersects(sphere0, sphere1) {
  133. const squareDistance = Vector3.DistanceSquared(sphere0.centerWorld, sphere1.centerWorld);
  134. const radiusSum = sphere0.radiusWorld + sphere1.radiusWorld;
  135. if (radiusSum * radiusSum < squareDistance) {
  136. return false;
  137. }
  138. return true;
  139. }
  140. /**
  141. * Creates a sphere from a center and a radius
  142. * @param center The center
  143. * @param radius radius
  144. * @param matrix Optional worldMatrix
  145. * @returns The sphere
  146. */
  147. static CreateFromCenterAndRadius(center, radius, matrix) {
  148. this._TmpVector3[0].copyFrom(center);
  149. this._TmpVector3[1].copyFromFloats(0, 0, radius);
  150. this._TmpVector3[2].copyFrom(center);
  151. this._TmpVector3[0].addInPlace(this._TmpVector3[1]);
  152. this._TmpVector3[2].subtractInPlace(this._TmpVector3[1]);
  153. const sphere = new BoundingSphere(this._TmpVector3[0], this._TmpVector3[2]);
  154. if (matrix) {
  155. sphere._worldMatrix = matrix;
  156. }
  157. else {
  158. sphere._worldMatrix = Matrix.Identity();
  159. }
  160. return sphere;
  161. }
  162. }
  163. BoundingSphere._TmpVector3 = ArrayTools.BuildArray(3, Vector3.Zero);
  164. //# sourceMappingURL=boundingSphere.js.map