Plane.js 4.4 KB

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