SkinnedMesh.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import { Mesh } from './Mesh.js';
  2. import { Box3 } from '../math/Box3.js';
  3. import { Matrix4 } from '../math/Matrix4.js';
  4. import { Sphere } from '../math/Sphere.js';
  5. import { Vector3 } from '../math/Vector3.js';
  6. import { Vector4 } from '../math/Vector4.js';
  7. import { Ray } from '../math/Ray.js';
  8. const _basePosition = /*@__PURE__*/ new Vector3();
  9. const _skinIndex = /*@__PURE__*/ new Vector4();
  10. const _skinWeight = /*@__PURE__*/ new Vector4();
  11. const _vector3 = /*@__PURE__*/ new Vector3();
  12. const _matrix4 = /*@__PURE__*/ new Matrix4();
  13. const _vertex = /*@__PURE__*/ new Vector3();
  14. const _sphere = /*@__PURE__*/ new Sphere();
  15. const _inverseMatrix = /*@__PURE__*/ new Matrix4();
  16. const _ray = /*@__PURE__*/ new Ray();
  17. class SkinnedMesh extends Mesh {
  18. constructor( geometry, material ) {
  19. super( geometry, material );
  20. this.isSkinnedMesh = true;
  21. this.type = 'SkinnedMesh';
  22. this.bindMode = 'attached';
  23. this.bindMatrix = new Matrix4();
  24. this.bindMatrixInverse = new Matrix4();
  25. this.boundingBox = null;
  26. this.boundingSphere = null;
  27. }
  28. computeBoundingBox() {
  29. const geometry = this.geometry;
  30. if ( this.boundingBox === null ) {
  31. this.boundingBox = new Box3();
  32. }
  33. this.boundingBox.makeEmpty();
  34. const positionAttribute = geometry.getAttribute( 'position' );
  35. for ( let i = 0; i < positionAttribute.count; i ++ ) {
  36. _vertex.fromBufferAttribute( positionAttribute, i );
  37. this.applyBoneTransform( i, _vertex );
  38. this.boundingBox.expandByPoint( _vertex );
  39. }
  40. }
  41. computeBoundingSphere() {
  42. const geometry = this.geometry;
  43. if ( this.boundingSphere === null ) {
  44. this.boundingSphere = new Sphere();
  45. }
  46. this.boundingSphere.makeEmpty();
  47. const positionAttribute = geometry.getAttribute( 'position' );
  48. for ( let i = 0; i < positionAttribute.count; i ++ ) {
  49. _vertex.fromBufferAttribute( positionAttribute, i );
  50. this.applyBoneTransform( i, _vertex );
  51. this.boundingSphere.expandByPoint( _vertex );
  52. }
  53. }
  54. copy( source, recursive ) {
  55. super.copy( source, recursive );
  56. this.bindMode = source.bindMode;
  57. this.bindMatrix.copy( source.bindMatrix );
  58. this.bindMatrixInverse.copy( source.bindMatrixInverse );
  59. this.skeleton = source.skeleton;
  60. if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone();
  61. if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone();
  62. return this;
  63. }
  64. raycast( raycaster, intersects ) {
  65. const material = this.material;
  66. const matrixWorld = this.matrixWorld;
  67. if ( material === undefined ) return;
  68. // test with bounding sphere in world space
  69. if ( this.boundingSphere === null ) this.computeBoundingSphere();
  70. _sphere.copy( this.boundingSphere );
  71. _sphere.applyMatrix4( matrixWorld );
  72. if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
  73. // convert ray to local space of skinned mesh
  74. _inverseMatrix.copy( matrixWorld ).invert();
  75. _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
  76. // test with bounding box in local space
  77. if ( this.boundingBox !== null ) {
  78. if ( _ray.intersectsBox( this.boundingBox ) === false ) return;
  79. }
  80. // test for intersections with geometry
  81. this._computeIntersections( raycaster, intersects, _ray );
  82. }
  83. getVertexPosition( index, target ) {
  84. super.getVertexPosition( index, target );
  85. this.applyBoneTransform( index, target );
  86. return target;
  87. }
  88. bind( skeleton, bindMatrix ) {
  89. this.skeleton = skeleton;
  90. if ( bindMatrix === undefined ) {
  91. this.updateMatrixWorld( true );
  92. this.skeleton.calculateInverses();
  93. bindMatrix = this.matrixWorld;
  94. }
  95. this.bindMatrix.copy( bindMatrix );
  96. this.bindMatrixInverse.copy( bindMatrix ).invert();
  97. }
  98. pose() {
  99. this.skeleton.pose();
  100. }
  101. normalizeSkinWeights() {
  102. const vector = new Vector4();
  103. const skinWeight = this.geometry.attributes.skinWeight;
  104. for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
  105. vector.fromBufferAttribute( skinWeight, i );
  106. const scale = 1.0 / vector.manhattanLength();
  107. if ( scale !== Infinity ) {
  108. vector.multiplyScalar( scale );
  109. } else {
  110. vector.set( 1, 0, 0, 0 ); // do something reasonable
  111. }
  112. skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
  113. }
  114. }
  115. updateMatrixWorld( force ) {
  116. super.updateMatrixWorld( force );
  117. if ( this.bindMode === 'attached' ) {
  118. this.bindMatrixInverse.copy( this.matrixWorld ).invert();
  119. } else if ( this.bindMode === 'detached' ) {
  120. this.bindMatrixInverse.copy( this.bindMatrix ).invert();
  121. } else {
  122. console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
  123. }
  124. }
  125. applyBoneTransform( index, vector ) {
  126. const skeleton = this.skeleton;
  127. const geometry = this.geometry;
  128. _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
  129. _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
  130. _basePosition.copy( vector ).applyMatrix4( this.bindMatrix );
  131. vector.set( 0, 0, 0 );
  132. for ( let i = 0; i < 4; i ++ ) {
  133. const weight = _skinWeight.getComponent( i );
  134. if ( weight !== 0 ) {
  135. const boneIndex = _skinIndex.getComponent( i );
  136. _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
  137. vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight );
  138. }
  139. }
  140. return vector.applyMatrix4( this.bindMatrixInverse );
  141. }
  142. boneTransform( index, vector ) { // @deprecated, r151
  143. console.warn( 'THREE.SkinnedMesh: .boneTransform() was renamed to .applyBoneTransform() in r151.' );
  144. return this.applyBoneTransform( index, vector );
  145. }
  146. }
  147. export { SkinnedMesh };
粤ICP备19079148号