babylon.boundingSphere.ts 6.2 KB

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