Triangle.js 6.9 KB

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