Fix 2 bugs with scale of position tracks in rest fixer
Both bugs were related to how position animation tracks were adjusted in rest fixer. First bug: motion scale is applied before subtracting the origin when applying bone roll Second bug: armature scale was lost when converting basis to quaternion, leading an unscaled position offset to be added to the scaled origin.
This commit is contained in:
parent
29b3d9e9e5
commit
00cf862b54
|
@ -436,42 +436,6 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
||||||
src_skeleton->set_motion_scale(motion_scale);
|
src_skeleton->set_motion_scale(motion_scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
|
|
||||||
while (nodes.size()) {
|
|
||||||
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
|
|
||||||
List<StringName> anims;
|
|
||||||
ap->get_animation_list(&anims);
|
|
||||||
for (const StringName &name : anims) {
|
|
||||||
Ref<Animation> anim = ap->get_animation(name);
|
|
||||||
int track_len = anim->get_track_count();
|
|
||||||
for (int i = 0; i < track_len; i++) {
|
|
||||||
if (anim->track_get_path(i).get_subname_count() != 1 || anim->track_get_type(i) != Animation::TYPE_POSITION_3D) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (anim->track_is_compressed(i)) {
|
|
||||||
continue; // Shouldn't occur in internal_process().
|
|
||||||
}
|
|
||||||
|
|
||||||
String track_path = String(anim->track_get_path(i).get_concatenated_names());
|
|
||||||
Node *node = (ap->get_node(ap->get_root_node()))->get_node(NodePath(track_path));
|
|
||||||
ERR_CONTINUE(!node);
|
|
||||||
|
|
||||||
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
|
||||||
if (!track_skeleton || track_skeleton != src_skeleton) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
real_t mlt = 1 / src_skeleton->get_motion_scale();
|
|
||||||
int key_len = anim->track_get_key_count(i);
|
|
||||||
for (int j = 0; j < key_len; j++) {
|
|
||||||
Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j));
|
|
||||||
anim->track_set_key_value(i, j, pos * mlt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overwrite axis.
|
// Overwrite axis.
|
||||||
|
@ -587,22 +551,24 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
||||||
anim->track_set_key_value(i, j, new_pg_q.inverse() * old_pg_q * qt * old_rest_q.inverse() * old_pg_q.inverse() * new_pg_q * new_rest_q);
|
anim->track_set_key_value(i, j, new_pg_q.inverse() * old_pg_q * qt * old_rest_q.inverse() * old_pg_q.inverse() * new_pg_q * new_rest_q);
|
||||||
}
|
}
|
||||||
} else if (anim->track_get_type(i) == Animation::TYPE_SCALE_3D) {
|
} else if (anim->track_get_type(i) == Animation::TYPE_SCALE_3D) {
|
||||||
Basis old_rest_b = old_rest.basis;
|
Basis old_rest_b_inv = old_rest.basis.inverse();
|
||||||
Basis new_rest_b = new_rest.basis;
|
Basis new_rest_b = new_rest.basis;
|
||||||
Basis old_pg_b = old_pg.basis;
|
Basis old_pg_b = old_pg.basis;
|
||||||
Basis new_pg_b = new_pg.basis;
|
Basis new_pg_b = new_pg.basis;
|
||||||
|
Basis old_pg_b_inv = old_pg.basis.inverse();
|
||||||
|
Basis new_pg_b_inv = new_pg.basis.inverse();
|
||||||
for (int j = 0; j < key_len; j++) {
|
for (int j = 0; j < key_len; j++) {
|
||||||
Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j)));
|
Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j)));
|
||||||
anim->track_set_key_value(i, j, (new_pg_b.inverse() * old_pg_b * sc * old_rest_b.inverse() * old_pg_b.inverse() * new_pg_b * new_rest_b).get_scale());
|
anim->track_set_key_value(i, j, (new_pg_b_inv * old_pg_b * sc * old_rest_b_inv * old_pg_b_inv * new_pg_b * new_rest_b).get_scale());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Vector3 old_rest_o = old_rest.origin;
|
Vector3 old_rest_o = old_rest.origin;
|
||||||
Vector3 new_rest_o = new_rest.origin;
|
Vector3 new_rest_o = new_rest.origin;
|
||||||
Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion();
|
Basis old_pg_b = old_pg.basis;
|
||||||
Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion();
|
Basis new_pg_b = new_pg.basis;
|
||||||
for (int j = 0; j < key_len; j++) {
|
for (int j = 0; j < key_len; j++) {
|
||||||
Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
|
Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
|
||||||
anim->track_set_key_value(i, j, new_pg_q.xform_inv(old_pg_q.xform(ps - old_rest_o)) + new_rest_o);
|
anim->track_set_key_value(i, j, new_pg_b.xform_inv(old_pg_b.xform(ps - old_rest_o)) + new_rest_o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -637,6 +603,45 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
||||||
is_rest_changed = true;
|
is_rest_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scale position tracks by motion scale if normalize position tracks.
|
||||||
|
if (bool(p_options["retarget/rest_fixer/normalize_position_tracks"])) {
|
||||||
|
TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
|
||||||
|
while (nodes.size()) {
|
||||||
|
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
|
||||||
|
List<StringName> anims;
|
||||||
|
ap->get_animation_list(&anims);
|
||||||
|
for (const StringName &name : anims) {
|
||||||
|
Ref<Animation> anim = ap->get_animation(name);
|
||||||
|
int track_len = anim->get_track_count();
|
||||||
|
for (int i = 0; i < track_len; i++) {
|
||||||
|
if (anim->track_get_path(i).get_subname_count() != 1 || anim->track_get_type(i) != Animation::TYPE_POSITION_3D) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anim->track_is_compressed(i)) {
|
||||||
|
continue; // Shouldn't occur in internal_process().
|
||||||
|
}
|
||||||
|
|
||||||
|
String track_path = String(anim->track_get_path(i).get_concatenated_names());
|
||||||
|
Node *node = (ap->get_node(ap->get_root_node()))->get_node(NodePath(track_path));
|
||||||
|
ERR_CONTINUE(!node);
|
||||||
|
|
||||||
|
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
||||||
|
if (!track_skeleton || track_skeleton != src_skeleton) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
real_t mlt = 1 / src_skeleton->get_motion_scale();
|
||||||
|
int key_len = anim->track_get_key_count(i);
|
||||||
|
for (int j = 0; j < key_len; j++) {
|
||||||
|
Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j));
|
||||||
|
anim->track_set_key_value(i, j, pos * mlt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (is_rest_changed) {
|
if (is_rest_changed) {
|
||||||
// Fix skin.
|
// Fix skin.
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue