Properly applying both translation and rotation to bones.

This commit is contained in:
Martin Felis 2025-12-31 20:30:28 +01:00
parent 69bb2d7980
commit 3bb0725e3e
3 changed files with 99 additions and 100 deletions

View File

@ -306,29 +306,26 @@ void SyncedAnimationGraph::_apply_animation_data(const AnimationData &output_dat
for (const KeyValue<Animation::TypeHash, AnimationData::TrackValue *> &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<const AnimationData::PositionTrackValue *>(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<const AnimationData::RotationTrackValue *>(track_value);
const AnimationData::TransformTrackValue *transform_track_value = static_cast<const AnimationData::TransformTrackValue *>(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!");
}
}

View File

@ -140,7 +140,7 @@ void AnimationData::sample_from_animation(const Ref<Animation> &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> &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<TransformTrackValue *>(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: {

View File

@ -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<const PositionTrackValue &>(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<const PositionTrackValue &>(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<const RotationTrackValue &>(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<const RotationTrackValue &>(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<const TransformTrackValue &>(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<const TransformTrackValue &>(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;