This commit is contained in:
2026-03-21 23:10:48 +01:00
parent 8cbb794dba
commit 3153735d0c
18 changed files with 249 additions and 195 deletions

View File

@@ -4,21 +4,17 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <destrum/Util/DeltaTime.h>
#include "spdlog/spdlog.h"
Animator::Animator(GameObject& parent)
: Component(parent, "Animator") {}
// ─── Component interface ──────────────────────────────────────────────────────
void Animator::Update() {
if (!m_current.clip) return;
// Time delta comes from your engine's time system
// const float dt = Time::GetDeltaTime();
const float dt = 0.016f; // ~60 FPS
const float dt = Time::GetInstance().DeltaTime();
m_current.time += dt * m_current.speed;
if (m_current.clip->looped)
@@ -37,11 +33,6 @@ void Animator::Update() {
m_previous = {};
}
}
spdlog::info("Playing '{}': time = {:.2f}s, blend = {:.2f}",
m_currentClipName.empty() ? "(none)" : m_currentClipName.c_str(),
m_current.time,
m_blendT);
}
void Animator::ImGuiInspector() {
@@ -65,8 +56,6 @@ void Animator::ImGuiInspector() {
// }
}
// ─── Animation control ────────────────────────────────────────────────────────
void Animator::addClip(std::shared_ptr<SkeletalAnimation> clip) {
m_clips[clip->name] = std::move(clip);
}
@@ -94,24 +83,18 @@ void Animator::stop() {
m_currentClipName = {};
}
// ─── Joint matrix upload ──────────────────────────────────────────────────────
std::size_t Animator::uploadJointMatrices(SkinningPipeline& pipeline,
const Skeleton& skeleton,
std::size_t frameIndex) {
std::size_t Animator::uploadJointMatrices(const RenderContext& ctx, const Skeleton& skeleton, std::size_t frameIndex) {
auto matrices = computeJointMatrices(skeleton);
return pipeline.appendJointMatrices(matrices, frameIndex);
return ctx.renderer.getSkinningPipeline().appendJointMatrices(matrices, frameIndex);
}
// ─── Private: pose evaluation ─────────────────────────────────────────────────
std::vector<glm::mat4> Animator::computeJointMatrices(const Skeleton& skeleton) {
const std::size_t numJoints = skeleton.joints.size();
std::vector<glm::mat4> global(numJoints, glm::mat4{1.f});
std::vector<glm::mat4> result(numJoints, glm::mat4{1.f});
auto findTrack = [](const SkeletalAnimation* clip,
std::uint32_t idx) -> const SkeletalAnimation::Track* {
std::uint32_t idx) -> const SkeletalAnimation::Track* {
if (!clip) return nullptr;
for (auto& t : clip->tracks)
if (t.jointIndex == idx) return &t;
@@ -123,26 +106,31 @@ std::vector<glm::mat4> Animator::computeJointMatrices(const Skeleton& skeleton)
glm::quat rot = glm::identity<glm::quat>();
glm::vec3 sc = {1.f, 1.f, 1.f};
if (const auto* track = findTrack(m_current.clip, i)) {
tr = sampleTranslation(*track, m_current.time);
rot = sampleRotation (*track, m_current.time);
sc = sampleScale (*track, m_current.time);
}
// Sample current clip if one is playing
if (m_current.clip) {
if (const auto* track = findTrack(m_current.clip, i)) {
tr = sampleTranslation(*track, m_current.time);
rot = sampleRotation (*track, m_current.time);
sc = sampleScale (*track, m_current.time);
}
if (m_previous.clip && m_blendT < 1.f) {
if (const auto* prev = findTrack(m_previous.clip, i)) {
tr = glm::mix (sampleTranslation(*prev, m_previous.time), tr, m_blendT);
rot = glm::slerp(sampleRotation (*prev, m_previous.time), rot, m_blendT);
sc = glm::mix (sampleScale (*prev, m_previous.time), sc, m_blendT);
if (m_previous.clip && m_blendT < 1.f) {
if (const auto* prev = findTrack(m_previous.clip, i)) {
tr = glm::mix (sampleTranslation(*prev, m_previous.time), tr, m_blendT);
rot = glm::slerp(sampleRotation (*prev, m_previous.time), rot, m_blendT);
sc = glm::mix (sampleScale (*prev, m_previous.time), sc, m_blendT);
}
}
}
// If no clip: tr/rot/sc stay as identity → rest pose
glm::mat4 local = glm::translate(glm::mat4{1.f}, tr)
* glm::mat4_cast(rot)
* glm::scale(glm::mat4{1.f}, sc);
const int parent = skeleton.parentIndex[i];
global[i] = (parent < 0) ? local : global[parent] * local;
global[i] = (parent < 0) ? skeleton.rootPreTransform * local
: global[parent] * local;
result[i] = global[i] * skeleton.inverseBindMatrices[i];
}