THREE.js Запекание позы скелета - преобразование позы A в позу T
Я создаю импортер DAZ и пытаюсь заставить экспорт A-позы по умолчанию работать с моей коллекцией анимаций T-позы. Вот что я делаю:
- Экспорт персонажа в DAZ с настройками по умолчанию и загрузка в Three.js
- Применение переопределений вращения костей, т.е. lShldrBend{x: -1, y: 0, z: 0.8}
- Запуск сценария выпечки, который работает аналогично STLExporter (код ниже)
- Теперь персонаж правильно выглядит в позе T, а все вращения равны 0,0,0. Это хорошо.
НО вот проблема(руки и их дети):
Детские кости измененной кости становятся все перепутанными. Что мне нужно сделать? Вот мой скелетный скрипт для выпечки (упрощено, нормали опущены)
function bakeSkeleton ( target ) {
var v1 = new Vector3();
target.traverse( function ( object ) {
if ( !object.isSkinnedMesh ) return;
if ( object.geometry.isBufferGeometry !== true ) throw new Error( 'Only BufferGeometry supported.' );
var positionAttribute = object.geometry.getAttribute( 'position' );
for ( var j = 0; j < positionAttribute.count; j++ ) {
object.boneTransform( j, v1 );
positionAttribute.setXYZ( j, v1.x, v1.y, v1.z);
}
positionAttribute.needsUpdate = true;
// commented out stuff is where I tried to apply rotation matrix to children's inverse matrices
// const orgUninverse = new Matrix4();
// const q1 = new Quaternion();
// const mat = new Matrix4();
// const inverse = new Matrix4();
object.skeleton.bones.forEach((bone, i) => {
// q1.copy(bone.quaternion)
// mat.makeRotationFromQuaternion(q1)
bone.rotation.set(0,0,0);
// bone.updateMatrix();
// bone.children.forEach(child => {
// const bid = object.skeleton.bones.indexOf(child)
// if (bid === -1) {
// console.log('bone not in skeleton', child.name)
// return
// }
// console.log('bone fond', child.name)
// orgUninverse.getInverse(object.skeleton.boneInverses[bid])
// orgUninverse.multiply(mat.makeRotationFromQuaternion(q1))
// object.skeleton.boneInverses[bid].getInverse(orgUninverse);
// })
})
} );
}
Обновлять
Я обнаружил, что гораздо более простой способ изменить позу — применить заслуженные повороты (но перевернутые) и вызвать скелет.calculateInverses(). Поза применяется правильно, и все повороты равны 0,0,0, но снова во время анимации возникает та же проблема, что и на картинке.