FrustumArray.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. import { WebGLCoordinateSystem } from '../constants.js';
  2. import { Frustum } from './Frustum.js';
  3. import { Matrix4 } from './Matrix4.js';
  4. const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
  5. const _frustum = /*@__PURE__*/ new Frustum();
  6. /**
  7. * FrustumArray is used to determine if an object is visible in at least one camera
  8. * from an array of cameras. This is particularly useful for multi-view renderers.
  9. */
  10. class FrustumArray {
  11. /**
  12. * Constructs a new frustum array.
  13. *
  14. */
  15. constructor() {
  16. /**
  17. * The coordinate system to use.
  18. *
  19. * @type {WebGLCoordinateSystem|WebGPUCoordinateSystem}
  20. * @default WebGLCoordinateSystem
  21. */
  22. this.coordinateSystem = WebGLCoordinateSystem;
  23. }
  24. /**
  25. * Returns `true` if the 3D object's bounding sphere is intersecting any frustum
  26. * from the camera array.
  27. *
  28. * @param {Object3D} object - The 3D object to test.
  29. * @param {Object} cameraArray - An object with a cameras property containing an array of cameras.
  30. * @return {boolean} Whether the 3D object is visible in any camera.
  31. */
  32. intersectsObject( object, cameraArray ) {
  33. if ( ! cameraArray.isArrayCamera || cameraArray.cameras.length === 0 ) {
  34. return false;
  35. }
  36. for ( let i = 0; i < cameraArray.cameras.length; i ++ ) {
  37. const camera = cameraArray.cameras[ i ];
  38. _projScreenMatrix.multiplyMatrices(
  39. camera.projectionMatrix,
  40. camera.matrixWorldInverse
  41. );
  42. _frustum.setFromProjectionMatrix(
  43. _projScreenMatrix,
  44. camera.coordinateSystem,
  45. camera.reversedDepth
  46. );
  47. if ( _frustum.intersectsObject( object ) ) {
  48. return true; // Object is visible in at least one camera
  49. }
  50. }
  51. return false; // Not visible in any camera
  52. }
  53. /**
  54. * Returns `true` if the given sprite is intersecting any frustum
  55. * from the camera array.
  56. *
  57. * @param {Sprite} sprite - The sprite to test.
  58. * @param {Object} cameraArray - An object with a cameras property containing an array of cameras.
  59. * @return {boolean} Whether the sprite is visible in any camera.
  60. */
  61. intersectsSprite( sprite, cameraArray ) {
  62. if ( ! cameraArray || ! cameraArray.cameras || cameraArray.cameras.length === 0 ) {
  63. return false;
  64. }
  65. for ( let i = 0; i < cameraArray.cameras.length; i ++ ) {
  66. const camera = cameraArray.cameras[ i ];
  67. _projScreenMatrix.multiplyMatrices(
  68. camera.projectionMatrix,
  69. camera.matrixWorldInverse
  70. );
  71. _frustum.setFromProjectionMatrix(
  72. _projScreenMatrix,
  73. camera.coordinateSystem,
  74. camera.reversedDepth
  75. );
  76. if ( _frustum.intersectsSprite( sprite ) ) {
  77. return true; // Sprite is visible in at least one camera
  78. }
  79. }
  80. return false; // Not visible in any camera
  81. }
  82. /**
  83. * Returns `true` if the given bounding sphere is intersecting any frustum
  84. * from the camera array.
  85. *
  86. * @param {Sphere} sphere - The bounding sphere to test.
  87. * @param {Object} cameraArray - An object with a cameras property containing an array of cameras.
  88. * @return {boolean} Whether the sphere is visible in any camera.
  89. */
  90. intersectsSphere( sphere, cameraArray ) {
  91. if ( ! cameraArray || ! cameraArray.cameras || cameraArray.cameras.length === 0 ) {
  92. return false;
  93. }
  94. for ( let i = 0; i < cameraArray.cameras.length; i ++ ) {
  95. const camera = cameraArray.cameras[ i ];
  96. _projScreenMatrix.multiplyMatrices(
  97. camera.projectionMatrix,
  98. camera.matrixWorldInverse
  99. );
  100. _frustum.setFromProjectionMatrix(
  101. _projScreenMatrix,
  102. camera.coordinateSystem,
  103. camera.reversedDepth
  104. );
  105. if ( _frustum.intersectsSphere( sphere ) ) {
  106. return true; // Sphere is visible in at least one camera
  107. }
  108. }
  109. return false; // Not visible in any camera
  110. }
  111. /**
  112. * Returns `true` if the given bounding box is intersecting any frustum
  113. * from the camera array.
  114. *
  115. * @param {Box3} box - The bounding box to test.
  116. * @param {Object} cameraArray - An object with a cameras property containing an array of cameras.
  117. * @return {boolean} Whether the box is visible in any camera.
  118. */
  119. intersectsBox( box, cameraArray ) {
  120. if ( ! cameraArray || ! cameraArray.cameras || cameraArray.cameras.length === 0 ) {
  121. return false;
  122. }
  123. for ( let i = 0; i < cameraArray.cameras.length; i ++ ) {
  124. const camera = cameraArray.cameras[ i ];
  125. _projScreenMatrix.multiplyMatrices(
  126. camera.projectionMatrix,
  127. camera.matrixWorldInverse
  128. );
  129. _frustum.setFromProjectionMatrix(
  130. _projScreenMatrix,
  131. camera.coordinateSystem,
  132. camera.reversedDepth
  133. );
  134. if ( _frustum.intersectsBox( box ) ) {
  135. return true; // Box is visible in at least one camera
  136. }
  137. }
  138. return false; // Not visible in any camera
  139. }
  140. /**
  141. * Returns `true` if the given point lies within any frustum
  142. * from the camera array.
  143. *
  144. * @param {Vector3} point - The point to test.
  145. * @param {Object} cameraArray - An object with a cameras property containing an array of cameras.
  146. * @return {boolean} Whether the point is visible in any camera.
  147. */
  148. containsPoint( point, cameraArray ) {
  149. if ( ! cameraArray || ! cameraArray.cameras || cameraArray.cameras.length === 0 ) {
  150. return false;
  151. }
  152. for ( let i = 0; i < cameraArray.cameras.length; i ++ ) {
  153. const camera = cameraArray.cameras[ i ];
  154. _projScreenMatrix.multiplyMatrices(
  155. camera.projectionMatrix,
  156. camera.matrixWorldInverse
  157. );
  158. _frustum.setFromProjectionMatrix(
  159. _projScreenMatrix,
  160. camera.coordinateSystem,
  161. camera.reversedDepth
  162. );
  163. if ( _frustum.containsPoint( point ) ) {
  164. return true; // Point is visible in at least one camera
  165. }
  166. }
  167. return false; // Not visible in any camera
  168. }
  169. /**
  170. * Returns a new frustum array with copied values from this instance.
  171. *
  172. * @return {FrustumArray} A clone of this instance.
  173. */
  174. clone() {
  175. return new FrustumArray();
  176. }
  177. }
  178. export { FrustumArray };
粤ICP备19079148号