Triangle.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. import { Vector3 } from './Vector3.js';
  2. /**
  3. * @author bhouston / http://clara.io
  4. * @author mrdoob / http://mrdoob.com/
  5. */
  6. var _v0 = new Vector3();
  7. var _v1 = new Vector3();
  8. var _v2 = new Vector3();
  9. var _v3 = new Vector3();
  10. var _vab = new Vector3();
  11. var _vac = new Vector3();
  12. var _vbc = new Vector3();
  13. var _vap = new Vector3();
  14. var _vbp = new Vector3();
  15. var _vcp = new Vector3();
  16. function Triangle( a, b, c ) {
  17. this.a = ( a !== undefined ) ? a : new Vector3();
  18. this.b = ( b !== undefined ) ? b : new Vector3();
  19. this.c = ( c !== undefined ) ? c : new Vector3();
  20. }
  21. Object.assign( Triangle, {
  22. getNormal: function ( a, b, c, target ) {
  23. if ( target === undefined ) {
  24. console.warn( 'THREE.Triangle: .getNormal() target is now required' );
  25. target = new Vector3();
  26. }
  27. target.subVectors( c, b );
  28. _v0.subVectors( a, b );
  29. target.cross( _v0 );
  30. var targetLengthSq = target.lengthSq();
  31. if ( targetLengthSq > 0 ) {
  32. return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
  33. }
  34. return target.set( 0, 0, 0 );
  35. },
  36. // static/instance method to calculate barycentric coordinates
  37. // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
  38. getBarycoord: function ( point, a, b, c, target ) {
  39. _v0.subVectors( c, a );
  40. _v1.subVectors( b, a );
  41. _v2.subVectors( point, a );
  42. var dot00 = _v0.dot( _v0 );
  43. var dot01 = _v0.dot( _v1 );
  44. var dot02 = _v0.dot( _v2 );
  45. var dot11 = _v1.dot( _v1 );
  46. var dot12 = _v1.dot( _v2 );
  47. var denom = ( dot00 * dot11 - dot01 * dot01 );
  48. if ( target === undefined ) {
  49. console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
  50. target = new Vector3();
  51. }
  52. // collinear or singular triangle
  53. if ( denom === 0 ) {
  54. // arbitrary location outside of triangle?
  55. // not sure if this is the best idea, maybe should be returning undefined
  56. return target.set( - 2, - 1, - 1 );
  57. }
  58. var invDenom = 1 / denom;
  59. var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
  60. var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
  61. // barycentric coordinates must always sum to 1
  62. return target.set( 1 - u - v, v, u );
  63. },
  64. containsPoint: function ( point, a, b, c ) {
  65. Triangle.getBarycoord( point, a, b, c, _v3 );
  66. return ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );
  67. },
  68. getUV: function ( point, p1, p2, p3, uv1, uv2, uv3, target ) {
  69. this.getBarycoord( point, p1, p2, p3, _v3 );
  70. target.set( 0, 0 );
  71. target.addScaledVector( uv1, _v3.x );
  72. target.addScaledVector( uv2, _v3.y );
  73. target.addScaledVector( uv3, _v3.z );
  74. return target;
  75. },
  76. isFrontFacing: function ( a, b, c, direction ) {
  77. _v0.subVectors( c, b );
  78. _v1.subVectors( a, b );
  79. // strictly front facing
  80. return ( _v0.cross( _v1 ).dot( direction ) < 0 ) ? true : false;
  81. }
  82. } );
  83. Object.assign( Triangle.prototype, {
  84. set: function ( a, b, c ) {
  85. this.a.copy( a );
  86. this.b.copy( b );
  87. this.c.copy( c );
  88. return this;
  89. },
  90. setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
  91. this.a.copy( points[ i0 ] );
  92. this.b.copy( points[ i1 ] );
  93. this.c.copy( points[ i2 ] );
  94. return this;
  95. },
  96. clone: function () {
  97. return new this.constructor().copy( this );
  98. },
  99. copy: function ( triangle ) {
  100. this.a.copy( triangle.a );
  101. this.b.copy( triangle.b );
  102. this.c.copy( triangle.c );
  103. return this;
  104. },
  105. getArea: function () {
  106. _v0.subVectors( this.c, this.b );
  107. _v1.subVectors( this.a, this.b );
  108. return _v0.cross( _v1 ).length() * 0.5;
  109. },
  110. getMidpoint: function ( target ) {
  111. if ( target === undefined ) {
  112. console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
  113. target = new Vector3();
  114. }
  115. return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
  116. },
  117. getNormal: function ( target ) {
  118. return Triangle.getNormal( this.a, this.b, this.c, target );
  119. },
  120. getPlane: function ( target ) {
  121. if ( target === undefined ) {
  122. console.warn( 'THREE.Triangle: .getPlane() target is now required' );
  123. target = new Vector3();
  124. }
  125. return target.setFromCoplanarPoints( this.a, this.b, this.c );
  126. },
  127. getBarycoord: function ( point, target ) {
  128. return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
  129. },
  130. getUV: function ( point, uv1, uv2, uv3, target ) {
  131. return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );
  132. },
  133. containsPoint: function ( point ) {
  134. return Triangle.containsPoint( point, this.a, this.b, this.c );
  135. },
  136. isFrontFacing: function ( direction ) {
  137. return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
  138. },
  139. intersectsBox: function ( box ) {
  140. return box.intersectsTriangle( this );
  141. },
  142. closestPointToPoint: function ( p, target ) {
  143. if ( target === undefined ) {
  144. console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
  145. target = new Vector3();
  146. }
  147. var a = this.a, b = this.b, c = this.c;
  148. var v, w;
  149. // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
  150. // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
  151. // under the accompanying license; see chapter 5.1.5 for detailed explanation.
  152. // basically, we're distinguishing which of the voronoi regions of the triangle
  153. // the point lies in with the minimum amount of redundant computation.
  154. _vab.subVectors( b, a );
  155. _vac.subVectors( c, a );
  156. _vap.subVectors( p, a );
  157. var d1 = _vab.dot( _vap );
  158. var d2 = _vac.dot( _vap );
  159. if ( d1 <= 0 && d2 <= 0 ) {
  160. // vertex region of A; barycentric coords (1, 0, 0)
  161. return target.copy( a );
  162. }
  163. _vbp.subVectors( p, b );
  164. var d3 = _vab.dot( _vbp );
  165. var d4 = _vac.dot( _vbp );
  166. if ( d3 >= 0 && d4 <= d3 ) {
  167. // vertex region of B; barycentric coords (0, 1, 0)
  168. return target.copy( b );
  169. }
  170. var vc = d1 * d4 - d3 * d2;
  171. if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
  172. v = d1 / ( d1 - d3 );
  173. // edge region of AB; barycentric coords (1-v, v, 0)
  174. return target.copy( a ).addScaledVector( _vab, v );
  175. }
  176. _vcp.subVectors( p, c );
  177. var d5 = _vab.dot( _vcp );
  178. var d6 = _vac.dot( _vcp );
  179. if ( d6 >= 0 && d5 <= d6 ) {
  180. // vertex region of C; barycentric coords (0, 0, 1)
  181. return target.copy( c );
  182. }
  183. var vb = d5 * d2 - d1 * d6;
  184. if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
  185. w = d2 / ( d2 - d6 );
  186. // edge region of AC; barycentric coords (1-w, 0, w)
  187. return target.copy( a ).addScaledVector( _vac, w );
  188. }
  189. var va = d3 * d6 - d5 * d4;
  190. if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
  191. _vbc.subVectors( c, b );
  192. w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
  193. // edge region of BC; barycentric coords (0, 1-w, w)
  194. return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
  195. }
  196. // face region
  197. var denom = 1 / ( va + vb + vc );
  198. // u = va * denom
  199. v = vb * denom;
  200. w = vc * denom;
  201. return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
  202. },
  203. equals: function ( triangle ) {
  204. return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
  205. }
  206. } );
  207. export { Triangle };