From 3bb0725e3e0aec00b3c2eb2c898357697386ca47 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Wed, 31 Dec 2025 20:30:28 +0100 Subject: [PATCH] Properly applying both translation and rotation to bones. --- synced_animation_graph.cpp | 33 +++++------ synced_animation_node.cpp | 51 ++++++++-------- synced_animation_node.h | 115 ++++++++++++++++++------------------- 3 files changed, 99 insertions(+), 100 deletions(-) diff --git a/synced_animation_graph.cpp b/synced_animation_graph.cpp index 8805c08..5599305 100644 --- a/synced_animation_graph.cpp +++ b/synced_animation_graph.cpp @@ -306,29 +306,26 @@ void SyncedAnimationGraph::_apply_animation_data(const AnimationData &output_dat for (const KeyValue &K : output_data.track_values) { const AnimationData::TrackValue *track_value = K.value; switch (track_value->type) { - case AnimationData::TrackType::TYPE_POSITION_3D: { - const AnimationData::PositionTrackValue *position_value = static_cast(track_value); - - NodePath path = position_value->track->path; - - if (path.get_subname_count() == 1) { - int bone_idx = graph_context.skeleton_3d->find_bone(path.get_subname(0)); - if (bone_idx != -1) { - graph_context.skeleton_3d->set_bone_pose_position(position_value->bone_idx, position_value->position); - } - } - - break; - } + case AnimationData::TrackType::TYPE_POSITION_3D: case AnimationData::TrackType::TYPE_ROTATION_3D: { - const AnimationData::RotationTrackValue *rotation_value = static_cast(track_value); + const AnimationData::TransformTrackValue *transform_track_value = static_cast(track_value); - NodePath path = rotation_value->track->path; + int bone_idx = -1; + NodePath path = transform_track_value->track->path; if (path.get_subname_count() == 1) { - int bone_idx = graph_context.skeleton_3d->find_bone(path.get_subname(0)); + bone_idx = graph_context.skeleton_3d->find_bone(path.get_subname(0)); + if (bone_idx != -1) { - graph_context.skeleton_3d->set_bone_pose_rotation(rotation_value->bone_idx, rotation_value->rotation); + if (transform_track_value->loc_used) { + graph_context.skeleton_3d->set_bone_pose_position(transform_track_value->bone_idx, transform_track_value->loc); + } + + if (transform_track_value->rot_used) { + graph_context.skeleton_3d->set_bone_pose_rotation(transform_track_value->bone_idx, transform_track_value->rot); + } + } else { + assert(false && "Not yet implemented!"); } } diff --git a/synced_animation_node.cpp b/synced_animation_node.cpp index 32a5563..bc66892 100644 --- a/synced_animation_node.cpp +++ b/synced_animation_node.cpp @@ -140,7 +140,7 @@ void AnimationData::sample_from_animation(const Ref &animation, const int count = tracks.size(); for (int i = 0; i < count; i++) { - AnimationData::TrackValue *track_value = nullptr; + TrackValue *track_value = nullptr; const Animation::Track *animation_track = tracks_ptr[i]; const NodePath &track_node_path = animation_track->path; if (!animation_track->enabled) { @@ -149,38 +149,43 @@ void AnimationData::sample_from_animation(const Ref &animation, const Animation::TrackType ttype = animation_track->type; switch (ttype) { - case Animation::TYPE_POSITION_3D: { - AnimationData::PositionTrackValue *position_track_value = memnew(AnimationData::PositionTrackValue); - - if (track_node_path.get_subname_count() == 1) { - int bone_idx = skeleton_3d->find_bone(track_node_path.get_subname(0)); - if (bone_idx != -1) { - position_track_value->bone_idx = bone_idx; - } - animation->try_position_track_interpolate(i, p_time, &position_track_value->position); - } else { - // TODO - assert(false && !"Not yet implemented"); - } - - track_value = position_track_value; - break; - } + case Animation::TYPE_POSITION_3D: case Animation::TYPE_ROTATION_3D: { - AnimationData::RotationTrackValue *rotation_track_value = memnew(AnimationData::RotationTrackValue); + TransformTrackValue *transform_track_value = nullptr; + if (track_values.has(animation_track->thash)) { + transform_track_value = static_cast(track_values[animation_track->thash]); + } else { + transform_track_value = memnew(AnimationData::TransformTrackValue); + } + int bone_idx = -1; if (track_node_path.get_subname_count() == 1) { - int bone_idx = skeleton_3d->find_bone(track_node_path.get_subname(0)); + bone_idx = skeleton_3d->find_bone(track_node_path.get_subname(0)); if (bone_idx != -1) { - rotation_track_value->bone_idx = bone_idx; + transform_track_value->bone_idx = bone_idx; + switch (ttype) { + case Animation::TYPE_POSITION_3D: { + animation->try_position_track_interpolate(i, p_time, &transform_track_value->loc); + transform_track_value->loc_used = true; + break; + } + case Animation::TYPE_ROTATION_3D: { + animation->try_rotation_track_interpolate(i, p_time, &transform_track_value->rot); + transform_track_value->rot_used = true; + break; + } + default: { + assert(false && !"Not yet implemented"); + break; + } + } } - animation->try_rotation_track_interpolate(i, p_time, &rotation_track_value->rotation); } else { // TODO assert(false && !"Not yet implemented"); } - track_value = rotation_track_value; + track_value = transform_track_value; break; } default: { diff --git a/synced_animation_node.h b/synced_animation_node.h index 5776ce6..dd44ef9 100644 --- a/synced_animation_node.h +++ b/synced_animation_node.h @@ -51,68 +51,65 @@ struct AnimationData { } }; - struct PositionTrackValue : public TrackValue { + struct TransformTrackValue : public TrackValue { int bone_idx = -1; - Vector3 position = Vector3(0, 0, 0); - PositionTrackValue() { type = TYPE_POSITION_3D; } - void blend(const TrackValue &to_value, const float lambda) override { - const PositionTrackValue *to_value_casted = &static_cast(to_value); - assert(bone_idx == to_value_casted->bone_idx); - position = (1. - lambda) * position + lambda * to_value_casted->position; - } - - bool operator==(const TrackValue &other_value) const override { - if (type != other_value.type) { - return false; - } - - const PositionTrackValue *other_value_casted = &static_cast(other_value); - return bone_idx == other_value_casted->bone_idx && position == other_value_casted->position; - } - - TrackValue *clone() const override { - PositionTrackValue *result = memnew(PositionTrackValue); - result->track = track; - result->bone_idx = bone_idx; - result->position = position; - return result; - } - }; - - struct RotationTrackValue : public TrackValue { - int bone_idx = -1; - Quaternion rotation = Quaternion(0, 0, 0, 1); - RotationTrackValue() { type = TYPE_ROTATION_3D; } - - void blend(const TrackValue &to_value, const float lambda) override { - const RotationTrackValue *to_value_casted = &static_cast(to_value); - assert(bone_idx == to_value_casted->bone_idx); - rotation = rotation.slerp(to_value_casted->rotation, lambda); - } - - bool operator==(const TrackValue &other_value) const override { - if (type != other_value.type) { - return false; - } - - const RotationTrackValue *other_value_casted = &static_cast(other_value); - return bone_idx == other_value_casted->bone_idx && rotation == other_value_casted->rotation; - } - - TrackValue *clone() const override { - RotationTrackValue *result = memnew(RotationTrackValue); - result->track = track; - result->bone_idx = bone_idx; - result->rotation = rotation; - return result; - } - }; - - struct ScaleTrackValue : public TrackValue { - int bone_idx = -1; + bool loc_used = false; + bool rot_used = false; + bool scale_used = false; + Vector3 init_loc = Vector3(0, 0, 0); + Quaternion init_rot = Quaternion(0, 0, 0, 1); + Vector3 init_scale = Vector3(1, 1, 1); + Vector3 loc; + Quaternion rot; Vector3 scale; - ScaleTrackValue() { type = TYPE_SCALE_3D; } + + TransformTrackValue() { type = TYPE_POSITION_3D; } + + void blend(const TrackValue &to_value, const float lambda) override { + const TransformTrackValue *to_value_casted = &static_cast(to_value); + assert(bone_idx == to_value_casted->bone_idx); + if (loc_used) { + loc = (1. - lambda) * loc + lambda * to_value_casted->loc; + } + + if (rot_used) { + rot = rot.slerp(to_value_casted->rot, lambda); + } + + if (scale_used) { + scale = (1. - lambda) * scale + lambda * to_value_casted->scale; + } + } + + bool operator==(const TrackValue &other_value) const override { + if (type != other_value.type) { + return false; + } + + const TransformTrackValue *other_value_casted = &static_cast(other_value); + return bone_idx == other_value_casted->bone_idx && loc == other_value_casted->loc && rot == other_value_casted->rot && scale == other_value_casted->scale; + } + + TrackValue *clone() const override { + TransformTrackValue *result = memnew(TransformTrackValue); + result->track = track; + result->bone_idx = bone_idx; + + result->loc_used = loc_used; + result->rot_used = rot_used; + result->scale_used = scale_used; + + result->init_loc = init_loc; + result->init_rot = init_rot; + result->init_scale = init_scale; + + result->loc = loc; + result->rot = rot; + result->scale = scale; + + return result; + } }; AnimationData() = default;