Mesh.js 9.7 KB

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