In order to export a posed character with both animations and morph targets applied, I am using the following algorithm. It works once, but the second time the export is deformed. The weird thing is that my object in the scene is not affected at all following this procedure. I can’t figure out what is being affected. I have also tried copying the scene using (https://gist.github.com/cdata/f2d7a6ccdec071839bc1954c32595e87) and running the export on the cloned scene but I’m still getting issues.
createPosedClone = (skinnedMesh) => {
let clone = skinnedMesh.clone();
var boneMatrices = this.skeleton.boneMatrices;
var geometry = skinnedMesh.geometry;
var position = geometry.attributes.position;
var skinIndex = geometry.attributes.skinIndex;
var skinWeight = geometry.attributes.skinWeight;
var bindMatrix = skinnedMesh.bindMatrix;
var bindMatrixInverse = skinnedMesh.bindMatrixInverse;
var i, j, si, sw;
var vertex = new THREE.Vector3();
var temp = new THREE.Vector3();
var skinned = new THREE.Vector3();
var skinIndices = new THREE.Vector4();
var skinWeights = new THREE.Vector4();
var boneMatrix = new THREE.Matrix4();
// non-indexed geometry
for ( i = 0; i < position.count; i++ ) {
vertex.fromBufferAttribute( position, i );
skinIndices.fromBufferAttribute( skinIndex, i );
skinWeights.fromBufferAttribute( skinWeight, i );
// the following code section is normally implemented in the vertex shader
vertex.applyMatrix4( bindMatrix ); // transform to bind space
skinned.set( 0, 0, 0 );
for ( j = 0; j < 4; j ++ ) {
si = skinIndices.getComponent( j );
sw = skinWeights.getComponent( j );
boneMatrix.fromArray( boneMatrices, si * 16 );
// weighted vertex transformation
temp.copy( vertex ).applyMatrix4( boneMatrix ).multiplyScalar( sw );
skinned.add( temp );
}
skinned.applyMatrix4( bindMatrixInverse ); // back to local space
// change the position of the object
var morphTargetArray = clone.geometry.morphAttributes.position;
var morphInfluences = clone.morphTargetInfluences;
var meshVertices = clone.geometry.attributes.position;
var vA = new THREE.Vector3();
var tempA = new THREE.Vector3();
var target = new THREE.Vector3();
var vertices = new THREE.Vector3();
vertices.fromBufferAttribute(meshVertices, i); // the vertex to transform
if(morphTargetArray){
for ( var t = 0; t < morphTargetArray.length; t++ ) {
var influence = morphInfluences[ t ];
if ( influence === 0 ) continue;
target.fromBufferAttribute( morphTargetArray[t], i);
vA.addScaledVector( tempA.subVectors( target, vertices ), influence );
}
}
skinned.add( vA ); // the transformed value
clone.geometry.attributes.position.setXYZ(i, skinned.x, skinned.y, skinned.z);
}
//now iterate over all
return clone;
}