summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
authorreduz <reduzio@gmail.com>2021-10-13 09:37:40 -0300
committerreduz <reduzio@gmail.com>2021-10-13 14:51:29 -0300
commit2dc823273e8d7d0eb92049c0d687f6a2c247ce13 (patch)
tree768c9c2f6f4dc005d05afc80200bf6cb5f0013d0 /scene
parent004b44e91519626e847c981c9f91ae3c4e36282c (diff)
Remove REST transform influence in skeleton bones
* Animations and Skeletons are now pose-only. * Rest transform is kept as reference (when it exists) and for IK * Improves 3D model compatibility (non uniform transforms will properly work, as well as all animations coming from Autodesk products).
Diffstat (limited to 'scene')
-rw-r--r--scene/3d/bone_attachment_3d.cpp6
-rw-r--r--scene/3d/bone_attachment_3d.h1
-rw-r--r--scene/3d/mesh_instance_3d.cpp4
-rw-r--r--scene/3d/skeleton_3d.cpp197
-rw-r--r--scene/3d/skeleton_3d.h14
-rw-r--r--scene/animation/animation_tree.cpp3
-rw-r--r--scene/resources/skeleton_modification_3d_fabrik.cpp2
-rw-r--r--scene/resources/skeleton_modification_3d_twoboneik.cpp2
8 files changed, 73 insertions, 156 deletions
diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp
index afd11482e3..8e89f4fc54 100644
--- a/scene/3d/bone_attachment_3d.cpp
+++ b/scene/3d/bone_attachment_3d.cpp
@@ -215,8 +215,6 @@ void BoneAttachment3D::_transform_changed() {
sk->set_bone_global_pose_override(bone_idx, our_trans, 1.0, true);
} else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) {
sk->set_bone_local_pose_override(bone_idx, sk->global_pose_to_local_pose(bone_idx, our_trans), 1.0, true);
- } else if (override_mode == OVERRIDE_MODES::MODE_CUSTOM_POSE) {
- sk->set_bone_custom_pose(bone_idx, sk->global_pose_to_local_pose(bone_idx, our_trans));
}
}
}
@@ -273,8 +271,6 @@ void BoneAttachment3D::set_override_pose(bool p_override) {
sk->set_bone_global_pose_override(bone_idx, Transform3D(), 0.0, false);
} else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) {
sk->set_bone_local_pose_override(bone_idx, Transform3D(), 0.0, false);
- } else if (override_mode == OVERRIDE_MODES::MODE_CUSTOM_POSE) {
- sk->set_bone_custom_pose(bone_idx, Transform3D());
}
}
_transform_changed();
@@ -294,8 +290,6 @@ void BoneAttachment3D::set_override_mode(int p_mode) {
sk->set_bone_global_pose_override(bone_idx, Transform3D(), 0.0, false);
} else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) {
sk->set_bone_local_pose_override(bone_idx, Transform3D(), 0.0, false);
- } else if (override_mode == OVERRIDE_MODES::MODE_CUSTOM_POSE) {
- sk->set_bone_custom_pose(bone_idx, Transform3D());
}
}
override_mode = p_mode;
diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h
index cf681cace8..57b9854e0e 100644
--- a/scene/3d/bone_attachment_3d.h
+++ b/scene/3d/bone_attachment_3d.h
@@ -47,7 +47,6 @@ class BoneAttachment3D : public Node3D {
enum OVERRIDE_MODES {
MODE_GLOBAL_POSE,
MODE_LOCAL_POSE,
- MODE_CUSTOM_POSE
};
bool use_external_skeleton = false;
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 67f4a88228..cfd90e5da0 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -146,11 +146,13 @@ void MeshInstance3D::_resolve_skeleton_path() {
if (!skeleton_path.is_empty()) {
Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(get_node(skeleton_path));
if (skeleton) {
- new_skin_reference = skeleton->register_skin(skin_internal);
if (skin_internal.is_null()) {
+ new_skin_reference = skeleton->register_skin(skeleton->create_skin_from_rest_transforms());
//a skin was created for us
skin_internal = new_skin_reference->get_skin();
notify_property_list_changed();
+ } else {
+ new_skin_reference = skeleton->register_skin(skin_internal);
}
}
}
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index 79504b10bb..9b28d7aff8 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -557,18 +557,6 @@ void Skeleton3D::unparent_bone_and_rest(int p_bone) {
_make_dirty();
}
-void Skeleton3D::set_bone_disable_rest(int p_bone, bool p_disable) {
- const int bone_size = bones.size();
- ERR_FAIL_INDEX(p_bone, bone_size);
- bones.write[p_bone].disable_rest = p_disable;
-}
-
-bool Skeleton3D::is_bone_rest_disabled(int p_bone) const {
- const int bone_size = bones.size();
- ERR_FAIL_INDEX_V(p_bone, bone_size, false);
- return bones[p_bone].disable_rest;
-}
-
int Skeleton3D::get_bone_parent(int p_bone) const {
const int bone_size = bones.size();
ERR_FAIL_INDEX_V(p_bone, bone_size, -1);
@@ -723,23 +711,6 @@ Transform3D Skeleton3D::get_bone_pose(int p_bone) const {
return bones[p_bone].pose_cache;
}
-void Skeleton3D::set_bone_custom_pose(int p_bone, const Transform3D &p_custom_pose) {
- const int bone_size = bones.size();
- ERR_FAIL_INDEX(p_bone, bone_size);
- //ERR_FAIL_COND( !is_inside_scene() );
-
- bones.write[p_bone].custom_pose_enable = (p_custom_pose != Transform3D());
- bones.write[p_bone].custom_pose = p_custom_pose;
-
- _make_dirty();
-}
-
-Transform3D Skeleton3D::get_bone_custom_pose(int p_bone) const {
- const int bone_size = bones.size();
- ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D());
- return bones[p_bone].custom_pose;
-}
-
void Skeleton3D::_make_dirty() {
if (dirty) {
return;
@@ -938,59 +909,57 @@ void Skeleton3D::_skin_changed() {
_make_dirty();
}
-Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) {
- for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) {
- if (E->get()->skin == p_skin) {
- return Ref<SkinReference>(E->get());
+Ref<Skin> Skeleton3D::create_skin_from_rest_transforms() {
+ Ref<Skin> skin;
+
+ skin.instantiate();
+ skin->set_bind_count(bones.size());
+ _update_process_order(); // Just in case.
+
+ // Pose changed, rebuild cache of inverses.
+ const Bone *bonesptr = bones.ptr();
+ int len = bones.size();
+
+ // Calculate global rests and invert them.
+ LocalVector<int> bones_to_process;
+ bones_to_process = get_parentless_bones();
+ while (bones_to_process.size() > 0) {
+ int current_bone_idx = bones_to_process[0];
+ const Bone &b = bonesptr[current_bone_idx];
+ bones_to_process.erase(current_bone_idx);
+ LocalVector<int> child_bones_vector;
+ child_bones_vector = get_bone_children(current_bone_idx);
+ int child_bones_size = child_bones_vector.size();
+ if (b.parent < 0) {
+ skin->set_bind_pose(current_bone_idx, b.rest);
+ }
+ for (int i = 0; i < child_bones_size; i++) {
+ int child_bone_idx = child_bones_vector[i];
+ const Bone &cb = bonesptr[child_bone_idx];
+ skin->set_bind_pose(child_bone_idx, skin->get_bind_pose(current_bone_idx) * cb.rest);
+ // Add the bone's children to the list of bones to be processed.
+ bones_to_process.push_back(child_bones_vector[i]);
}
}
- Ref<Skin> skin = p_skin;
-
- if (skin.is_null()) {
- // Need to create one from existing code, this is for compatibility only
- // when skeletons did not support skins. It is also used by gizmo
- // to display the skeleton.
-
- skin.instantiate();
- skin->set_bind_count(bones.size());
- _update_process_order(); // Just in case.
-
- // Pose changed, rebuild cache of inverses.
- const Bone *bonesptr = bones.ptr();
- int len = bones.size();
-
- // Calculate global rests and invert them.
- LocalVector<int> bones_to_process;
- bones_to_process = get_parentless_bones();
- while (bones_to_process.size() > 0) {
- int current_bone_idx = bones_to_process[0];
- const Bone &b = bonesptr[current_bone_idx];
- bones_to_process.erase(current_bone_idx);
- LocalVector<int> child_bones_vector;
- child_bones_vector = get_bone_children(current_bone_idx);
- int child_bones_size = child_bones_vector.size();
- if (b.parent < 0) {
- skin->set_bind_pose(current_bone_idx, b.rest);
- }
- for (int i = 0; i < child_bones_size; i++) {
- int child_bone_idx = child_bones_vector[i];
- const Bone &cb = bonesptr[child_bone_idx];
- skin->set_bind_pose(child_bone_idx, skin->get_bind_pose(current_bone_idx) * cb.rest);
- // Add the bone's children to the list of bones to be processed.
- bones_to_process.push_back(child_bones_vector[i]);
- }
- }
+ for (int i = 0; i < len; i++) {
+ // The inverse is what is actually required.
+ skin->set_bind_bone(i, i);
+ skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse());
+ }
- for (int i = 0; i < len; i++) {
- // The inverse is what is actually required.
- skin->set_bind_bone(i, i);
- skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse());
+ return skin;
+}
+
+Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) {
+ ERR_FAIL_COND_V(p_skin.is_null(), Ref<SkinReference>());
+
+ for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) {
+ if (E->get()->skin == p_skin) {
+ return Ref<SkinReference>(E->get());
}
}
- ERR_FAIL_COND_V(skin.is_null(), Ref<SkinReference>());
-
Ref<SkinReference> skin_ref;
skin_ref.instantiate();
@@ -998,11 +967,11 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) {
skin_ref->bind_count = 0;
skin_ref->skeleton = RenderingServer::get_singleton()->skeleton_create();
skin_ref->skeleton_node = this;
- skin_ref->skin = skin;
+ skin_ref->skin = p_skin;
skin_bindings.insert(skin_ref.operator->());
- skin->connect("changed", Callable(skin_ref.operator->(), "_skin_changed"));
+ skin_ref->skin->connect("changed", Callable(skin_ref.operator->(), "_skin_changed"));
_make_dirty(); // Skin needs to be updated, so update skeleton.
@@ -1038,61 +1007,33 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) {
Bone &b = bonesptr[current_bone_idx];
bool bone_enabled = b.enabled && !show_rest_only;
- if (b.disable_rest) {
- if (bone_enabled) {
- b.update_pose_cache();
- Transform3D pose = b.pose_cache;
- if (b.custom_pose_enable) {
- pose = b.custom_pose * pose;
- }
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global * pose;
- b.pose_global_no_override = b.pose_global;
- } else {
- b.pose_global = pose;
- b.pose_global_no_override = b.pose_global;
- }
+ if (bone_enabled) {
+ b.update_pose_cache();
+ Transform3D pose = b.pose_cache;
+
+ if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global * pose;
+ b.pose_global_no_override = b.pose_global;
} else {
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global;
- b.pose_global_no_override = b.pose_global;
- } else {
- b.pose_global = Transform3D();
- b.pose_global_no_override = b.pose_global;
- }
+ b.pose_global = pose;
+ b.pose_global_no_override = b.pose_global;
}
-
} else {
- if (bone_enabled) {
- b.update_pose_cache();
- Transform3D pose = b.pose_cache;
- if (b.custom_pose_enable) {
- pose = b.custom_pose * pose;
- }
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose);
- b.pose_global_no_override = b.pose_global;
- } else {
- b.pose_global = b.rest * pose;
- b.pose_global_no_override = b.pose_global;
- }
+ if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global * b.rest;
+ b.pose_global_no_override = b.pose_global;
} else {
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global * b.rest;
- b.pose_global_no_override = b.pose_global;
- } else {
- b.pose_global = b.rest;
- b.pose_global_no_override = b.pose_global;
- }
+ b.pose_global = b.rest;
+ b.pose_global_no_override = b.pose_global;
}
}
if (b.local_pose_override_amount >= CMP_EPSILON) {
Transform3D override_local_pose;
if (b.parent >= 0) {
- override_local_pose = bonesptr[b.parent].pose_global * (b.rest * b.local_pose_override);
+ override_local_pose = bonesptr[b.parent].pose_global * b.local_pose_override;
} else {
- override_local_pose = (b.rest * b.local_pose_override);
+ override_local_pose = b.local_pose_override;
}
b.pose_global = b.pose_global.interpolate_with(override_local_pose, b.local_pose_override_amount);
}
@@ -1133,8 +1074,8 @@ Transform3D Skeleton3D::global_pose_to_local_pose(int p_bone_idx, Transform3D p_
ERR_FAIL_INDEX_V(p_bone_idx, bone_size, Transform3D());
if (bones[p_bone_idx].parent >= 0) {
int parent_bone_idx = bones[p_bone_idx].parent;
- Transform3D conversion_transform = (bones[parent_bone_idx].pose_global * bones[p_bone_idx].rest);
- return conversion_transform.affine_inverse() * p_global_pose;
+ Transform3D conversion_transform = bones[parent_bone_idx].pose_global.affine_inverse();
+ return conversion_transform * p_global_pose;
} else {
return p_global_pose;
}
@@ -1145,8 +1086,7 @@ Transform3D Skeleton3D::local_pose_to_global_pose(int p_bone_idx, Transform3D p_
ERR_FAIL_INDEX_V(p_bone_idx, bone_size, Transform3D());
if (bones[p_bone_idx].parent >= 0) {
int parent_bone_idx = bones[p_bone_idx].parent;
- Transform3D conversion_transform = (bones[parent_bone_idx].pose_global * bones[p_bone_idx].rest);
- return conversion_transform * p_local_pose;
+ return bones[parent_bone_idx].pose_global * p_local_pose;
} else {
return p_local_pose;
}
@@ -1236,13 +1176,11 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bone_rest", "bone_idx"), &Skeleton3D::get_bone_rest);
ClassDB::bind_method(D_METHOD("set_bone_rest", "bone_idx", "rest"), &Skeleton3D::set_bone_rest);
+ ClassDB::bind_method(D_METHOD("create_skin_from_rest_transforms"), &Skeleton3D::create_skin_from_rest_transforms);
ClassDB::bind_method(D_METHOD("register_skin", "skin"), &Skeleton3D::register_skin);
ClassDB::bind_method(D_METHOD("localize_rests"), &Skeleton3D::localize_rests);
- ClassDB::bind_method(D_METHOD("set_bone_disable_rest", "bone_idx", "disable"), &Skeleton3D::set_bone_disable_rest);
- ClassDB::bind_method(D_METHOD("is_bone_rest_disabled", "bone_idx"), &Skeleton3D::is_bone_rest_disabled);
-
ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton3D::clear_bones);
ClassDB::bind_method(D_METHOD("get_bone_pose", "bone_idx"), &Skeleton3D::get_bone_pose);
@@ -1267,9 +1205,6 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bone_local_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton3D::set_bone_local_pose_override, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_bone_local_pose_override", "bone_idx"), &Skeleton3D::get_bone_local_pose_override);
- ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton3D::get_bone_custom_pose);
- ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton3D::set_bone_custom_pose);
-
ClassDB::bind_method(D_METHOD("force_update_all_bone_transforms"), &Skeleton3D::force_update_all_bone_transforms);
ClassDB::bind_method(D_METHOD("force_update_bone_child_transform", "bone_idx"), &Skeleton3D::force_update_bone_children_transforms);
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index aacee3da4e..f3cf551af7 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -76,7 +76,6 @@ private:
bool enabled;
int parent;
- bool disable_rest = false;
Transform3D rest;
_FORCE_INLINE_ void update_pose_cache() {
@@ -95,9 +94,6 @@ private:
Transform3D pose_global;
Transform3D pose_global_no_override;
- bool custom_pose_enable = false;
- Transform3D custom_pose;
-
real_t global_pose_override_amount = 0.0;
bool global_pose_override_reset = false;
Transform3D global_pose_override;
@@ -119,8 +115,6 @@ private:
Bone() {
parent = -1;
enabled = true;
- disable_rest = false;
- custom_pose_enable = false;
global_pose_override_amount = 0;
global_pose_override_reset = false;
#ifndef _3D_DISABLED
@@ -199,9 +193,6 @@ public:
void remove_bone_child(int p_bone, int p_child);
Vector<int> get_parentless_bones();
- void set_bone_disable_rest(int p_bone, bool p_disable);
- bool is_bone_rest_disabled(int p_bone) const;
-
int get_bone_count() const;
void set_bone_rest(int p_bone, const Transform3D &p_rest);
@@ -228,9 +219,6 @@ public:
Quaternion get_bone_pose_rotation(int p_bone) const;
Vector3 get_bone_pose_scale(int p_bone) const;
- void set_bone_custom_pose(int p_bone, const Transform3D &p_custom_pose);
- Transform3D get_bone_custom_pose(int p_bone) const;
-
void clear_bones_global_pose_override();
Transform3D get_bone_global_pose_override(int p_bone) const;
void set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, real_t p_amount, bool p_persistent = false);
@@ -241,6 +229,8 @@ public:
void localize_rests(); // used for loaders and tools
+ Ref<Skin> create_skin_from_rest_transforms();
+
Ref<SkinReference> register_skin(const Ref<Skin> &p_skin);
void force_update_all_dirty_bones();
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 2ed8268289..dd5fe46223 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -1360,9 +1360,6 @@ void AnimationTree::_process_graph(real_t p_delta) {
root_motion_transform = xform;
- if (t->skeleton && t->bone_idx >= 0) {
- root_motion_transform = (t->skeleton->get_bone_rest(t->bone_idx) * root_motion_transform) * t->skeleton->get_bone_rest(t->bone_idx).affine_inverse();
- }
} else if (t->skeleton && t->bone_idx >= 0) {
if (t->loc_used) {
t->skeleton->set_bone_pose_position(t->bone_idx, t->loc);
diff --git a/scene/resources/skeleton_modification_3d_fabrik.cpp b/scene/resources/skeleton_modification_3d_fabrik.cpp
index e615615924..20ebbda256 100644
--- a/scene/resources/skeleton_modification_3d_fabrik.cpp
+++ b/scene/resources/skeleton_modification_3d_fabrik.cpp
@@ -168,7 +168,7 @@ void SkeletonModification3DFABRIK::_execute(real_t p_delta) {
// Apply magnet positions:
if (stack->skeleton->get_bone_parent(fabrik_data_chain[i].bone_idx) >= 0) {
int parent_bone_idx = stack->skeleton->get_bone_parent(fabrik_data_chain[i].bone_idx);
- Transform3D conversion_transform = (stack->skeleton->get_bone_global_pose(parent_bone_idx) * stack->skeleton->get_bone_rest(parent_bone_idx));
+ Transform3D conversion_transform = (stack->skeleton->get_bone_global_pose(parent_bone_idx));
local_pose_override.origin += conversion_transform.basis.xform_inv(fabrik_data_chain[i].magnet_position);
} else {
local_pose_override.origin += fabrik_data_chain[i].magnet_position;
diff --git a/scene/resources/skeleton_modification_3d_twoboneik.cpp b/scene/resources/skeleton_modification_3d_twoboneik.cpp
index ae7a3bab7e..c1a71148a7 100644
--- a/scene/resources/skeleton_modification_3d_twoboneik.cpp
+++ b/scene/resources/skeleton_modification_3d_twoboneik.cpp
@@ -455,7 +455,7 @@ void SkeletonModification3DTwoBoneIK::calculate_joint_lengths() {
joint_two_length = 0;
for (int i = 0; i < bone_two_children.size(); i++) {
joint_two_length += bone_two_rest_trans.origin.distance_to(
- stack->skeleton->local_pose_to_global_pose(bone_two_children[i], stack->skeleton->get_bone_rest(bone_two_children[i])).origin);
+ stack->skeleton->get_bone_global_pose(bone_two_children[i]).origin);
}
joint_two_length = joint_two_length / bone_two_children.size();
} else {