Plane.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import { Matrix3 } from './Matrix3';
  2. import { Vector3 } from './Vector3';
  3. /**
  4. * @author bhouston / http://clara.io
  5. */
  6. function Plane( normal, constant ) {
  7. this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
  8. this.constant = ( constant !== undefined ) ? constant : 0;
  9. }
  10. Object.assign( Plane.prototype, {
  11. set: function ( normal, constant ) {
  12. this.normal.copy( normal );
  13. this.constant = constant;
  14. return this;
  15. },
  16. setComponents: function ( x, y, z, w ) {
  17. this.normal.set( x, y, z );
  18. this.constant = w;
  19. return this;
  20. },
  21. setFromNormalAndCoplanarPoint: function ( normal, point ) {
  22. this.normal.copy( normal );
  23. this.constant = - point.dot( this.normal ); // must be this.normal, not normal, as this.normal is normalized
  24. return this;
  25. },
  26. setFromCoplanarPoints: function () {
  27. var v1 = new Vector3();
  28. var v2 = new Vector3();
  29. return function setFromCoplanarPoints( a, b, c ) {
  30. var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
  31. // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
  32. this.setFromNormalAndCoplanarPoint( normal, a );
  33. return this;
  34. };
  35. }(),
  36. clone: function () {
  37. return new this.constructor().copy( this );
  38. },
  39. copy: function ( plane ) {
  40. this.normal.copy( plane.normal );
  41. this.constant = plane.constant;
  42. return this;
  43. },
  44. normalize: function () {
  45. // Note: will lead to a divide by zero if the plane is invalid.
  46. var inverseNormalLength = 1.0 / this.normal.length();
  47. this.normal.multiplyScalar( inverseNormalLength );
  48. this.constant *= inverseNormalLength;
  49. return this;
  50. },
  51. negate: function () {
  52. this.constant *= - 1;
  53. this.normal.negate();
  54. return this;
  55. },
  56. distanceToPoint: function ( point ) {
  57. return this.normal.dot( point ) + this.constant;
  58. },
  59. distanceToSphere: function ( sphere ) {
  60. return this.distanceToPoint( sphere.center ) - sphere.radius;
  61. },
  62. projectPoint: function ( point, optionalTarget ) {
  63. return this.orthoPoint( point, optionalTarget ).sub( point ).negate();
  64. },
  65. orthoPoint: function ( point, optionalTarget ) {
  66. var perpendicularMagnitude = this.distanceToPoint( point );
  67. var result = optionalTarget || new Vector3();
  68. return result.copy( this.normal ).multiplyScalar( perpendicularMagnitude );
  69. },
  70. intersectLine: function () {
  71. var v1 = new Vector3();
  72. return function intersectLine( line, optionalTarget ) {
  73. var result = optionalTarget || new Vector3();
  74. var direction = line.delta( v1 );
  75. var denominator = this.normal.dot( direction );
  76. if ( denominator === 0 ) {
  77. // line is coplanar, return origin
  78. if ( this.distanceToPoint( line.start ) === 0 ) {
  79. return result.copy( line.start );
  80. }
  81. // Unsure if this is the correct method to handle this case.
  82. return undefined;
  83. }
  84. var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
  85. if ( t < 0 || t > 1 ) {
  86. return undefined;
  87. }
  88. return result.copy( direction ).multiplyScalar( t ).add( line.start );
  89. };
  90. }(),
  91. intersectsLine: function ( line ) {
  92. // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
  93. var startSign = this.distanceToPoint( line.start );
  94. var endSign = this.distanceToPoint( line.end );
  95. return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
  96. },
  97. intersectsBox: function ( box ) {
  98. return box.intersectsPlane( this );
  99. },
  100. intersectsSphere: function ( sphere ) {
  101. return sphere.intersectsPlane( this );
  102. },
  103. coplanarPoint: function ( optionalTarget ) {
  104. var result = optionalTarget || new Vector3();
  105. return result.copy( this.normal ).multiplyScalar( - this.constant );
  106. },
  107. applyMatrix4: function () {
  108. var v1 = new Vector3();
  109. var m1 = new Matrix3();
  110. return function applyMatrix4( matrix, optionalNormalMatrix ) {
  111. var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix );
  112. // transform normal based on theory here:
  113. // http://www.songho.ca/opengl/gl_normaltransform.html
  114. var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix );
  115. var normal = this.normal.applyMatrix3( normalMatrix ).normalize();
  116. // recalculate constant (like in setFromNormalAndCoplanarPoint)
  117. this.constant = - referencePoint.dot( normal );
  118. return this;
  119. };
  120. }(),
  121. translate: function ( offset ) {
  122. this.constant = this.constant - offset.dot( this.normal );
  123. return this;
  124. },
  125. equals: function ( plane ) {
  126. return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
  127. }
  128. } );
  129. export { Plane };
粤ICP备19079148号