Frustum.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import { WebGLCoordinateSystem, WebGPUCoordinateSystem } from '../constants.js';
  2. import { Vector3 } from './Vector3.js';
  3. import { Sphere } from './Sphere.js';
  4. import { Plane } from './Plane.js';
  5. const _sphere = /*@__PURE__*/ new Sphere();
  6. const _vector = /*@__PURE__*/ new Vector3();
  7. class Frustum {
  8. constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) {
  9. this.planes = [ p0, p1, p2, p3, p4, p5 ];
  10. }
  11. set( p0, p1, p2, p3, p4, p5 ) {
  12. const planes = this.planes;
  13. planes[ 0 ].copy( p0 );
  14. planes[ 1 ].copy( p1 );
  15. planes[ 2 ].copy( p2 );
  16. planes[ 3 ].copy( p3 );
  17. planes[ 4 ].copy( p4 );
  18. planes[ 5 ].copy( p5 );
  19. return this;
  20. }
  21. copy( frustum ) {
  22. const planes = this.planes;
  23. for ( let i = 0; i < 6; i ++ ) {
  24. planes[ i ].copy( frustum.planes[ i ] );
  25. }
  26. return this;
  27. }
  28. setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) {
  29. const planes = this.planes;
  30. const me = m.elements;
  31. const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
  32. const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
  33. const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
  34. const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
  35. planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
  36. planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
  37. planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
  38. planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
  39. planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
  40. if ( coordinateSystem === WebGLCoordinateSystem ) {
  41. planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
  42. } else if ( coordinateSystem === WebGPUCoordinateSystem ) {
  43. planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize();
  44. } else {
  45. throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem );
  46. }
  47. return this;
  48. }
  49. intersectsObject( object ) {
  50. if ( object.boundingSphere !== undefined ) {
  51. if ( object.boundingSphere === null ) object.computeBoundingSphere();
  52. _sphere.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld );
  53. } else {
  54. const geometry = object.geometry;
  55. if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
  56. _sphere.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
  57. }
  58. return this.intersectsSphere( _sphere );
  59. }
  60. intersectsSprite( sprite ) {
  61. _sphere.center.set( 0, 0, 0 );
  62. _sphere.radius = 0.7071067811865476;
  63. _sphere.applyMatrix4( sprite.matrixWorld );
  64. return this.intersectsSphere( _sphere );
  65. }
  66. intersectsSphere( sphere ) {
  67. const planes = this.planes;
  68. const center = sphere.center;
  69. const negRadius = - sphere.radius;
  70. for ( let i = 0; i < 6; i ++ ) {
  71. const distance = planes[ i ].distanceToPoint( center );
  72. if ( distance < negRadius ) {
  73. return false;
  74. }
  75. }
  76. return true;
  77. }
  78. intersectsBox( box ) {
  79. const planes = this.planes;
  80. for ( let i = 0; i < 6; i ++ ) {
  81. const plane = planes[ i ];
  82. // corner at max distance
  83. _vector.x = plane.normal.x > 0 ? box.max.x : box.min.x;
  84. _vector.y = plane.normal.y > 0 ? box.max.y : box.min.y;
  85. _vector.z = plane.normal.z > 0 ? box.max.z : box.min.z;
  86. if ( plane.distanceToPoint( _vector ) < 0 ) {
  87. return false;
  88. }
  89. }
  90. return true;
  91. }
  92. containsPoint( point ) {
  93. const planes = this.planes;
  94. for ( let i = 0; i < 6; i ++ ) {
  95. if ( planes[ i ].distanceToPoint( point ) < 0 ) {
  96. return false;
  97. }
  98. }
  99. return true;
  100. }
  101. clone() {
  102. return new this.constructor().copy( this );
  103. }
  104. }
  105. export { Frustum };