#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; // boneVector = boneLength * (0, 1, 0) � ���� �������� // Then multiply by 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; GpuBoneData gpuBoneData; 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 BoneAnimationData { BoneSystem model; float currentFrame = 0.f; int lastFrame = -1; int totalFrames = 1; // 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(); }; };