Merge pull request #63662 from TokageItLab/fix-silhouetter-for-rotated-skel
This commit is contained in:
commit
5a2dde51c0
1 changed files with 130 additions and 27 deletions
|
@ -38,6 +38,7 @@
|
|||
|
||||
void PostImportPluginSkeletonRestFixer::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) {
|
||||
if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) {
|
||||
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/apply_node_transforms"), true));
|
||||
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/normalize_position_tracks"), true));
|
||||
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/overwrite_axis"), true));
|
||||
|
||||
|
@ -67,6 +68,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||
if (!src_skeleton) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_renamed = bool(p_options["retarget/bone_renamer/rename_bones"]);
|
||||
Array filter = p_options["retarget/rest_fixer/fix_silhouette/filter"];
|
||||
bool is_rest_changed = false;
|
||||
|
@ -89,6 +91,107 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||
}
|
||||
}
|
||||
|
||||
// Apply node transforms.
|
||||
if (bool(p_options["retarget/rest_fixer/apply_node_transforms"])) {
|
||||
LocalVector<Transform3D> old_skeleton_rest;
|
||||
LocalVector<Transform3D> old_skeleton_global_rest;
|
||||
for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
|
||||
old_skeleton_rest.push_back(src_skeleton->get_bone_rest(i));
|
||||
old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i));
|
||||
}
|
||||
|
||||
Transform3D global_transform;
|
||||
Node *pr = src_skeleton;
|
||||
while (pr) {
|
||||
Node3D *pr3d = Object::cast_to<Node3D>(pr);
|
||||
if (pr3d) {
|
||||
global_transform = pr3d->get_transform() * global_transform;
|
||||
pr3d->set_transform(Transform3D());
|
||||
}
|
||||
pr = pr->get_parent();
|
||||
}
|
||||
Vector3 scl = global_transform.basis.get_scale_local();
|
||||
|
||||
Vector<int> bones_to_process = src_skeleton->get_parentless_bones();
|
||||
for (int i = 0; i < bones_to_process.size(); i++) {
|
||||
src_skeleton->set_bone_rest(bones_to_process[i], global_transform.orthonormalized() * src_skeleton->get_bone_rest(bones_to_process[i]));
|
||||
}
|
||||
|
||||
while (bones_to_process.size() > 0) {
|
||||
int src_idx = bones_to_process[0];
|
||||
bones_to_process.erase(src_idx);
|
||||
Vector<int> src_children = src_skeleton->get_bone_children(src_idx);
|
||||
for (int i = 0; i < src_children.size(); i++) {
|
||||
bones_to_process.push_back(src_children[i]);
|
||||
}
|
||||
src_skeleton->set_bone_rest(src_idx, Transform3D(src_skeleton->get_bone_rest(src_idx).basis, src_skeleton->get_bone_rest(src_idx).origin * scl));
|
||||
}
|
||||
|
||||
// Fix animation.
|
||||
bones_to_process = src_skeleton->get_parentless_bones();
|
||||
{
|
||||
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 || anim->track_get_type(i) == Animation::TYPE_ROTATION_3D || anim->track_get_type(i) == Animation::TYPE_SCALE_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()))->get_node(NodePath(track_path));
|
||||
if (node) {
|
||||
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
||||
if (track_skeleton && track_skeleton == src_skeleton) {
|
||||
StringName bn = anim->track_get_path(i).get_subname(0);
|
||||
if (bn) {
|
||||
int bone_idx = src_skeleton->find_bone(bn);
|
||||
int key_len = anim->track_get_key_count(i);
|
||||
if (anim->track_get_type(i) == Animation::TYPE_POSITION_3D) {
|
||||
if (bones_to_process.has(bone_idx)) {
|
||||
for (int j = 0; j < key_len; j++) {
|
||||
Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
|
||||
anim->track_set_key_value(i, j, global_transform.basis.xform(ps) + global_transform.origin);
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < key_len; j++) {
|
||||
Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
|
||||
anim->track_set_key_value(i, j, ps * scl);
|
||||
}
|
||||
}
|
||||
} else if (bones_to_process.has(bone_idx)) {
|
||||
if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) {
|
||||
for (int j = 0; j < key_len; j++) {
|
||||
Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j));
|
||||
anim->track_set_key_value(i, j, global_transform.basis.get_rotation_quaternion() * qt);
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < key_len; j++) {
|
||||
Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j)));
|
||||
anim->track_set_key_value(i, j, (global_transform.basis * sc).get_scale());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is_rest_changed = true;
|
||||
}
|
||||
|
||||
// Set motion scale to Skeleton if normalize position tracks.
|
||||
if (bool(p_options["retarget/rest_fixer/normalize_position_tracks"])) {
|
||||
int src_bone_idx = src_skeleton->find_bone(profile->get_scale_base_bone());
|
||||
|
@ -367,32 +470,6 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||
src_skeleton->set_bone_rest(src_idx, Transform3D(tgt_rot, diff.xform(src_skeleton->get_bone_rest(src_idx).origin)));
|
||||
}
|
||||
|
||||
// Fix skin.
|
||||
{
|
||||
TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
|
||||
while (nodes.size()) {
|
||||
ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
|
||||
Ref<Skin> skin = mi->get_skin();
|
||||
if (skin.is_valid()) {
|
||||
Node *node = mi->get_node(mi->get_skeleton_path());
|
||||
if (node) {
|
||||
Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
|
||||
if (mesh_skeleton && node == src_skeleton) {
|
||||
int skin_len = skin->get_bind_count();
|
||||
for (int i = 0; i < skin_len; i++) {
|
||||
StringName bn = skin->get_bind_name(i);
|
||||
int bone_idx = src_skeleton->find_bone(bn);
|
||||
if (bone_idx >= 0) {
|
||||
Transform3D new_rest = silhouette_diff[i] * src_skeleton->get_bone_global_rest(bone_idx);
|
||||
skin->set_bind_pose(i, new_rest.inverse());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fix animation.
|
||||
{
|
||||
TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
|
||||
|
@ -471,8 +548,34 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||
is_rest_changed = true;
|
||||
}
|
||||
|
||||
// Init skeleton pose to new rest.
|
||||
if (is_rest_changed) {
|
||||
// Fix skin.
|
||||
{
|
||||
TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
|
||||
while (nodes.size()) {
|
||||
ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
|
||||
Ref<Skin> skin = mi->get_skin();
|
||||
if (skin.is_valid()) {
|
||||
Node *node = mi->get_node(mi->get_skeleton_path());
|
||||
if (node) {
|
||||
Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
|
||||
if (mesh_skeleton && node == src_skeleton) {
|
||||
int skin_len = skin->get_bind_count();
|
||||
for (int i = 0; i < skin_len; i++) {
|
||||
StringName bn = skin->get_bind_name(i);
|
||||
int bone_idx = src_skeleton->find_bone(bn);
|
||||
if (bone_idx >= 0) {
|
||||
Transform3D new_rest = silhouette_diff[i] * src_skeleton->get_bone_global_rest(bone_idx);
|
||||
skin->set_bind_pose(i, new_rest.inverse());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init skeleton pose to new rest.
|
||||
for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
|
||||
Transform3D fixed_rest = src_skeleton->get_bone_rest(i);
|
||||
src_skeleton->set_bone_pose_position(i, fixed_rest.origin);
|
||||
|
|
Loading…
Reference in a new issue