Enhance anim playback

This commit is contained in:
tovjemam 2025-09-09 00:59:48 +02:00
parent 251871c776
commit e982cd73a8
2 changed files with 36 additions and 11 deletions

View File

@ -65,7 +65,7 @@ void game::MeshInstance::UpdateBoneMatrices()
} }
} }
void game::MeshInstance::PlayAnim(const std::string& name) void game::MeshInstance::PlayAnim(const std::string& name, int flags)
{ {
if (!IsSkeletal()) if (!IsSkeletal())
{ {
@ -75,7 +75,9 @@ void game::MeshInstance::PlayAnim(const std::string& name)
const auto& skeleton = mesh_->GetSkeleton(); const auto& skeleton = mesh_->GetSkeleton();
current_anim_ = skeleton->GetAnimation(name); // Can be nullptr current_anim_ = skeleton->GetAnimation(name); // Can be nullptr
anim_time_ = 0.0f; anim_start_ = *time_ptr_;
anim_flags_ = flags;
anim_done_ = false;
} }
void game::MeshInstance::Update() void game::MeshInstance::Update()
@ -119,28 +121,42 @@ const gfx::UniformBuffer<glm::mat4>& game::MeshInstance::GetBoneUBO()
void game::MeshInstance::ApplyAnimFrame() void game::MeshInstance::ApplyAnimFrame()
{ {
ApplySkelAnim(current_anim_, anim_time_, 1.0f); if (!current_anim_)
{
return; // No animation to apply
}
float anim_time = *time_ptr_ - anim_start_;
float anim_duration = current_anim_->GetDuration();
if (!(anim_flags_ & ANIM_LOOP) && anim_time >= anim_duration)
{
anim_done_ = true;
anim_time = anim_duration;
}
ApplySkelAnim(*current_anim_, anim_time, 1.0f);
} }
void game::MeshInstance::ApplySkelAnim(const assets::Animation* anim, float time, float weight) void game::MeshInstance::ApplySkelAnim(const assets::Animation& anim, float time, float weight)
{ {
float anim_frame = (*time_ptr_ - time) * anim->GetTPS(); float anim_frame = time * anim.GetTPS();
if (anim_frame < 0.0f) if (anim_frame < 0.0f)
{ {
anim_frame = 0.0f; anim_frame = 0.0f;
} }
size_t num_anim_frames = anim->GetNumFrames(); size_t num_anim_frames = anim.GetNumFrames();
size_t frame_i = static_cast<size_t>(anim_frame); size_t frame_i = static_cast<size_t>(anim_frame);
size_t frame0 = frame_i % num_anim_frames; size_t frame0 = frame_i % num_anim_frames;
size_t frame1 = (frame_i + 1) % num_anim_frames; size_t frame1 = (frame_i + 1) % num_anim_frames;
float t = anim_frame - static_cast<float>(frame_i); float t = anim_frame - static_cast<float>(frame_i);
for (size_t i = 0; i < anim->GetNumChannels(); ++i) for (size_t i = 0; i < anim.GetNumChannels(); ++i)
{ {
const assets::AnimationChannel& channel = anim->GetChannel(i); const assets::AnimationChannel& channel = anim.GetChannel(i);
TransformNode& node = bone_nodes_[channel.bone_index]; TransformNode& node = bone_nodes_[channel.bone_index];
const Transform* t0 = channel.frames[frame0]; const Transform* t0 = channel.frames[frame0];

View File

@ -6,6 +6,11 @@
namespace game namespace game
{ {
enum PlayAnimFlags
{
ANIM_LOOP = 1 << 0,
};
class MeshInstance class MeshInstance
{ {
std::shared_ptr<const assets::Mesh> mesh_; std::shared_ptr<const assets::Mesh> mesh_;
@ -20,14 +25,16 @@ namespace game
bool bone_ubo_dirty_ = true; bool bone_ubo_dirty_ = true;
const assets::Animation* current_anim_ = nullptr; const assets::Animation* current_anim_ = nullptr;
float anim_time_ = 0.0f; float anim_start_ = 0.0f;
int anim_flags_ = 0;
bool anim_done_ = false;
public: public:
MeshInstance(std::shared_ptr<const assets::Mesh> mesh, const TransformNode* root_node, const float* time_ptr); MeshInstance(std::shared_ptr<const assets::Mesh> mesh, const TransformNode* root_node, const float* time_ptr);
bool IsSkeletal() const { return skeletal_; } bool IsSkeletal() const { return skeletal_; }
void PlayAnim(const std::string& name); void PlayAnim(const std::string& name, int flags = 0);
void Update(); void Update();
@ -38,6 +45,8 @@ namespace game
const TransformNode& GetBoneNode(size_t index) const { return bone_nodes_[index]; } const TransformNode& GetBoneNode(size_t index) const { return bone_nodes_[index]; }
const TransformNode* GetBoneNodeByName(const std::string& name) const; const TransformNode* GetBoneNodeByName(const std::string& name) const;
bool AnimDone() const { return anim_done_; }
private: private:
void SetupBoneNodes(); void SetupBoneNodes();
void UpdateBoneMatrices(); void UpdateBoneMatrices();
@ -47,7 +56,7 @@ namespace game
virtual void ApplyAnimFrame(); virtual void ApplyAnimFrame();
private: private:
void ApplySkelAnim(const assets::Animation* anim, float time, float weight); void ApplySkelAnim(const assets::Animation& anim, float time, float weight);
}; };
} }