Mesh.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. import { Vector3 } from '../math/Vector3.js';
  2. import { Vector2 } from '../math/Vector2.js';
  3. import { Sphere } from '../math/Sphere.js';
  4. import { Ray } from '../math/Ray.js';
  5. import { Matrix4 } from '../math/Matrix4.js';
  6. import { Object3D } from '../core/Object3D.js';
  7. import { Triangle } from '../math/Triangle.js';
  8. import { BackSide, FrontSide } from '../constants.js';
  9. import { MeshBasicMaterial } from '../materials/MeshBasicMaterial.js';
  10. import { BufferGeometry } from '../core/BufferGeometry.js';
  11. const _inverseMatrix = /*@__PURE__*/ new Matrix4();
  12. const _ray = /*@__PURE__*/ new Ray();
  13. const _sphere = /*@__PURE__*/ new Sphere();
  14. const _sphereHitAt = /*@__PURE__*/ new Vector3();
  15. const _vA = /*@__PURE__*/ new Vector3();
  16. const _vB = /*@__PURE__*/ new Vector3();
  17. const _vC = /*@__PURE__*/ new Vector3();
  18. const _tempA = /*@__PURE__*/ new Vector3();
  19. const _morphA = /*@__PURE__*/ new Vector3();
  20. const _intersectionPoint = /*@__PURE__*/ new Vector3();
  21. const _intersectionPointWorld = /*@__PURE__*/ new Vector3();
  22. class Mesh extends Object3D {
  23. constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
  24. super();
  25. this.isMesh = true;
  26. this.type = 'Mesh';
  27. this.geometry = geometry;
  28. this.material = material;
  29. this.updateMorphTargets();
  30. }
  31. copy( source, recursive ) {
  32. super.copy( source, recursive );
  33. if ( source.morphTargetInfluences !== undefined ) {
  34. this.morphTargetInfluences = source.morphTargetInfluences.slice();
  35. }
  36. if ( source.morphTargetDictionary !== undefined ) {
  37. this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
  38. }
  39. this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
  40. this.geometry = source.geometry;
  41. return this;
  42. }
  43. updateMorphTargets() {
  44. const geometry = this.geometry;
  45. const morphAttributes = geometry.morphAttributes;
  46. const keys = Object.keys( morphAttributes );
  47. if ( keys.length > 0 ) {
  48. const morphAttribute = morphAttributes[ keys[ 0 ] ];
  49. if ( morphAttribute !== undefined ) {
  50. this.morphTargetInfluences = [];
  51. this.morphTargetDictionary = {};
  52. for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
  53. const name = morphAttribute[ m ].name || String( m );
  54. this.morphTargetInfluences.push( 0 );
  55. this.morphTargetDictionary[ name ] = m;
  56. }
  57. }
  58. }
  59. }
  60. getVertexPosition( index, target ) {
  61. const geometry = this.geometry;
  62. const position = geometry.attributes.position;
  63. const morphPosition = geometry.morphAttributes.position;
  64. const morphTargetsRelative = geometry.morphTargetsRelative;
  65. target.fromBufferAttribute( position, index );
  66. const morphInfluences = this.morphTargetInfluences;
  67. if ( morphPosition && morphInfluences ) {
  68. _morphA.set( 0, 0, 0 );
  69. for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
  70. const influence = morphInfluences[ i ];
  71. const morphAttribute = morphPosition[ i ];
  72. if ( influence === 0 ) continue;
  73. _tempA.fromBufferAttribute( morphAttribute, index );
  74. if ( morphTargetsRelative ) {
  75. _morphA.addScaledVector( _tempA, influence );
  76. } else {
  77. _morphA.addScaledVector( _tempA.sub( target ), influence );
  78. }
  79. }
  80. target.add( _morphA );
  81. }
  82. return target;
  83. }
  84. raycast( raycaster, intersects ) {
  85. const geometry = this.geometry;
  86. const material = this.material;
  87. const matrixWorld = this.matrixWorld;
  88. if ( material === undefined ) return;
  89. // test with bounding sphere in world space
  90. if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
  91. _sphere.copy( geometry.boundingSphere );
  92. _sphere.applyMatrix4( matrixWorld );
  93. // check distance from ray origin to bounding sphere
  94. _ray.copy( raycaster.ray ).recast( raycaster.near );
  95. if ( _sphere.containsPoint( _ray.origin ) === false ) {
  96. if ( _ray.intersectSphere( _sphere, _sphereHitAt ) === null ) return;
  97. if ( _ray.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return;
  98. }
  99. // convert ray to local space of mesh
  100. _inverseMatrix.copy( matrixWorld ).invert();
  101. _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
  102. // test with bounding box in local space
  103. if ( geometry.boundingBox !== null ) {
  104. if ( _ray.intersectsBox( geometry.boundingBox ) === false ) return;
  105. }
  106. // test for intersections with geometry
  107. this._computeIntersections( raycaster, intersects, _ray );
  108. }
  109. _computeIntersections( raycaster, intersects, rayLocalSpace ) {
  110. let intersection;
  111. const geometry = this.geometry;
  112. const material = this.material;
  113. const index = geometry.index;
  114. const position = geometry.attributes.position;
  115. const uv = geometry.attributes.uv;
  116. const uv1 = geometry.attributes.uv1;
  117. const normal = geometry.attributes.normal;
  118. const groups = geometry.groups;
  119. const drawRange = geometry.drawRange;
  120. if ( index !== null ) {
  121. // indexed buffer geometry
  122. if ( Array.isArray( material ) ) {
  123. for ( let i = 0, il = groups.length; i < il; i ++ ) {
  124. const group = groups[ i ];
  125. const groupMaterial = material[ group.materialIndex ];
  126. const start = Math.max( group.start, drawRange.start );
  127. const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
  128. for ( let j = start, jl = end; j < jl; j += 3 ) {
  129. const a = index.getX( j );
  130. const b = index.getX( j + 1 );
  131. const c = index.getX( j + 2 );
  132. intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
  133. if ( intersection ) {
  134. intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
  135. intersection.face.materialIndex = group.materialIndex;
  136. intersects.push( intersection );
  137. }
  138. }
  139. }
  140. } else {
  141. const start = Math.max( 0, drawRange.start );
  142. const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
  143. for ( let i = start, il = end; i < il; i += 3 ) {
  144. const a = index.getX( i );
  145. const b = index.getX( i + 1 );
  146. const c = index.getX( i + 2 );
  147. intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
  148. if ( intersection ) {
  149. intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
  150. intersects.push( intersection );
  151. }
  152. }
  153. }
  154. } else if ( position !== undefined ) {
  155. // non-indexed buffer geometry
  156. if ( Array.isArray( material ) ) {
  157. for ( let i = 0, il = groups.length; i < il; i ++ ) {
  158. const group = groups[ i ];
  159. const groupMaterial = material[ group.materialIndex ];
  160. const start = Math.max( group.start, drawRange.start );
  161. const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
  162. for ( let j = start, jl = end; j < jl; j += 3 ) {
  163. const a = j;
  164. const b = j + 1;
  165. const c = j + 2;
  166. intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
  167. if ( intersection ) {
  168. intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
  169. intersection.face.materialIndex = group.materialIndex;
  170. intersects.push( intersection );
  171. }
  172. }
  173. }
  174. } else {
  175. const start = Math.max( 0, drawRange.start );
  176. const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
  177. for ( let i = start, il = end; i < il; i += 3 ) {
  178. const a = i;
  179. const b = i + 1;
  180. const c = i + 2;
  181. intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
  182. if ( intersection ) {
  183. intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
  184. intersects.push( intersection );
  185. }
  186. }
  187. }
  188. }
  189. }
  190. }
  191. function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
  192. let intersect;
  193. if ( material.side === BackSide ) {
  194. intersect = ray.intersectTriangle( pC, pB, pA, true, point );
  195. } else {
  196. intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point );
  197. }
  198. if ( intersect === null ) return null;
  199. _intersectionPointWorld.copy( point );
  200. _intersectionPointWorld.applyMatrix4( object.matrixWorld );
  201. const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
  202. if ( distance < raycaster.near || distance > raycaster.far ) return null;
  203. return {
  204. distance: distance,
  205. point: _intersectionPointWorld.clone(),
  206. object: object
  207. };
  208. }
  209. function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) {
  210. object.getVertexPosition( a, _vA );
  211. object.getVertexPosition( b, _vB );
  212. object.getVertexPosition( c, _vC );
  213. const intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );
  214. if ( intersection ) {
  215. const barycoord = new Vector3();
  216. Triangle.getBarycoord( _intersectionPoint, _vA, _vB, _vC, barycoord );
  217. if ( uv ) {
  218. intersection.uv = Triangle.getInterpolatedAttribute( uv, a, b, c, barycoord, new Vector2() );
  219. }
  220. if ( uv1 ) {
  221. intersection.uv1 = Triangle.getInterpolatedAttribute( uv1, a, b, c, barycoord, new Vector2() );
  222. }
  223. if ( normal ) {
  224. intersection.normal = Triangle.getInterpolatedAttribute( normal, a, b, c, barycoord, new Vector3() );
  225. if ( intersection.normal.dot( ray.direction ) > 0 ) {
  226. intersection.normal.multiplyScalar( - 1 );
  227. }
  228. }
  229. const face = {
  230. a: a,
  231. b: b,
  232. c: c,
  233. normal: new Vector3(),
  234. materialIndex: 0
  235. };
  236. Triangle.getNormal( _vA, _vB, _vC, face.normal );
  237. intersection.face = face;
  238. intersection.barycoord = barycoord;
  239. }
  240. return intersection;
  241. }
  242. export { Mesh };
粤ICP备19079148号