babylon.boundingInfo.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. module BABYLON {
  2. var computeBoxExtents = (axis: Vector3, box: BoundingBox) => {
  3. var p = Vector3.Dot(box.centerWorld, axis);
  4. var r0 = Math.abs(Vector3.Dot(box.directions[0], axis)) * box.extendSize.x;
  5. var r1 = Math.abs(Vector3.Dot(box.directions[1], axis)) * box.extendSize.y;
  6. var r2 = Math.abs(Vector3.Dot(box.directions[2], axis)) * box.extendSize.z;
  7. var r = r0 + r1 + r2;
  8. return {
  9. min: p - r,
  10. max: p + r
  11. };
  12. }
  13. var extentsOverlap = (min0: number, max0: number, min1: number, max1: number): boolean => !(min0 > max1 || min1 > max0);
  14. var axisOverlap = (axis: Vector3, box0: BoundingBox, box1: BoundingBox): boolean => {
  15. var result0 = computeBoxExtents(axis, box0);
  16. var result1 = computeBoxExtents(axis, box1);
  17. return extentsOverlap(result0.min, result0.max, result1.min, result1.max);
  18. }
  19. export interface ICullable {
  20. isInFrustum(frustumPlanes: Plane[]): boolean;
  21. isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
  22. }
  23. export class BoundingInfo implements ICullable {
  24. public boundingBox: BoundingBox;
  25. public boundingSphere: BoundingSphere;
  26. private _isLocked = false;
  27. constructor(public minimum: Vector3, public maximum: Vector3) {
  28. this.boundingBox = new BoundingBox(minimum, maximum);
  29. this.boundingSphere = new BoundingSphere(minimum, maximum);
  30. }
  31. public get isLocked(): boolean {
  32. return this._isLocked;
  33. }
  34. public set isLocked(value: boolean) {
  35. this._isLocked = value;
  36. }
  37. // Methods
  38. public update(world: Matrix) {
  39. if (this._isLocked) {
  40. return;
  41. }
  42. this.boundingBox._update(world);
  43. this.boundingSphere._update(world);
  44. }
  45. /**
  46. * Recreate the bounding info to be centered around a specific point given a specific extend.
  47. * @param center New center of the bounding info
  48. * @param extend New extend of the bounding info
  49. */
  50. public centerOn(center: Vector3, extend: Vector3): BoundingInfo {
  51. this.minimum = center.subtract(extend);
  52. this.maximum = center.add(extend);
  53. this.boundingBox = new BoundingBox(this.minimum, this.maximum);
  54. this.boundingSphere = new BoundingSphere(this.minimum, this.maximum);
  55. return this;
  56. }
  57. /**
  58. * Scale the current bounding info by applying a scale factor
  59. * @param factor defines the scale factor to apply
  60. * @returns the current bounding info
  61. */
  62. public scale(factor: number): BoundingInfo {
  63. this.boundingBox.scale(factor);
  64. this.boundingSphere.scale(factor);
  65. return this;
  66. }
  67. /**
  68. * Returns `true` if the bounding info is within the frustum defined by the passed array of planes.
  69. * @param frustumPlanes defines the frustum to test
  70. * @param strategy defines the strategy to use for the culling (default is BABYLON.Scene.CULLINGSTRATEGY_STANDARD)
  71. * @returns true if the bounding info is in the frustum planes
  72. */
  73. public isInFrustum(frustumPlanes: Plane[], strategy: number = AbstractMesh.CULLINGSTRATEGY_STANDARD): boolean {
  74. if (!this.boundingSphere.isInFrustum(frustumPlanes)) {
  75. return false;
  76. }
  77. if (strategy === AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY) {
  78. return true;
  79. }
  80. return this.boundingBox.isInFrustum(frustumPlanes);
  81. }
  82. /**
  83. * Gets the world distance between the min and max points of the bounding box
  84. */
  85. public get diagonalLength(): number {
  86. let boundingBox = this.boundingBox;
  87. let size = boundingBox.maximumWorld.subtract(boundingBox.minimumWorld);
  88. return size.length();
  89. }
  90. public isCompletelyInFrustum(frustumPlanes: Plane[]): boolean {
  91. return this.boundingBox.isCompletelyInFrustum(frustumPlanes);
  92. }
  93. /** @hidden */
  94. public _checkCollision(collider: Collider): boolean {
  95. return collider._canDoCollision(this.boundingSphere.centerWorld, this.boundingSphere.radiusWorld, this.boundingBox.minimumWorld, this.boundingBox.maximumWorld);
  96. }
  97. public intersectsPoint(point: Vector3): boolean {
  98. if (!this.boundingSphere.centerWorld) {
  99. return false;
  100. }
  101. if (!this.boundingSphere.intersectsPoint(point)) {
  102. return false;
  103. }
  104. if (!this.boundingBox.intersectsPoint(point)) {
  105. return false;
  106. }
  107. return true;
  108. }
  109. public intersects(boundingInfo: BoundingInfo, precise: boolean): boolean {
  110. if (!this.boundingSphere.centerWorld || !boundingInfo.boundingSphere.centerWorld) {
  111. return false;
  112. }
  113. if (!BoundingSphere.Intersects(this.boundingSphere, boundingInfo.boundingSphere)) {
  114. return false;
  115. }
  116. if (!BoundingBox.Intersects(this.boundingBox, boundingInfo.boundingBox)) {
  117. return false;
  118. }
  119. if (!precise) {
  120. return true;
  121. }
  122. var box0 = this.boundingBox;
  123. var box1 = boundingInfo.boundingBox;
  124. if (!axisOverlap(box0.directions[0], box0, box1)) return false;
  125. if (!axisOverlap(box0.directions[1], box0, box1)) return false;
  126. if (!axisOverlap(box0.directions[2], box0, box1)) return false;
  127. if (!axisOverlap(box1.directions[0], box0, box1)) return false;
  128. if (!axisOverlap(box1.directions[1], box0, box1)) return false;
  129. if (!axisOverlap(box1.directions[2], box0, box1)) return false;
  130. if (!axisOverlap(Vector3.Cross(box0.directions[0], box1.directions[0]), box0, box1)) return false;
  131. if (!axisOverlap(Vector3.Cross(box0.directions[0], box1.directions[1]), box0, box1)) return false;
  132. if (!axisOverlap(Vector3.Cross(box0.directions[0], box1.directions[2]), box0, box1)) return false;
  133. if (!axisOverlap(Vector3.Cross(box0.directions[1], box1.directions[0]), box0, box1)) return false;
  134. if (!axisOverlap(Vector3.Cross(box0.directions[1], box1.directions[1]), box0, box1)) return false;
  135. if (!axisOverlap(Vector3.Cross(box0.directions[1], box1.directions[2]), box0, box1)) return false;
  136. if (!axisOverlap(Vector3.Cross(box0.directions[2], box1.directions[0]), box0, box1)) return false;
  137. if (!axisOverlap(Vector3.Cross(box0.directions[2], box1.directions[1]), box0, box1)) return false;
  138. if (!axisOverlap(Vector3.Cross(box0.directions[2], box1.directions[2]), box0, box1)) return false;
  139. return true;
  140. }
  141. }
  142. }