Spaces:
Running
Running
File size: 2,965 Bytes
2b7aae2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | import { Mesh } from './Mesh.js';
import { Matrix4 } from '../math/Matrix4.js';
import { Vector3 } from '../math/Vector3.js';
import { Vector4 } from '../math/Vector4.js';
const _basePosition = /*@__PURE__*/ new Vector3();
const _skinIndex = /*@__PURE__*/ new Vector4();
const _skinWeight = /*@__PURE__*/ new Vector4();
const _vector = /*@__PURE__*/ new Vector3();
const _matrix = /*@__PURE__*/ new Matrix4();
class SkinnedMesh extends Mesh {
constructor(geometry, material) {
super(geometry, material);
this.type = 'SkinnedMesh';
this.bindMode = 'attached';
this.bindMatrix = new Matrix4();
this.bindMatrixInverse = new Matrix4();
}
copy(source) {
super.copy(source);
this.bindMode = source.bindMode;
this.bindMatrix.copy(source.bindMatrix);
this.bindMatrixInverse.copy(source.bindMatrixInverse);
this.skeleton = source.skeleton;
return this;
}
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.x = skinWeight.getX(i);
vector.y = skinWeight.getY(i);
vector.z = skinWeight.getZ(i);
vector.w = skinWeight.getW(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);
}
}
boneTransform(index, target) {
const skeleton = this.skeleton;
const geometry = this.geometry;
_skinIndex.fromBufferAttribute(geometry.attributes.skinIndex, index);
_skinWeight.fromBufferAttribute(geometry.attributes.skinWeight, index);
_basePosition.copy(target).applyMatrix4(this.bindMatrix);
target.set(0, 0, 0);
for (let i = 0; i < 4; i++) {
const weight = _skinWeight.getComponent(i);
if (weight !== 0) {
const boneIndex = _skinIndex.getComponent(i);
_matrix.multiplyMatrices(skeleton.bones[boneIndex].matrixWorld, skeleton.boneInverses[boneIndex]);
target.addScaledVector(_vector.copy(_basePosition).applyMatrix4(_matrix), weight);
}
}
return target.applyMatrix4(this.bindMatrixInverse);
}
}
SkinnedMesh.prototype.isSkinnedMesh = true;
export { SkinnedMesh };
|