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())
{
@ -75,7 +75,9 @@ void game::MeshInstance::PlayAnim(const std::string& name)
const auto& skeleton = mesh_->GetSkeleton();
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()
@ -119,28 +121,42 @@ const gfx::UniformBuffer<glm::mat4>& game::MeshInstance::GetBoneUBO()
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)
{
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 frame0 = frame_i % num_anim_frames;
size_t frame1 = (frame_i + 1) % num_anim_frames;
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];
const Transform* t0 = channel.frames[frame0];

View File

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