From ce8547c8d36c06fe82aa2340ef4b13f3572dd27c Mon Sep 17 00:00:00 2001 From: lisyarus Date: Tue, 15 Oct 2024 21:42:00 +0300 Subject: [PATCH] Preprocess glTF rotation animations to force shortest-arc interpolation --- .../gfx/include/psemek/gfx/gltf_animation.hpp | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/libs/gfx/include/psemek/gfx/gltf_animation.hpp b/libs/gfx/include/psemek/gfx/gltf_animation.hpp index a50826e1..dcdb1a63 100644 --- a/libs/gfx/include/psemek/gfx/gltf_animation.hpp +++ b/libs/gfx/include/psemek/gfx/gltf_animation.hpp @@ -98,7 +98,33 @@ namespace psemek::gfx : input_(std::move(input)) , output_(std::move(output)) , interpolation_(interpolation) - {} + { + if constexpr (path == gltf_asset::animation::channel::rotation) + { + if (interpolation == geom::easing_type::linear) + { + for (std::size_t i = 1; i < input_.size(); ++i) + { + if (geom::dot(output_[i - 1].coords, output_[i].coords) < 0.f) + { + output_[i] = - output_[i]; + } + } + } + else if (interpolation == geom::easing_type::cubic) + { + for (std::size_t i = 1; i < input_.size(); ++i) + { + if (geom::dot(output_[3 * (i - 1) + 1].coords, output_[3 * i + 1].coords) < 0.f) + { + output_[3 * i + 0] = - output_[3 * i + 0]; + output_[3 * i + 1] = - output_[3 * i + 1]; + output_[3 * i + 2] = - output_[3 * i + 2]; + } + } + } + } + } gltf_animation_channel(gltf_animation_channel &&) = default;