You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-24 15:26:15 +00:00
Fix rest fixer for the model has skin which non inverse global rest
This commit is contained in:
@@ -143,7 +143,7 @@ void PostImportPluginSkeletonRenamer::internal_process(InternalImportCategory p_
|
|||||||
// Make unique skeleton.
|
// Make unique skeleton.
|
||||||
if (bool(p_options["retarget/bone_renamer/unique_node/make_unique"])) {
|
if (bool(p_options["retarget/bone_renamer/unique_node/make_unique"])) {
|
||||||
String unique_name = String(p_options["retarget/bone_renamer/unique_node/skeleton_name"]);
|
String unique_name = String(p_options["retarget/bone_renamer/unique_node/skeleton_name"]);
|
||||||
ERR_FAIL_COND_MSG(unique_name == String(), "Skeleton unique name cannot be empty.");
|
ERR_FAIL_COND_MSG(unique_name.is_empty(), "Skeleton unique name cannot be empty.");
|
||||||
|
|
||||||
TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
|
TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
|
||||||
while (nodes.size()) {
|
while (nodes.size()) {
|
||||||
|
|||||||
@@ -90,16 +90,9 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply node transforms.
|
// Get global transform.
|
||||||
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;
|
Transform3D global_transform;
|
||||||
|
if (bool(p_options["retarget/rest_fixer/apply_node_transforms"])) {
|
||||||
Node *pr = src_skeleton;
|
Node *pr = src_skeleton;
|
||||||
while (pr) {
|
while (pr) {
|
||||||
Node3D *pr3d = Object::cast_to<Node3D>(pr);
|
Node3D *pr3d = Object::cast_to<Node3D>(pr);
|
||||||
@@ -109,6 +102,47 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
}
|
}
|
||||||
pr = pr->get_parent();
|
pr = pr->get_parent();
|
||||||
}
|
}
|
||||||
|
global_transform.origin = Vector3(); // Translation by a Node is not a bone animation, so the retargeted model should be at the origin.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calc IBM difference.
|
||||||
|
LocalVector<Vector<Transform3D>> ibm_diffs;
|
||||||
|
{
|
||||||
|
TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
|
||||||
|
while (nodes.size()) {
|
||||||
|
ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
|
||||||
|
ERR_CONTINUE(!mi);
|
||||||
|
|
||||||
|
Ref<Skin> skin = mi->get_skin();
|
||||||
|
ERR_CONTINUE(!skin.is_valid());
|
||||||
|
|
||||||
|
Node *node = mi->get_node(mi->get_skeleton_path());
|
||||||
|
ERR_CONTINUE(!node);
|
||||||
|
|
||||||
|
Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
|
||||||
|
if (!mesh_skeleton || mesh_skeleton != src_skeleton) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<Transform3D> ibm_diff;
|
||||||
|
ibm_diff.resize(src_skeleton->get_bone_count());
|
||||||
|
Transform3D *ibm_diff_w = ibm_diff.ptrw();
|
||||||
|
|
||||||
|
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) {
|
||||||
|
ibm_diff_w[bone_idx] = global_transform * src_skeleton->get_bone_global_rest(bone_idx) * skin->get_bind_pose(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ibm_diffs.push_back(ibm_diff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply node transforms.
|
||||||
|
if (bool(p_options["retarget/rest_fixer/apply_node_transforms"])) {
|
||||||
Vector3 scl = global_transform.basis.get_scale_local();
|
Vector3 scl = global_transform.basis.get_scale_local();
|
||||||
|
|
||||||
Vector<int> bones_to_process = src_skeleton->get_parentless_bones();
|
Vector<int> bones_to_process = src_skeleton->get_parentless_bones();
|
||||||
@@ -148,11 +182,18 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
|
|
||||||
String track_path = String(anim->track_get_path(i).get_concatenated_names());
|
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));
|
Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
|
||||||
if (node) {
|
ERR_CONTINUE(!node);
|
||||||
|
|
||||||
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
||||||
if (track_skeleton && track_skeleton == src_skeleton) {
|
if (!track_skeleton || track_skeleton != src_skeleton) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
StringName bn = anim->track_get_path(i).get_subname(0);
|
StringName bn = anim->track_get_path(i).get_subname(0);
|
||||||
if (bn) {
|
if (!bn) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int bone_idx = src_skeleton->find_bone(bn);
|
int bone_idx = src_skeleton->find_bone(bn);
|
||||||
int key_len = anim->track_get_key_count(i);
|
int key_len = anim->track_get_key_count(i);
|
||||||
if (anim->track_get_type(i) == Animation::TYPE_POSITION_3D) {
|
if (anim->track_get_type(i) == Animation::TYPE_POSITION_3D) {
|
||||||
@@ -184,9 +225,6 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is_rest_changed = true;
|
is_rest_changed = true;
|
||||||
}
|
}
|
||||||
@@ -220,11 +258,14 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found_skeleton) {
|
if (!found_skeleton) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Search and insert rot track if it doesn't exist.
|
// Search and insert rot track if it doesn't exist.
|
||||||
for (int prof_idx = 0; prof_idx < prof_skeleton->get_bone_count(); prof_idx++) {
|
for (int prof_idx = 0; prof_idx < prof_skeleton->get_bone_count(); prof_idx++) {
|
||||||
String bone_name = is_renamed ? prof_skeleton->get_bone_name(prof_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_idx)));
|
String bone_name = is_renamed ? prof_skeleton->get_bone_name(prof_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_idx)));
|
||||||
if (bone_name == String()) {
|
if (bone_name.is_empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int src_idx = src_skeleton->find_bone(bone_name);
|
int src_idx = src_skeleton->find_bone(bone_name);
|
||||||
@@ -242,7 +283,6 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Fix silhouette.
|
// Fix silhouette.
|
||||||
Vector<Transform3D> silhouette_diff; // Transform values to be ignored when overwrite axis.
|
Vector<Transform3D> silhouette_diff; // Transform values to be ignored when overwrite axis.
|
||||||
@@ -385,11 +425,18 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
|
|
||||||
String track_path = String(anim->track_get_path(i).get_concatenated_names());
|
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));
|
Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
|
||||||
if (node) {
|
ERR_CONTINUE(!node);
|
||||||
|
|
||||||
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
||||||
if (track_skeleton && track_skeleton == src_skeleton) {
|
if (!track_skeleton || track_skeleton != src_skeleton) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
StringName bn = anim->track_get_path(i).get_concatenated_subnames();
|
StringName bn = anim->track_get_path(i).get_concatenated_subnames();
|
||||||
if (bn == scale_base_bone_name) {
|
if (bn != scale_base_bone_name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int key_len = anim->track_get_key_count(i);
|
int key_len = anim->track_get_key_count(i);
|
||||||
for (int j = 0; j < key_len; j++) {
|
for (int j = 0; j < key_len; j++) {
|
||||||
Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j));
|
Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j));
|
||||||
@@ -400,9 +447,6 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For skin modification in overwrite rest.
|
// For skin modification in overwrite rest.
|
||||||
for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
|
for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
|
||||||
@@ -441,9 +485,13 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
|
|
||||||
String track_path = String(anim->track_get_path(i).get_concatenated_names());
|
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));
|
Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
|
||||||
if (node) {
|
ERR_CONTINUE(!node);
|
||||||
|
|
||||||
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
||||||
if (track_skeleton && track_skeleton == src_skeleton) {
|
if (!track_skeleton || track_skeleton != src_skeleton) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
real_t mlt = 1 / src_skeleton->get_motion_scale();
|
real_t mlt = 1 / src_skeleton->get_motion_scale();
|
||||||
int key_len = anim->track_get_key_count(i);
|
int key_len = anim->track_get_key_count(i);
|
||||||
for (int j = 0; j < key_len; j++) {
|
for (int j = 0; j < key_len; j++) {
|
||||||
@@ -454,8 +502,6 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overwrite axis.
|
// Overwrite axis.
|
||||||
if (bool(p_options["retarget/rest_fixer/overwrite_axis"])) {
|
if (bool(p_options["retarget/rest_fixer/overwrite_axis"])) {
|
||||||
@@ -518,6 +564,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
|
TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
|
||||||
while (nodes.size()) {
|
while (nodes.size()) {
|
||||||
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
|
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
|
||||||
|
ERR_CONTINUE(!ap);
|
||||||
List<StringName> anims;
|
List<StringName> anims;
|
||||||
ap->get_animation_list(&anims);
|
ap->get_animation_list(&anims);
|
||||||
for (const StringName &name : anims) {
|
for (const StringName &name : anims) {
|
||||||
@@ -534,11 +581,18 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
|
|
||||||
String track_path = String(anim->track_get_path(i).get_concatenated_names());
|
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));
|
Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
|
||||||
if (node) {
|
ERR_CONTINUE(!node);
|
||||||
|
|
||||||
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
|
||||||
if (track_skeleton && track_skeleton == src_skeleton) {
|
if (!track_skeleton || track_skeleton != src_skeleton) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
StringName bn = anim->track_get_path(i).get_subname(0);
|
StringName bn = anim->track_get_path(i).get_subname(0);
|
||||||
if (bn) {
|
if (!bn) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int bone_idx = src_skeleton->find_bone(bn);
|
int bone_idx = src_skeleton->find_bone(bn);
|
||||||
|
|
||||||
Transform3D old_rest = old_skeleton_rest[bone_idx];
|
Transform3D old_rest = old_skeleton_rest[bone_idx];
|
||||||
@@ -584,9 +638,6 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is_rest_changed = true;
|
is_rest_changed = true;
|
||||||
}
|
}
|
||||||
@@ -595,26 +646,35 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|||||||
// Fix skin.
|
// Fix skin.
|
||||||
{
|
{
|
||||||
TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
|
TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
|
||||||
|
int skin_idx = 0;
|
||||||
while (nodes.size()) {
|
while (nodes.size()) {
|
||||||
ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
|
ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
|
||||||
|
ERR_CONTINUE(!mi);
|
||||||
|
|
||||||
Ref<Skin> skin = mi->get_skin();
|
Ref<Skin> skin = mi->get_skin();
|
||||||
if (skin.is_valid()) {
|
ERR_CONTINUE(!skin.is_valid());
|
||||||
|
|
||||||
Node *node = mi->get_node(mi->get_skeleton_path());
|
Node *node = mi->get_node(mi->get_skeleton_path());
|
||||||
if (node) {
|
ERR_CONTINUE(!node);
|
||||||
|
|
||||||
Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
|
Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
|
||||||
if (mesh_skeleton && node == src_skeleton) {
|
if (!mesh_skeleton || mesh_skeleton != src_skeleton) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<Transform3D> ibm_diff = ibm_diffs[skin_idx];
|
||||||
|
|
||||||
int skin_len = skin->get_bind_count();
|
int skin_len = skin->get_bind_count();
|
||||||
for (int i = 0; i < skin_len; i++) {
|
for (int i = 0; i < skin_len; i++) {
|
||||||
StringName bn = skin->get_bind_name(i);
|
StringName bn = skin->get_bind_name(i);
|
||||||
int bone_idx = src_skeleton->find_bone(bn);
|
int bone_idx = src_skeleton->find_bone(bn);
|
||||||
if (bone_idx >= 0) {
|
if (bone_idx >= 0) {
|
||||||
Transform3D new_rest = silhouette_diff[i] * src_skeleton->get_bone_global_rest(bone_idx);
|
Transform3D new_rest = silhouette_diff[i] * src_skeleton->get_bone_global_rest(bone_idx);
|
||||||
skin->set_bind_pose(i, new_rest.inverse());
|
skin->set_bind_pose(i, new_rest.inverse() * ibm_diff[bone_idx]);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skin_idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user