mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-04-09 05:21:49 +02:00
Ported from Godot4: 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).
- reduz
2dc823273e
This commit is contained in:
parent
15a5bea727
commit
109a0ca81b
@ -45,6 +45,11 @@
|
|||||||
Removes the local pose override on all bones in the skeleton.
|
Removes the local pose override on all bones in the skeleton.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="create_skin_from_rest_transforms">
|
||||||
|
<return type="Skin" />
|
||||||
|
<description>
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="execute_modifications">
|
<method name="execute_modifications">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<argument index="0" name="delta" type="float" />
|
<argument index="0" name="delta" type="float" />
|
||||||
@ -200,7 +205,7 @@
|
|||||||
<argument index="1" name="basis" type="Basis" />
|
<argument index="1" name="basis" type="Basis" />
|
||||||
<description>
|
<description>
|
||||||
Rotates the given [Basis] so that the forward axis of the Basis is facing in the forward direction of the bone at [code]bone_idx[/code].
|
Rotates the given [Basis] so that the forward axis of the Basis is facing in the forward direction of the bone at [code]bone_idx[/code].
|
||||||
This is helper function to make using [method Transform3D.looking_at] easier with bone poses.
|
This is helper function to make using [method Transform.looking_at] easier with bone poses.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="is_bone_enabled" qualifiers="const">
|
<method name="is_bone_enabled" qualifiers="const">
|
||||||
@ -210,15 +215,6 @@
|
|||||||
Returns whether the bone pose for the bone at [code]bone_idx[/code] is enabled.
|
Returns whether the bone pose for the bone at [code]bone_idx[/code] is enabled.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="is_bone_rest_disabled" qualifiers="const">
|
|
||||||
<return type="bool">
|
|
||||||
</return>
|
|
||||||
<argument index="0" name="bone_idx" type="int">
|
|
||||||
</argument>
|
|
||||||
<description>
|
|
||||||
Returns whether the bone rest for the bone at [code]bone_idx[/code] is disabled.
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="local_pose_to_global_pose">
|
<method name="local_pose_to_global_pose">
|
||||||
<return type="Transform3D" />
|
<return type="Transform3D" />
|
||||||
<argument index="0" name="bone_idx" type="int" />
|
<argument index="0" name="bone_idx" type="int" />
|
||||||
@ -288,15 +284,6 @@
|
|||||||
Sets the children for the passed in bone, [code]bone_idx[/code], to the passed-in array of bone indexes, [code]bone_children[/code].
|
Sets the children for the passed in bone, [code]bone_idx[/code], to the passed-in array of bone indexes, [code]bone_children[/code].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="set_bone_custom_pose">
|
|
||||||
<return type="void" />
|
|
||||||
<argument index="0" name="bone_idx" type="int" />
|
|
||||||
<argument index="1" name="custom_pose" type="Transform3D" />
|
|
||||||
<description>
|
|
||||||
Sets the custom pose transform, [code]custom_pose[/code], for the bone at [code]bone_idx[/code]. This pose is an addition to the bone rest pose.
|
|
||||||
[b]Note:[/b] The pose transform needs to be in bone space. Use [method world_transform_to_global_pose] to convert a world transform, like one you can get from a [Node3D], to bone space.
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="remove_bone">
|
<method name="remove_bone">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<argument index="0" name="bone_idx" type="int" />
|
<argument index="0" name="bone_idx" type="int" />
|
||||||
|
@ -4362,6 +4362,9 @@ Error GLTFDocument::_create_skeletons(Ref<GLTFState> state) {
|
|||||||
|
|
||||||
skeleton->add_bone(node->get_name());
|
skeleton->add_bone(node->get_name());
|
||||||
skeleton->set_bone_rest(bone_index, node->xform);
|
skeleton->set_bone_rest(bone_index, node->xform);
|
||||||
|
skeleton->set_bone_pose_position(bone_index, node->translation);
|
||||||
|
skeleton->set_bone_pose_rotation(bone_index, node->rotation.normalized());
|
||||||
|
skeleton->set_bone_pose_scale(bone_index, node->scale);
|
||||||
|
|
||||||
if (node->parent >= 0 && state->nodes[node->parent]->skeleton == skel_i) {
|
if (node->parent >= 0 && state->nodes[node->parent]->skeleton == skel_i) {
|
||||||
const int bone_parent = skeleton->find_bone(state->nodes[node->parent]->get_name());
|
const int bone_parent = skeleton->find_bone(state->nodes[node->parent]->get_name());
|
||||||
@ -5448,7 +5451,7 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton *p_skeleton3d, Ref<GLTFSta
|
|||||||
// Note that we cannot use _gen_unique_bone_name here, because glTF spec requires all node
|
// Note that we cannot use _gen_unique_bone_name here, because glTF spec requires all node
|
||||||
// names to be unique regardless of whether or not they are used as joints.
|
// names to be unique regardless of whether or not they are used as joints.
|
||||||
joint_node->set_name(_gen_unique_name(state, skeleton->get_bone_name(bone_i)));
|
joint_node->set_name(_gen_unique_name(state, skeleton->get_bone_name(bone_i)));
|
||||||
Transform xform = skeleton->get_bone_rest(bone_i) * skeleton->get_bone_pose(bone_i);
|
Transform xform = skeleton->get_bone_pose(bone_i);
|
||||||
joint_node->scale = xform.basis.get_scale();
|
joint_node->scale = xform.basis.get_scale();
|
||||||
joint_node->rotation = xform.basis.get_rotation_quat();
|
joint_node->rotation = xform.basis.get_rotation_quat();
|
||||||
joint_node->translation = xform.origin;
|
joint_node->translation = xform.origin;
|
||||||
@ -5933,38 +5936,16 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
|
|||||||
|
|
||||||
if (position_idx >= 0) {
|
if (position_idx >= 0) {
|
||||||
pos = _interpolate_track<Vector3>(track.translation_track.times, track.translation_track.values, time, track.translation_track.interpolation);
|
pos = _interpolate_track<Vector3>(track.translation_track.times, track.translation_track.values, time, track.translation_track.interpolation);
|
||||||
|
animation->position_track_insert_key(position_idx, time, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rotation_idx >= 0) {
|
if (rotation_idx >= 0) {
|
||||||
rot = _interpolate_track<Quat>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
|
rot = _interpolate_track<Quat>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
|
||||||
|
animation->rotation_track_insert_key(rotation_idx, time, rot);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scale_idx >= 0) {
|
if (scale_idx >= 0) {
|
||||||
scale = _interpolate_track<Vector3>(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation);
|
scale = _interpolate_track<Vector3>(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation);
|
||||||
}
|
|
||||||
|
|
||||||
if (gltf_node->skeleton >= 0) {
|
|
||||||
Transform xform;
|
|
||||||
xform.basis.set_quat_scale(rot, scale);
|
|
||||||
xform.origin = pos;
|
|
||||||
|
|
||||||
const Skeleton *skeleton = state->skeletons[gltf_node->skeleton]->pandemonium_skeleton;
|
|
||||||
const int bone_idx = skeleton->find_bone(gltf_node->get_name());
|
|
||||||
xform = skeleton->get_bone_rest(bone_idx).affine_inverse() * xform;
|
|
||||||
|
|
||||||
rot = xform.basis.get_rotation_quat();
|
|
||||||
rot.normalize();
|
|
||||||
scale = xform.basis.get_scale();
|
|
||||||
pos = xform.origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position_idx >= 0) {
|
|
||||||
animation->position_track_insert_key(position_idx, time, pos);
|
|
||||||
}
|
|
||||||
if (rotation_idx >= 0) {
|
|
||||||
animation->rotation_track_insert_key(rotation_idx, time, rot);
|
|
||||||
}
|
|
||||||
if (scale_idx >= 0) {
|
|
||||||
animation->scale_track_insert_key(scale_idx, time, scale);
|
animation->scale_track_insert_key(scale_idx, time, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6087,7 +6068,7 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
|
|||||||
} else {
|
} else {
|
||||||
if (skin.is_null()) {
|
if (skin.is_null()) {
|
||||||
// Note that gltf_skin_key should remain null, so these can share a reference.
|
// Note that gltf_skin_key should remain null, so these can share a reference.
|
||||||
skin = skeleton->register_skin(nullptr)->get_skin();
|
skin = skeleton->create_skin_from_rest_transforms();
|
||||||
}
|
}
|
||||||
gltf_skin.instance();
|
gltf_skin.instance();
|
||||||
gltf_skin->pandemonium_skin = skin;
|
gltf_skin->pandemonium_skin = skin;
|
||||||
|
@ -259,11 +259,6 @@ void BoneTransformEditor::_change_transform(Transform p_new_transform) {
|
|||||||
undo_redo->add_undo_method(skeleton, "set_bone_pose", property.get_slicec('/', 1).to_int(), skeleton->get_bone_pose(property.get_slicec('/', 1).to_int()));
|
undo_redo->add_undo_method(skeleton, "set_bone_pose", property.get_slicec('/', 1).to_int(), skeleton->get_bone_pose(property.get_slicec('/', 1).to_int()));
|
||||||
undo_redo->add_do_method(skeleton, "set_bone_pose", property.get_slicec('/', 1).to_int(), p_new_transform);
|
undo_redo->add_do_method(skeleton, "set_bone_pose", property.get_slicec('/', 1).to_int(), p_new_transform);
|
||||||
undo_redo->commit_action();
|
undo_redo->commit_action();
|
||||||
} else if (s == "custom_pose") {
|
|
||||||
undo_redo->create_action(TTR("Set Custom Bone Pose Transform"), UndoRedo::MERGE_ENDS);
|
|
||||||
undo_redo->add_undo_method(skeleton, "set_bone_custom_pose", property.get_slicec('/', 1).to_int(), skeleton->get_bone_custom_pose(property.get_slicec('/', 1).to_int()));
|
|
||||||
undo_redo->add_do_method(skeleton, "set_bone_custom_pose", property.get_slicec('/', 1).to_int(), p_new_transform);
|
|
||||||
undo_redo->commit_action();
|
|
||||||
} else if (s == "rest") {
|
} else if (s == "rest") {
|
||||||
undo_redo->create_action(TTR("Set Bone Rest Transform"), UndoRedo::MERGE_ENDS);
|
undo_redo->create_action(TTR("Set Bone Rest Transform"), UndoRedo::MERGE_ENDS);
|
||||||
undo_redo->add_undo_property(skeleton, property, skeleton->get(property));
|
undo_redo->add_undo_property(skeleton, property, skeleton->get(property));
|
||||||
@ -310,27 +305,6 @@ void BoneTransformEditor::_update_properties() {
|
|||||||
_update_transform_properties(tform);
|
_update_transform_properties(tform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoneTransformEditor::_update_custom_pose_properties() {
|
|
||||||
if (updating) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skeleton == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updating = true;
|
|
||||||
|
|
||||||
int idx = property.to_int();
|
|
||||||
|
|
||||||
//if (idx == 0) {
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
Transform tform = skeleton->get_bone_custom_pose(idx);
|
|
||||||
_update_transform_properties(tform);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BoneTransformEditor::_update_transform_properties(Transform tform) {
|
void BoneTransformEditor::_update_transform_properties(Transform tform) {
|
||||||
Basis rotation_basis = tform.get_basis();
|
Basis rotation_basis = tform.get_basis();
|
||||||
Vector3 rotation_radians = rotation_basis.get_rotation_euler();
|
Vector3 rotation_radians = rotation_basis.get_rotation_euler();
|
||||||
@ -566,9 +540,7 @@ void SkeletonEditor::pose_to_rest() {
|
|||||||
|
|
||||||
ur->add_do_method(skeleton, "set_bone_pose", selected_bone, Transform());
|
ur->add_do_method(skeleton, "set_bone_pose", selected_bone, Transform());
|
||||||
ur->add_undo_method(skeleton, "set_bone_pose", selected_bone, skeleton->get_bone_pose(selected_bone));
|
ur->add_undo_method(skeleton, "set_bone_pose", selected_bone, skeleton->get_bone_pose(selected_bone));
|
||||||
ur->add_do_method(skeleton, "set_bone_custom_pose", selected_bone, Transform());
|
ur->add_do_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_rest(selected_bone) * skeleton->get_bone_pose(selected_bone));
|
||||||
ur->add_undo_method(skeleton, "set_bone_custom_pose", selected_bone, skeleton->get_bone_custom_pose(selected_bone));
|
|
||||||
ur->add_do_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_rest(selected_bone) * skeleton->get_bone_custom_pose(selected_bone) * skeleton->get_bone_pose(selected_bone));
|
|
||||||
ur->add_undo_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_rest(selected_bone));
|
ur->add_undo_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_rest(selected_bone));
|
||||||
|
|
||||||
ur->commit_action();
|
ur->commit_action();
|
||||||
@ -784,11 +756,9 @@ void SkeletonEditor::_joint_tree_selection_changed() {
|
|||||||
|
|
||||||
pose_editor->set_target(bone_path + "pose");
|
pose_editor->set_target(bone_path + "pose");
|
||||||
rest_editor->set_target(bone_path + "rest");
|
rest_editor->set_target(bone_path + "rest");
|
||||||
custom_pose_editor->set_target(bone_path + "custom_pose");
|
|
||||||
|
|
||||||
pose_editor->set_visible(true);
|
pose_editor->set_visible(true);
|
||||||
rest_editor->set_visible(true);
|
rest_editor->set_visible(true);
|
||||||
custom_pose_editor->set_visible(true);
|
|
||||||
|
|
||||||
selected_bone = b_idx;
|
selected_bone = b_idx;
|
||||||
}
|
}
|
||||||
@ -813,10 +783,6 @@ void SkeletonEditor::_update_properties() {
|
|||||||
pose_editor->_update_properties();
|
pose_editor->_update_properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (custom_pose_editor) {
|
|
||||||
custom_pose_editor->_update_custom_pose_properties();
|
|
||||||
}
|
|
||||||
|
|
||||||
_update_gizmo_transform();
|
_update_gizmo_transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1000,12 +966,6 @@ void SkeletonEditor::create_editors() {
|
|||||||
rest_editor->set_visible(false);
|
rest_editor->set_visible(false);
|
||||||
add_child(rest_editor);
|
add_child(rest_editor);
|
||||||
rest_editor->set_transform_read_only(true);
|
rest_editor->set_transform_read_only(true);
|
||||||
|
|
||||||
custom_pose_editor = memnew(BoneTransformEditor(skeleton));
|
|
||||||
custom_pose_editor->set_label(TTR("Bone Custom Pose"));
|
|
||||||
custom_pose_editor->set_visible(false);
|
|
||||||
add_child(custom_pose_editor);
|
|
||||||
custom_pose_editor->set_transform_read_only(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonEditor::_notification(int p_what) {
|
void SkeletonEditor::_notification(int p_what) {
|
||||||
@ -1081,7 +1041,6 @@ SkeletonEditor::SkeletonEditor(EditorInspectorPluginSkeleton *e_plugin, EditorNo
|
|||||||
joint_tree = nullptr;
|
joint_tree = nullptr;
|
||||||
rest_editor = nullptr;
|
rest_editor = nullptr;
|
||||||
pose_editor = nullptr;
|
pose_editor = nullptr;
|
||||||
custom_pose_editor = nullptr;
|
|
||||||
|
|
||||||
skeleton_options = nullptr;
|
skeleton_options = nullptr;
|
||||||
rest_options = nullptr;
|
rest_options = nullptr;
|
||||||
@ -1627,7 +1586,7 @@ void SkeletonGizmoPlugin::set_subgizmo_transform(const EditorSpatialGizmo *p_giz
|
|||||||
if (parent_idx >= 0) {
|
if (parent_idx >= 0) {
|
||||||
original_to_local = original_to_local * skeleton->get_bone_global_pose(parent_idx);
|
original_to_local = original_to_local * skeleton->get_bone_global_pose(parent_idx);
|
||||||
}
|
}
|
||||||
original_to_local = original_to_local * skeleton->get_bone_rest(p_id) * skeleton->get_bone_custom_pose(p_id);
|
|
||||||
Basis to_local = original_to_local.get_basis().inverse();
|
Basis to_local = original_to_local.get_basis().inverse();
|
||||||
|
|
||||||
// Prepare transform.
|
// Prepare transform.
|
||||||
@ -1854,5 +1813,5 @@ void SkeletonGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ref<ArrayMesh> m = surface_tool->commit();
|
Ref<ArrayMesh> m = surface_tool->commit();
|
||||||
p_gizmo->add_mesh(m, Ref<Material>(), Transform(), skeleton->register_skin(Ref<Skin>()));
|
p_gizmo->add_mesh(m, Ref<Material>(), Transform(), skeleton->register_skin(skeleton->create_skin_from_rest_transforms()));
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,6 @@ public:
|
|||||||
void set_label(const String &p_label) { label = p_label; }
|
void set_label(const String &p_label) { label = p_label; }
|
||||||
|
|
||||||
void _update_properties();
|
void _update_properties();
|
||||||
void _update_custom_pose_properties();
|
|
||||||
void _update_transform_properties(Transform p_transform);
|
void _update_transform_properties(Transform p_transform);
|
||||||
|
|
||||||
// Transform can be keyed, whether or not to show the button
|
// Transform can be keyed, whether or not to show the button
|
||||||
@ -169,7 +168,6 @@ class SkeletonEditor : public VBoxContainer {
|
|||||||
Tree *joint_tree;
|
Tree *joint_tree;
|
||||||
BoneTransformEditor *rest_editor;
|
BoneTransformEditor *rest_editor;
|
||||||
BoneTransformEditor *pose_editor;
|
BoneTransformEditor *pose_editor;
|
||||||
BoneTransformEditor *custom_pose_editor;
|
|
||||||
|
|
||||||
VSeparator *separator;
|
VSeparator *separator;
|
||||||
MenuButton *skeleton_options;
|
MenuButton *skeleton_options;
|
||||||
|
@ -83,8 +83,6 @@ void BoneAttachment::set_override_pose(bool p_override) {
|
|||||||
sk->set_bone_global_pose_override(bone_idx, Transform(), 0.0, false);
|
sk->set_bone_global_pose_override(bone_idx, Transform(), 0.0, false);
|
||||||
} else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) {
|
} else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) {
|
||||||
sk->set_bone_local_pose_override(bone_idx, Transform(), 0.0, false);
|
sk->set_bone_local_pose_override(bone_idx, Transform(), 0.0, false);
|
||||||
} else if (override_mode == OVERRIDE_MODES::MODE_CUSTOM_POSE) {
|
|
||||||
sk->set_bone_custom_pose(bone_idx, Transform());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_transform_changed();
|
_transform_changed();
|
||||||
@ -105,8 +103,6 @@ void BoneAttachment::set_override_mode(int p_mode) {
|
|||||||
sk->set_bone_global_pose_override(bone_idx, Transform(), 0.0, false);
|
sk->set_bone_global_pose_override(bone_idx, Transform(), 0.0, false);
|
||||||
} else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) {
|
} else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) {
|
||||||
sk->set_bone_local_pose_override(bone_idx, Transform(), 0.0, false);
|
sk->set_bone_local_pose_override(bone_idx, Transform(), 0.0, false);
|
||||||
} else if (override_mode == OVERRIDE_MODES::MODE_CUSTOM_POSE) {
|
|
||||||
sk->set_bone_custom_pose(bone_idx, Transform());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,6 @@ private:
|
|||||||
enum OVERRIDE_MODES {
|
enum OVERRIDE_MODES {
|
||||||
MODE_GLOBAL_POSE,
|
MODE_GLOBAL_POSE,
|
||||||
MODE_LOCAL_POSE,
|
MODE_LOCAL_POSE,
|
||||||
MODE_CUSTOM_POSE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool bound;
|
bool bound;
|
||||||
|
@ -163,11 +163,13 @@ void MeshInstance::_resolve_skeleton_path() {
|
|||||||
if (!skeleton_path.is_empty()) {
|
if (!skeleton_path.is_empty()) {
|
||||||
Skeleton *skeleton = Object::cast_to<Skeleton>(get_node(skeleton_path));
|
Skeleton *skeleton = Object::cast_to<Skeleton>(get_node(skeleton_path));
|
||||||
if (skeleton) {
|
if (skeleton) {
|
||||||
new_skin_reference = skeleton->register_skin(skin_internal);
|
|
||||||
if (skin_internal.is_null()) {
|
if (skin_internal.is_null()) {
|
||||||
|
new_skin_reference = skeleton->register_skin(skeleton->create_skin_from_rest_transforms());
|
||||||
//a skin was created for us
|
//a skin was created for us
|
||||||
skin_internal = new_skin_reference->get_skin();
|
skin_internal = new_skin_reference->get_skin();
|
||||||
_change_notify();
|
_change_notify();
|
||||||
|
} else {
|
||||||
|
new_skin_reference = skeleton->register_skin(skin_internal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,18 +571,6 @@ void Skeleton::unparent_bone_and_rest(int p_bone) {
|
|||||||
_make_dirty();
|
_make_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skeleton::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 Skeleton::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 Skeleton::get_bone_parent(int p_bone) const {
|
int Skeleton::get_bone_parent(int p_bone) const {
|
||||||
const int bone_size = bones.size();
|
const int bone_size = bones.size();
|
||||||
ERR_FAIL_INDEX_V(p_bone, bone_size, -1);
|
ERR_FAIL_INDEX_V(p_bone, bone_size, -1);
|
||||||
@ -759,21 +747,6 @@ Vector3 Skeleton::get_bone_pose_scale(int p_bone) const {
|
|||||||
return bones[p_bone].pose_scale;
|
return bones[p_bone].pose_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skeleton::set_bone_custom_pose(int p_bone, const Transform &p_custom_pose) {
|
|
||||||
ERR_FAIL_INDEX(p_bone, bones.size());
|
|
||||||
//ERR_FAIL_COND( !is_inside_scene() );
|
|
||||||
|
|
||||||
bones.write[p_bone].custom_pose_enable = (p_custom_pose != Transform());
|
|
||||||
bones.write[p_bone].custom_pose = p_custom_pose;
|
|
||||||
|
|
||||||
_make_dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform Skeleton::get_bone_custom_pose(int p_bone) const {
|
|
||||||
ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
|
|
||||||
return bones[p_bone].custom_pose;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Skeleton::_make_dirty() {
|
void Skeleton::_make_dirty() {
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
return;
|
return;
|
||||||
@ -981,31 +954,38 @@ Ref<Skin> Skeleton::create_skin_from_rest_transforms() {
|
|||||||
|
|
||||||
skin.instance();
|
skin.instance();
|
||||||
skin->set_bind_count(bones.size());
|
skin->set_bind_count(bones.size());
|
||||||
_update_process_order(); //just in case
|
_update_process_order(); // Just in case.
|
||||||
|
|
||||||
// pose changed, rebuild cache of inverses
|
// Pose changed, rebuild cache of inverses.
|
||||||
const Bone *bonesptr = bones.ptr();
|
const Bone *bonesptr = bones.ptr();
|
||||||
int len = bones.size();
|
int len = bones.size();
|
||||||
|
|
||||||
// calculate global rests and invert them
|
// Calculate global rests and invert them.
|
||||||
Vector<int> bones_to_process = get_parentless_bones();
|
LocalVector<int> bones_to_process;
|
||||||
|
bones_to_process = get_parentless_bones();
|
||||||
while (bones_to_process.size() > 0) {
|
while (bones_to_process.size() > 0) {
|
||||||
int current_bone_idx = bones_to_process[0];
|
int current_bone_idx = bones_to_process[0];
|
||||||
bones_to_process.erase(current_bone_idx);
|
|
||||||
const Bone &b = bonesptr[current_bone_idx];
|
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();
|
||||||
|
|
||||||
// Note: the code below may not work by default. May need to track an integer for the bone pose index order
|
if (b.parent < 0) {
|
||||||
// in the while loop, instead of using current_bone_idx.
|
|
||||||
|
|
||||||
if (b.parent >= 0) {
|
|
||||||
skin->set_bind_pose(current_bone_idx, skin->get_bind_pose(b.parent) * b.rest);
|
|
||||||
} else {
|
|
||||||
skin->set_bind_pose(current_bone_idx, b.rest);
|
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++) {
|
for (int i = 0; i < len; i++) {
|
||||||
//the inverse is what is actually required
|
// The inverse is what is actually required.
|
||||||
skin->set_bind_bone(i, i);
|
skin->set_bind_bone(i, i);
|
||||||
skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse());
|
skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse());
|
||||||
}
|
}
|
||||||
@ -1014,52 +994,14 @@ Ref<Skin> Skeleton::create_skin_from_rest_transforms() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ref<SkinReference> Skeleton::register_skin(const Ref<Skin> &p_skin) {
|
Ref<SkinReference> Skeleton::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()) {
|
for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) {
|
||||||
if (E->get()->skin == p_skin) {
|
if (E->get()->skin == p_skin) {
|
||||||
return Ref<SkinReference>(E->get());
|
return Ref<SkinReference>(E->get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.instance();
|
|
||||||
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
|
|
||||||
Vector<int> bones_to_process = get_parentless_bones();
|
|
||||||
while (bones_to_process.size() > 0) {
|
|
||||||
int current_bone_idx = bones_to_process[0];
|
|
||||||
bones_to_process.erase(current_bone_idx);
|
|
||||||
const Bone &b = bonesptr[current_bone_idx];
|
|
||||||
|
|
||||||
// Note: the code below may not work by default. May need to track an integer for the bone pose index order
|
|
||||||
// in the while loop, instead of using current_bone_idx.
|
|
||||||
if (b.parent >= 0) {
|
|
||||||
skin->set_bind_pose(current_bone_idx, skin->get_bind_pose(b.parent) * b.rest);
|
|
||||||
} else {
|
|
||||||
skin->set_bind_pose(current_bone_idx, b.rest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_FAIL_COND_V(skin.is_null(), Ref<SkinReference>());
|
|
||||||
|
|
||||||
Ref<SkinReference> skin_ref;
|
Ref<SkinReference> skin_ref;
|
||||||
skin_ref.instance();
|
skin_ref.instance();
|
||||||
|
|
||||||
@ -1067,12 +1009,14 @@ Ref<SkinReference> Skeleton::register_skin(const Ref<Skin> &p_skin) {
|
|||||||
skin_ref->bind_count = 0;
|
skin_ref->bind_count = 0;
|
||||||
skin_ref->skeleton = RID_PRIME(VisualServer::get_singleton()->skeleton_create());
|
skin_ref->skeleton = RID_PRIME(VisualServer::get_singleton()->skeleton_create());
|
||||||
skin_ref->skeleton_node = this;
|
skin_ref->skeleton_node = this;
|
||||||
skin_ref->skin = skin;
|
skin_ref->skin = p_skin;
|
||||||
|
|
||||||
skin_bindings.insert(skin_ref.operator->());
|
skin_bindings.insert(skin_ref.operator->());
|
||||||
|
|
||||||
skin->connect("changed", skin_ref.operator->(), "_skin_changed");
|
skin_ref->skin->connect("changed", skin_ref.operator->(), "_skin_changed");
|
||||||
_make_dirty();
|
|
||||||
|
_make_dirty(); // Skin needs to be updated, so update skeleton.
|
||||||
|
|
||||||
return skin_ref;
|
return skin_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1105,61 +1049,33 @@ void Skeleton::force_update_bone_children_transforms(int p_bone_idx) {
|
|||||||
Bone &b = bonesptr[current_bone_idx];
|
Bone &b = bonesptr[current_bone_idx];
|
||||||
bool bone_enabled = b.enabled && !show_rest_only;
|
bool bone_enabled = b.enabled && !show_rest_only;
|
||||||
|
|
||||||
if (b.disable_rest) {
|
if (bone_enabled) {
|
||||||
if (bone_enabled) {
|
b.update_pose_cache();
|
||||||
b.update_pose_cache();
|
Transform pose = b.pose_cache;
|
||||||
Transform 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;
|
|
||||||
}
|
|
||||||
} 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 = Transform();
|
|
||||||
b.pose_global_no_override = b.pose_global;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
if (b.parent >= 0) {
|
||||||
if (bone_enabled) {
|
b.pose_global = bonesptr[b.parent].pose_global * pose;
|
||||||
b.update_pose_cache();
|
b.pose_global_no_override = b.pose_global;
|
||||||
Transform 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;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (b.parent >= 0) {
|
b.pose_global = pose;
|
||||||
b.pose_global = bonesptr[b.parent].pose_global * b.rest;
|
b.pose_global_no_override = b.pose_global;
|
||||||
b.pose_global_no_override = b.pose_global;
|
}
|
||||||
} else {
|
} else {
|
||||||
b.pose_global = b.rest;
|
if (b.parent >= 0) {
|
||||||
b.pose_global_no_override = b.pose_global;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.local_pose_override_amount >= CMP_EPSILON) {
|
if (b.local_pose_override_amount >= CMP_EPSILON) {
|
||||||
Transform override_local_pose;
|
Transform override_local_pose;
|
||||||
if (b.parent >= 0) {
|
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 {
|
} 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);
|
b.pose_global = b.pose_global.interpolate_with(override_local_pose, b.local_pose_override_amount);
|
||||||
}
|
}
|
||||||
@ -1196,9 +1112,10 @@ Transform Skeleton::world_transform_to_global_pose(Transform p_world_transform)
|
|||||||
Transform Skeleton::global_pose_to_local_pose(int p_bone_idx, Transform p_global_pose) {
|
Transform Skeleton::global_pose_to_local_pose(int p_bone_idx, Transform p_global_pose) {
|
||||||
const int bone_size = bones.size();
|
const int bone_size = bones.size();
|
||||||
ERR_FAIL_INDEX_V(p_bone_idx, bone_size, Transform());
|
ERR_FAIL_INDEX_V(p_bone_idx, bone_size, Transform());
|
||||||
|
|
||||||
if (bones[p_bone_idx].parent >= 0) {
|
if (bones[p_bone_idx].parent >= 0) {
|
||||||
int parent_bone_idx = bones[p_bone_idx].parent;
|
int parent_bone_idx = bones[p_bone_idx].parent;
|
||||||
Transform conversion_transform = get_bone_global_pose(parent_bone_idx).affine_inverse();
|
Transform conversion_transform = bones[parent_bone_idx].pose_global.affine_inverse();
|
||||||
return conversion_transform * p_global_pose;
|
return conversion_transform * p_global_pose;
|
||||||
} else {
|
} else {
|
||||||
return p_global_pose;
|
return p_global_pose;
|
||||||
@ -1306,9 +1223,6 @@ void Skeleton::_bind_methods() {
|
|||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("localize_rests"), &Skeleton::localize_rests);
|
ClassDB::bind_method(D_METHOD("localize_rests"), &Skeleton::localize_rests);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_bone_disable_rest", "bone_idx", "disable"), &Skeleton::set_bone_disable_rest);
|
|
||||||
ClassDB::bind_method(D_METHOD("is_bone_rest_disabled", "bone_idx"), &Skeleton::is_bone_rest_disabled);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton::clear_bones);
|
ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton::clear_bones);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_bone_pose", "bone_idx", "pose"), &Skeleton::set_bone_pose);
|
ClassDB::bind_method(D_METHOD("set_bone_pose", "bone_idx", "pose"), &Skeleton::set_bone_pose);
|
||||||
@ -1334,9 +1248,6 @@ void Skeleton::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("set_bone_local_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton::set_bone_local_pose_override, DEFVAL(false));
|
ClassDB::bind_method(D_METHOD("set_bone_local_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton::set_bone_local_pose_override, DEFVAL(false));
|
||||||
ClassDB::bind_method(D_METHOD("get_bone_local_pose_override", "bone_idx"), &Skeleton::get_bone_local_pose_override);
|
ClassDB::bind_method(D_METHOD("get_bone_local_pose_override", "bone_idx"), &Skeleton::get_bone_local_pose_override);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton::get_bone_custom_pose);
|
|
||||||
ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton::set_bone_custom_pose);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("force_update_all_bone_transforms"), &Skeleton::force_update_all_bone_transforms);
|
ClassDB::bind_method(D_METHOD("force_update_all_bone_transforms"), &Skeleton::force_update_all_bone_transforms);
|
||||||
ClassDB::bind_method(D_METHOD("force_update_bone_child_transform", "bone_idx"), &Skeleton::force_update_bone_children_transforms);
|
ClassDB::bind_method(D_METHOD("force_update_bone_child_transform", "bone_idx"), &Skeleton::force_update_bone_children_transforms);
|
||||||
|
|
||||||
|
@ -83,7 +83,6 @@ private:
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
int parent;
|
int parent;
|
||||||
|
|
||||||
bool disable_rest;
|
|
||||||
Transform rest;
|
Transform rest;
|
||||||
|
|
||||||
//Transform pose;
|
//Transform pose;
|
||||||
@ -104,9 +103,6 @@ private:
|
|||||||
Transform pose_global;
|
Transform pose_global;
|
||||||
Transform pose_global_no_override;
|
Transform pose_global_no_override;
|
||||||
|
|
||||||
bool custom_pose_enable;
|
|
||||||
Transform custom_pose;
|
|
||||||
|
|
||||||
float global_pose_override_amount;
|
float global_pose_override_amount;
|
||||||
bool global_pose_override_reset;
|
bool global_pose_override_reset;
|
||||||
Transform global_pose_override;
|
Transform global_pose_override;
|
||||||
@ -130,10 +126,8 @@ private:
|
|||||||
Bone() {
|
Bone() {
|
||||||
parent = -1;
|
parent = -1;
|
||||||
enabled = true;
|
enabled = true;
|
||||||
disable_rest = false;
|
|
||||||
pose_cache_dirty = true;
|
pose_cache_dirty = true;
|
||||||
pose_scale = Vector3(1, 1, 1);
|
pose_scale = Vector3(1, 1, 1);
|
||||||
custom_pose_enable = false;
|
|
||||||
global_pose_override_amount = 0;
|
global_pose_override_amount = 0;
|
||||||
global_pose_override_reset = false;
|
global_pose_override_reset = false;
|
||||||
#ifndef _3D_DISABLED
|
#ifndef _3D_DISABLED
|
||||||
@ -209,9 +203,6 @@ public:
|
|||||||
void remove_bone_child(int p_bone, int p_child);
|
void remove_bone_child(int p_bone, int p_child);
|
||||||
Vector<int> get_parentless_bones();
|
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;
|
int get_bone_count() const;
|
||||||
|
|
||||||
void set_bone_rest(int p_bone, const Transform &p_rest);
|
void set_bone_rest(int p_bone, const Transform &p_rest);
|
||||||
@ -238,9 +229,6 @@ public:
|
|||||||
Quat get_bone_pose_rotation(int p_bone) const;
|
Quat get_bone_pose_rotation(int p_bone) const;
|
||||||
Vector3 get_bone_pose_scale(int p_bone) const;
|
Vector3 get_bone_pose_scale(int p_bone) const;
|
||||||
|
|
||||||
void set_bone_custom_pose(int p_bone, const Transform &p_custom_pose);
|
|
||||||
Transform get_bone_custom_pose(int p_bone) const;
|
|
||||||
|
|
||||||
void clear_bones_global_pose_override();
|
void clear_bones_global_pose_override();
|
||||||
Transform get_bone_global_pose_override(int p_bone) const;
|
Transform get_bone_global_pose_override(int p_bone) const;
|
||||||
void set_bone_global_pose_override(int p_bone, const Transform &p_pose, real_t p_amount, bool p_persistent = false);
|
void set_bone_global_pose_override(int p_bone, const Transform &p_pose, real_t p_amount, bool p_persistent = false);
|
||||||
|
@ -1370,10 +1370,6 @@ void AnimationTree::_process_graph(float p_delta) {
|
|||||||
xform.basis.set_quat_scale(t->rot, t->scale);
|
xform.basis.set_quat_scale(t->rot, t->scale);
|
||||||
|
|
||||||
root_motion_transform = xform;
|
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) {
|
} else if (t->skeleton && t->bone_idx >= 0) {
|
||||||
if (t->loc_used) {
|
if (t->loc_used) {
|
||||||
t->skeleton->set_bone_pose_position(t->bone_idx, t->loc);
|
t->skeleton->set_bone_pose_position(t->bone_idx, t->loc);
|
||||||
|
Loading…
Reference in New Issue
Block a user