#pragma once #include "render/Renderer.h" #include namespace ZL { constexpr int MAX_BONE_COUNT = 6; constexpr int MAX_GPU_BONES = 64; struct Bone { Vector3f boneStartWorld; float boneLength; Matrix4f boneMatrixWorld; int parent; std::vector children; }; struct BoneWeight { int boneIndex = -1; float weight = 0; }; struct AnimationKeyFrame { int frame; std::vector bones; }; struct Animation { std::vector keyFrames; }; struct GpuBoneData { std::vector boneIndices0; // bone indices 0-3 per vertex (as float) std::vector boneIndices1; // bone indices 4-5 per vertex std::vector boneWeights0; // bone weights 0-3 per vertex std::vector boneWeights1; // bone weights 4-5 per vertex bool prepared = false; void PrepareGpuSkinningData(const std::vector>& verticesBoneWeight); }; struct BoneSystem { VertexDataStruct mesh; VertexDataStruct startMesh; std::vector> verticesBoneWeight; Matrix4f armatureMatrix; std::vector startBones; std::vector currentBones; std::vector animations; int startingFrame = 0; void LoadFromFile(const std::string& fileName, const std::string& ZIPFileName = ""); void LoadFromBinaryFile(const std::string& fileName, const std::string& ZIPFileName = ""); void Interpolate(int frame); // GPU skinning: compute skinning matrices without modifying the mesh //void ComputeSkinningMatrices(int frame, std::vector& outMatrices) const; }; struct GpuSkinningShaderData { GpuBoneData gpuBoneData; // GPU skinning data (lazily initialized) VertexRenderStruct bindPoseMutable; std::shared_ptr boneIndices0VBO; std::shared_ptr boneIndices1VBO; std::shared_ptr boneWeights0VBO; std::shared_ptr boneWeights1VBO; bool gpuSkinningPrepared = false; std::vector skinningMatrices; void prepareGpuSkinningVBOs(BoneSystem& model); void RenderVBO(Renderer& renderer); void ComputeSkinningMatrices(const std::vector& startBones, const std::vector& keyFrames, int frame); }; struct BoneAnimationData { BoneSystem model; float currentFrame = 0.f; int lastFrame = -1; int totalFrames = 1; GpuSkinningShaderData gpuSkinningShaderData; }; };