94 lines
2.3 KiB
C++
94 lines
2.3 KiB
C++
#pragma once
|
||
#include "render/Renderer.h"
|
||
#include <unordered_map>
|
||
|
||
|
||
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) <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// Then multiply by boneMatrixWorld <20> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
int parent;
|
||
std::vector<int> children;
|
||
};
|
||
|
||
struct BoneWeight
|
||
{
|
||
int boneIndex = -1;
|
||
float weight = 0;
|
||
};
|
||
|
||
struct AnimationKeyFrame
|
||
{
|
||
int frame;
|
||
std::vector<Bone> bones;
|
||
};
|
||
|
||
struct Animation
|
||
{
|
||
std::vector<AnimationKeyFrame> keyFrames;
|
||
};
|
||
|
||
struct GpuBoneData {
|
||
std::vector<Vector4f> boneIndices0; // bone indices 0-3 per vertex (as float)
|
||
std::vector<Vector2f> boneIndices1; // bone indices 4-5 per vertex
|
||
std::vector<Vector4f> boneWeights0; // bone weights 0-3 per vertex
|
||
std::vector<Vector2f> boneWeights1; // bone weights 4-5 per vertex
|
||
bool prepared = false;
|
||
void PrepareGpuSkinningData(const std::vector<std::array<BoneWeight, MAX_BONE_COUNT>>& verticesBoneWeight);
|
||
};
|
||
|
||
struct BoneSystem
|
||
{
|
||
VertexDataStruct mesh;
|
||
VertexDataStruct startMesh;
|
||
std::vector<std::array<BoneWeight, MAX_BONE_COUNT>> verticesBoneWeight;
|
||
|
||
Matrix4f armatureMatrix;
|
||
|
||
std::vector<Bone> startBones;
|
||
std::vector<Bone> currentBones;
|
||
|
||
std::vector<Animation> 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<Matrix4f>& 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<VBOHolder> boneIndices0VBO;
|
||
std::shared_ptr<VBOHolder> boneIndices1VBO;
|
||
std::shared_ptr<VBOHolder> boneWeights0VBO;
|
||
std::shared_ptr<VBOHolder> boneWeights1VBO;
|
||
bool gpuSkinningPrepared = false;
|
||
std::vector<Eigen::Matrix4f> skinningMatrices;
|
||
|
||
void prepareGpuSkinningVBOs();
|
||
};
|
||
|
||
|
||
|
||
|
||
}; |