retargetClip static method
dynamic
retargetClip(
- dynamic target,
- dynamic source,
- dynamic clip, [
- dynamic options,
Implementation
static retargetClip(target, source, clip, [options]) {
options = options ?? {};
options.useFirstFramePosition = options.useFirstFramePosition ?? false;
options.fps = options.fps ?? 30;
options.names = options.names ?? [];
if (!source.isObject3D) {
source = getHelperFromSkeleton(source);
}
var numFrames = Math.round(clip.duration * (options.fps / 1000) * 1000),
delta = 1 / options.fps,
convertedTracks = <KeyframeTrack>[],
mixer = AnimationMixer(source),
bones = getBones(target.skeleton),
boneDatas = [];
var positionOffset, bone, boneTo, boneData, name;
mixer.clipAction(clip)?.play();
mixer.update(0);
source.updateMatrixWorld();
for (var i = 0; i < numFrames; ++i) {
var time = i * delta;
retarget(target, source, options);
for (var j = 0; j < bones.length; ++j) {
name = options.names[bones[j].name] || bones[j].name;
boneTo = getBoneByName(name, source.skeleton);
if (boneTo) {
bone = bones[j];
boneData = boneDatas[j] = boneDatas[j] ?? {"bone": bone};
if (options.hip == name) {
if (!boneData.pos) {
boneData.pos = {"times": Float32Array(numFrames), "values": Float32Array(numFrames * 3)};
}
if (options.useFirstFramePosition) {
if (i == 0) {
positionOffset = bone.position.clone();
}
bone.position.sub(positionOffset);
}
boneData.pos.times[i] = time;
bone.position.toArray(boneData.pos.values, i * 3);
}
if (!boneData.quat) {
boneData.quat = {"times": Float32Array(numFrames), "values": Float32Array(numFrames * 4)};
}
boneData.quat.times[i] = time;
bone.quaternion.toArray(boneData.quat.values, i * 4);
}
}
mixer.update(delta);
source.updateMatrixWorld();
}
for (var i = 0; i < boneDatas.length; ++i) {
boneData = boneDatas[i];
if (boneData) {
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);
}