| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- import { Mesh } from './Mesh.js';
- import { Box3 } from '../math/Box3.js';
- import { Matrix4 } from '../math/Matrix4.js';
- import { Sphere } from '../math/Sphere.js';
- import { Vector3 } from '../math/Vector3.js';
- import { Vector4 } from '../math/Vector4.js';
- import { Ray } from '../math/Ray.js';
- const _basePosition = /*@__PURE__*/ new Vector3();
- const _skinIndex = /*@__PURE__*/ new Vector4();
- const _skinWeight = /*@__PURE__*/ new Vector4();
- const _vector3 = /*@__PURE__*/ new Vector3();
- const _matrix4 = /*@__PURE__*/ new Matrix4();
- const _vertex = /*@__PURE__*/ new Vector3();
- const _sphere = /*@__PURE__*/ new Sphere();
- const _inverseMatrix = /*@__PURE__*/ new Matrix4();
- const _ray = /*@__PURE__*/ new Ray();
- class SkinnedMesh extends Mesh {
- constructor( geometry, material ) {
- super( geometry, material );
- this.isSkinnedMesh = true;
- this.type = 'SkinnedMesh';
- this.bindMode = 'attached';
- this.bindMatrix = new Matrix4();
- this.bindMatrixInverse = new Matrix4();
- this.boundingBox = null;
- this.boundingSphere = null;
- }
- computeBoundingBox() {
- const geometry = this.geometry;
- if ( this.boundingBox === null ) {
- this.boundingBox = new Box3();
- }
- this.boundingBox.makeEmpty();
- const positionAttribute = geometry.getAttribute( 'position' );
- for ( let i = 0; i < positionAttribute.count; i ++ ) {
- _vertex.fromBufferAttribute( positionAttribute, i );
- this.applyBoneTransform( i, _vertex );
- this.boundingBox.expandByPoint( _vertex );
- }
- }
- computeBoundingSphere() {
- const geometry = this.geometry;
- if ( this.boundingSphere === null ) {
- this.boundingSphere = new Sphere();
- }
- this.boundingSphere.makeEmpty();
- const positionAttribute = geometry.getAttribute( 'position' );
- for ( let i = 0; i < positionAttribute.count; i ++ ) {
- _vertex.fromBufferAttribute( positionAttribute, i );
- this.applyBoneTransform( i, _vertex );
- this.boundingSphere.expandByPoint( _vertex );
- }
- }
- copy( source, recursive ) {
- super.copy( source, recursive );
- this.bindMode = source.bindMode;
- this.bindMatrix.copy( source.bindMatrix );
- this.bindMatrixInverse.copy( source.bindMatrixInverse );
- this.skeleton = source.skeleton;
- if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone();
- if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone();
- return this;
- }
- raycast( raycaster, intersects ) {
- const material = this.material;
- const matrixWorld = this.matrixWorld;
- if ( material === undefined ) return;
- // test with bounding sphere in world space
- if ( this.boundingSphere === null ) this.computeBoundingSphere();
- _sphere.copy( this.boundingSphere );
- _sphere.applyMatrix4( matrixWorld );
- if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
- // convert ray to local space of skinned mesh
- _inverseMatrix.copy( matrixWorld ).invert();
- _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
- // test with bounding box in local space
- if ( this.boundingBox !== null ) {
- if ( _ray.intersectsBox( this.boundingBox ) === false ) return;
- }
- // test for intersections with geometry
- this._computeIntersections( raycaster, intersects, _ray );
- }
- getVertexPosition( index, target ) {
- super.getVertexPosition( index, target );
- this.applyBoneTransform( index, target );
- return target;
- }
- bind( skeleton, bindMatrix ) {
- this.skeleton = skeleton;
- if ( bindMatrix === undefined ) {
- this.updateMatrixWorld( true );
- this.skeleton.calculateInverses();
- bindMatrix = this.matrixWorld;
- }
- this.bindMatrix.copy( bindMatrix );
- this.bindMatrixInverse.copy( bindMatrix ).invert();
- }
- pose() {
- this.skeleton.pose();
- }
- normalizeSkinWeights() {
- const vector = new Vector4();
- const skinWeight = this.geometry.attributes.skinWeight;
- for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
- vector.fromBufferAttribute( skinWeight, i );
- const scale = 1.0 / vector.manhattanLength();
- if ( scale !== Infinity ) {
- vector.multiplyScalar( scale );
- } else {
- vector.set( 1, 0, 0, 0 ); // do something reasonable
- }
- skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
- }
- }
- updateMatrixWorld( force ) {
- super.updateMatrixWorld( force );
- if ( this.bindMode === 'attached' ) {
- this.bindMatrixInverse.copy( this.matrixWorld ).invert();
- } else if ( this.bindMode === 'detached' ) {
- this.bindMatrixInverse.copy( this.bindMatrix ).invert();
- } else {
- console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
- }
- }
- applyBoneTransform( index, vector ) {
- const skeleton = this.skeleton;
- const geometry = this.geometry;
- _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
- _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
- _basePosition.copy( vector ).applyMatrix4( this.bindMatrix );
- vector.set( 0, 0, 0 );
- for ( let i = 0; i < 4; i ++ ) {
- const weight = _skinWeight.getComponent( i );
- if ( weight !== 0 ) {
- const boneIndex = _skinIndex.getComponent( i );
- _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
- vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight );
- }
- }
- return vector.applyMatrix4( this.bindMatrixInverse );
- }
- boneTransform( index, vector ) { // @deprecated, r151
- console.warn( 'THREE.SkinnedMesh: .boneTransform() was renamed to .applyBoneTransform() in r151.' );
- return this.applyBoneTransform( index, vector );
- }
- }
- export { SkinnedMesh };
|