retarget static method
Implementation
static void retarget(Object3D target, source, [SkeletonUtilsOptions? options]) {
final quat = Quaternion(),
scale = Vector3(),
relativeMatrix = Matrix4(),
globalMatrix = Matrix4();
options ??= SkeletonUtilsOptions();
List<Bone> sourceBones = source is Object3D ? (source.skeleton?.bones ?? []) : getBones(source);
List<Bone> bones = target.skeleton?.bones ?? [];
Bone bone;
String? name;
Bone? boneTo;
List<Vector3> bonesPosition = [];
// reset bones
// if (target is Object3D) {
target.skeleton?.pose();
// }
// else {
// options.useTargetMatrix = true;
// options.preserveMatrix = false;
// }
if ( options.preserveBonePositions ) {
bonesPosition = [];
for (int i = 0; i < bones.length; i ++ ) {
bonesPosition.add( bones[ i ].position.clone() );
}
}
if ( options.preserveBoneMatrix ) {
target.updateMatrixWorld();
target.matrixWorld.identity();
for (int i = 0; i < target.children.length; ++ i ) {
target.children[ i ].updateMatrixWorld( true );
}
}
for (int i = 0; i < bones.length; ++ i ) {
bone = bones[ i ];
name = getBoneName( bone, options );
boneTo = getBoneByNameList( name!, sourceBones );
globalMatrix.setFrom( bone.matrixWorld );
if ( boneTo != null) {
boneTo.updateMatrixWorld();
if ( options.useTargetMatrix ) {
relativeMatrix.setFrom( boneTo.matrixWorld );
}
else {
relativeMatrix.setFrom( target.matrixWorld ).invert();
relativeMatrix.multiply( boneTo.matrixWorld );
}
// ignore scale to extract rotation
scale.setFromMatrixScale( relativeMatrix );
relativeMatrix.scaleByVector( scale.setValues( 1 / scale.x, 1 / scale.y, 1 / scale.z ) );
// apply to global matrix
globalMatrix.makeRotationFromQuaternion( quat.setFromRotationMatrix( relativeMatrix ) );
//if ( target is Object3D ) {
if ( options.localOffsets != null) {
if ( options.localOffsets![ bone.name ] ) {
globalMatrix.multiply( options.localOffsets![ bone.name ] );
}
}
//}
globalMatrix.copyPosition( relativeMatrix );
}
if ( name == options.hip ) {
globalMatrix.storage[ 12 ] *= options.scale * options.hipInfluence.x;
globalMatrix.storage[ 13 ] *= options.scale * options.hipInfluence.y;
globalMatrix.storage[ 14 ] *= options.scale * options.hipInfluence.z;
if ( options.hipPosition != null ) {
globalMatrix.storage[ 12 ] += options.hipPosition!.x * options.scale;
globalMatrix.storage[ 13 ] += options.hipPosition!.y * options.scale;
globalMatrix.storage[ 14 ] += options.hipPosition!.z * options.scale;
}
}
if ( bone.parent != null) {
bone.matrix.setFrom( bone.parent!.matrixWorld ).invert();
bone.matrix.multiply( globalMatrix );
} else {
bone.matrix.setFrom( globalMatrix );
}
bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
bone.updateMatrixWorld();
}
if ( options.preserveBonePositions ) {
for (int i = 0; i < bones.length; ++ i ) {
bone = bones[ i ];
name = getBoneName( bone, options ) ?? bone.name;
if ( name != options.hip ) {
bone.position.setFrom( bonesPosition[ i ] );
}
}
}
if ( options.preserveBoneMatrix ) {
target.updateMatrixWorld( true );
}
}