retargetClip static method
dynamic
retargetClip(
- dynamic target,
- dynamic source,
- AnimationClip clip, [
- SkeletonUtilsOptions? options,
Implementation
static retargetClip(target, source, AnimationClip clip, [SkeletonUtilsOptions? options]) {
options = options ?? SkeletonUtilsOptions();
options.useFirstFramePosition = options.useFirstFramePosition;
options.fps = options.fps;
options.names = options.names;
if (source is! Object3D) {
source = getHelperFromSkeleton(source);
}
final numFrames = (clip.duration * (options.fps / 1000) * 1000).round(),
delta = 1 / options.fps,
convertedTracks = <KeyframeTrack>[],
mixer = AnimationMixer(source),
bones = getBones(target.skeleton),
boneDatas = [];
Vector3? positionOffset;
Bone? bone, boneTo;
Map? boneData;
String name;
mixer.clipAction(clip)?.play();
mixer.update(0);
source.updateMatrixWorld();
for (int i = 0; i < numFrames; ++i) {
double time = i * delta;
retarget(target, source, options);
for (int j = 0; j < bones.length; ++j) {
name = options.names[bones[j].name] ?? bones[j].name;
boneTo = getBoneFromSkeleton(name, source.skeleton!);
if (boneTo != null) {
bone = bones[j];
boneData = boneDatas[j] = boneDatas[j] ?? {"bone": bone};
if (options.hip == name) {
if (boneData!['pos'] == null) {
boneData['pos'] = {"times": Float32List(numFrames), "values": Float32List(numFrames * 3)};
}
if (options.useFirstFramePosition) {
if (i == 0) {
positionOffset = bone.position.clone();
}
bone.position.sub(positionOffset!);
}
boneData['pos']['times'][i] = time;
bone.position.copyIntoArray(boneData['pos']['values'], i * 3);
}
if (boneData!['quat'] == null) {
boneData['quat'] = {"times": Float32List(numFrames), "values": Float32List(numFrames * 4)};
}
boneData['quat']['times'][i] = time;
bone.quaternion.toArray(boneData['quat']['values'], i * 4);
}
}
mixer.update(delta);
source.updateMatrixWorld();
}
for (int i = 0; i < boneDatas.length; ++i) {
boneData = boneDatas[i];
if (boneData != null) {
if (boneData['pos']) {
convertedTracks.add(VectorKeyframeTrack('.bones[${boneData['bone']['name']}].position', boneData['pos']['times'], boneData['pos']['values'], null));
}
convertedTracks.add(QuaternionKeyframeTrack('.bones[${boneData['bone']['name']}].quaternion', boneData['quat']['times'], boneData['quat']['values'], null));
}
}
mixer.uncacheAction(clip);
return AnimationClip(clip.name, -1, convertedTracks);
}