Minor refactoring

This commit is contained in:
Vladislav Khorev 2026-04-16 15:07:59 +03:00
parent 71346b4227
commit d47cfd1b6b
4 changed files with 86 additions and 108 deletions

View File

@ -196,35 +196,18 @@ namespace ZL
} }
else else
{ {
/*std::cout << "-Processing bone: " << boneName << ", parent: " << boneParent << " " << "sizeof:" << boneParent.size() << " " << strlen("None") <<
int(boneParent[0])<<","<<
int(boneParent[1]) << ","<<
int(boneParent[2]) << ","<<
int(boneParent[3]) << ","<<
int(boneParent[4]) << "," <<
int(boneParent[5]) << ","
<< std::endl;*/
bones[i].parent = getIndexByValue(boneParent, boneNames); bones[i].parent = getIndexByValue(boneParent, boneNames);
} }
for (int j = 0; j < boneChildren[boneName].size(); j++) for (int j = 0; j < boneChildren[boneName].size(); j++)
{ {
//std::cout << "Enumerating bones:" << j << " " << boneName << " " << boneChildren[boneName][j] << std::endl;
bones[i].children.push_back(getIndexByValue(boneChildren[boneName][j], boneNames)); bones[i].children.push_back(getIndexByValue(boneChildren[boneName][j], boneNames));
} }
/*if (boneName == "Bone.020")
{
std::cout << i << std::endl;
}*/
} }
startBones = bones; startBones = bones;
currentBones = bones; currentBones = bones;
///std::cout << "Hello!" << std::endl;
std::getline(f, tempLine); //vertice count std::getline(f, tempLine); //vertice count
int numberVertices; int numberVertices;
@ -258,8 +241,6 @@ namespace ZL
//==== process uv and normals begin //==== process uv and normals begin
//std::cout << "Hello x1" << std::endl;
std::getline(f, tempLine); //===UV Coordinates: std::getline(f, tempLine); //===UV Coordinates:
std::getline(f, tempLine); //triangle count std::getline(f, tempLine); //triangle count
@ -319,19 +300,10 @@ namespace ZL
uvCoords[i][j] = Vector2f{ floatValues[0],floatValues[1] }; uvCoords[i][j] = Vector2f{ floatValues[0],floatValues[1] };
} }
} }
//std::cout << "Hello eee" << std::endl;
std::getline(f, tempLine); //===Normals: std::getline(f, tempLine); //===Normals:
std::vector<Vector3f> normals; std::vector<Vector3f> normals;
normals.resize(numberVertices); normals.resize(numberVertices);
@ -436,8 +408,6 @@ namespace ZL
std::getline(f, tempLine);//=== Animation Keyframes === std::getline(f, tempLine);//=== Animation Keyframes ===
std::getline(f, tempLine);//=== Bone Transforms per Keyframe === std::getline(f, tempLine);//=== Bone Transforms per Keyframe ===
std::getline(f, tempLine); std::getline(f, tempLine);
int numberKeyFrames; int numberKeyFrames;
@ -466,11 +436,6 @@ namespace ZL
throw std::runtime_error("No number found in the input string."); throw std::runtime_error("No number found in the input string.");
} }
/*if (i == 0)
{
startingFrame = numberFrame;
}*/
animations[0].keyFrames[i].frame = numberFrame; animations[0].keyFrames[i].frame = numberFrame;
animations[0].keyFrames[i].bones.resize(numberBones); animations[0].keyFrames[i].bones.resize(numberBones);
@ -479,7 +444,7 @@ namespace ZL
{ {
std::getline(f, tempLine); std::getline(f, tempLine);
std::string boneName = tempLine.substr(8); std::string boneName = tempLine.substr(8);
//std::cout << "Processing keyframe " << i << ", bone: " << j << " " << boneName << std::endl;
int boneNumber = getIndexByValue(boneName, boneNames); int boneNumber = getIndexByValue(boneName, boneNames);
animations[0].keyFrames[i].bones[boneNumber] = startBones[boneNumber]; animations[0].keyFrames[i].bones[boneNumber] = startBones[boneNumber];
@ -516,7 +481,6 @@ namespace ZL
animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[0 + 2 * 4] = floatValues[2]; animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[0 + 2 * 4] = floatValues[2];
animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[0 + 3 * 4] = floatValues[3]; animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[0 + 3 * 4] = floatValues[3];
std::getline(f, tempLine); std::getline(f, tempLine);
b = tempLine.cbegin(); b = tempLine.cbegin();
e = tempLine.cend(); e = tempLine.cend();
@ -544,8 +508,6 @@ namespace ZL
animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2 + 1 * 4] = floatValues[1]; animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2 + 1 * 4] = floatValues[1];
animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2 + 2 * 4] = floatValues[2]; animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2 + 2 * 4] = floatValues[2];
animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2 + 3 * 4] = floatValues[3]; animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2 + 3 * 4] = floatValues[3];
std::getline(f, tempLine); std::getline(f, tempLine);
b = tempLine.cbegin(); b = tempLine.cbegin();
e = tempLine.cend(); e = tempLine.cend();
@ -560,8 +522,6 @@ namespace ZL
animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[3 + 2 * 4] = floatValues[2]; animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[3 + 2 * 4] = floatValues[2];
animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[3 + 3 * 4] = floatValues[3]; animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[3 + 3 * 4] = floatValues[3];
//std::getline(f, tempLine);// ignore last matrix line
//=============== Matrix end ================== //=============== Matrix end ==================
} }
@ -587,6 +547,14 @@ namespace ZL
} }
startMesh = mesh; startMesh = mesh;
if (startBones.size() > MAX_GPU_BONES)
{
std::cout << "Warning: model has " << startBones.size()
<< " bones, exceeding GPU skinning limit of " << MAX_GPU_BONES << std::endl;
//throw std::runtime_error("Too many bones for GPU skinning");
}
} }
void BoneSystem::LoadFromBinaryFile(const std::string& fileName, const std::string& ZIPFileName) void BoneSystem::LoadFromBinaryFile(const std::string& fileName, const std::string& ZIPFileName)
@ -747,49 +715,57 @@ namespace ZL
} }
startMesh = mesh; startMesh = mesh;
}
void BoneSystem::PrepareGpuSkinningData()
{
size_t vertexCount = verticesBoneWeight.size();
gpuBoneData.boneIndices0.resize(vertexCount);
gpuBoneData.boneIndices1.resize(vertexCount);
gpuBoneData.boneWeights0.resize(vertexCount);
gpuBoneData.boneWeights1.resize(vertexCount);
for (size_t i = 0; i < vertexCount; i++)
{
gpuBoneData.boneIndices0[i] = Vector4f(
static_cast<float>(max(0, verticesBoneWeight[i][0].boneIndex)),
static_cast<float>(max(0, verticesBoneWeight[i][1].boneIndex)),
static_cast<float>(max(0, verticesBoneWeight[i][2].boneIndex)),
static_cast<float>(max(0, verticesBoneWeight[i][3].boneIndex))
);
gpuBoneData.boneIndices1[i] = Vector2f(
static_cast<float>(max(0, verticesBoneWeight[i][4].boneIndex)),
static_cast<float>(max(0, verticesBoneWeight[i][5].boneIndex))
);
gpuBoneData.boneWeights0[i] = Vector4f(
verticesBoneWeight[i][0].weight,
verticesBoneWeight[i][1].weight,
verticesBoneWeight[i][2].weight,
verticesBoneWeight[i][3].weight
);
gpuBoneData.boneWeights1[i] = Vector2f(
verticesBoneWeight[i][4].weight,
verticesBoneWeight[i][5].weight
);
}
gpuBoneData.prepared = true;
if (startBones.size() > MAX_GPU_BONES) if (startBones.size() > MAX_GPU_BONES)
{ {
std::cout << "Warning: model has " << startBones.size() std::cout << "Warning: model has " << startBones.size()
<< " bones, exceeding GPU skinning limit of " << MAX_GPU_BONES << std::endl; << " bones, exceeding GPU skinning limit of " << MAX_GPU_BONES << std::endl;
//throw std::runtime_error("Too many bones for GPU skinning");
} }
} }
void GpuBoneData::PrepareGpuSkinningData(const std::vector<std::array<BoneWeight, MAX_BONE_COUNT>>& verticesBoneWeight)
{
size_t vertexCount = verticesBoneWeight.size();
boneIndices0.resize(vertexCount);
boneIndices1.resize(vertexCount);
boneWeights0.resize(vertexCount);
boneWeights1.resize(vertexCount);
for (size_t i = 0; i < vertexCount; i++)
{
boneIndices0[i] = Vector4f(
static_cast<float>(max(0, verticesBoneWeight[i][0].boneIndex)),
static_cast<float>(max(0, verticesBoneWeight[i][1].boneIndex)),
static_cast<float>(max(0, verticesBoneWeight[i][2].boneIndex)),
static_cast<float>(max(0, verticesBoneWeight[i][3].boneIndex))
);
boneIndices1[i] = Vector2f(
static_cast<float>(max(0, verticesBoneWeight[i][4].boneIndex)),
static_cast<float>(max(0, verticesBoneWeight[i][5].boneIndex))
);
boneWeights0[i] = Vector4f(
verticesBoneWeight[i][0].weight,
verticesBoneWeight[i][1].weight,
verticesBoneWeight[i][2].weight,
verticesBoneWeight[i][3].weight
);
boneWeights1[i] = Vector2f(
verticesBoneWeight[i][4].weight,
verticesBoneWeight[i][5].weight
);
}
prepared = true;
/*
if (startBones.size() > MAX_GPU_BONES)
{
std::cout << "Warning: model has " << startBones.size()
<< " bones, exceeding GPU skinning limit of " << MAX_GPU_BONES << std::endl;
}*/
}
void BoneSystem::ComputeSkinningMatrices(int frame, std::vector<Matrix4f>& outMatrices) const void BoneSystem::ComputeSkinningMatrices(int frame, std::vector<Matrix4f>& outMatrices) const
{ {
int startingKeyFrame = -1; int startingKeyFrame = -1;

View File

@ -42,6 +42,7 @@ namespace ZL
std::vector<Vector4f> boneWeights0; // bone weights 0-3 per vertex std::vector<Vector4f> boneWeights0; // bone weights 0-3 per vertex
std::vector<Vector2f> boneWeights1; // bone weights 4-5 per vertex std::vector<Vector2f> boneWeights1; // bone weights 4-5 per vertex
bool prepared = false; bool prepared = false;
void PrepareGpuSkinningData(const std::vector<std::array<BoneWeight, MAX_BONE_COUNT>>& verticesBoneWeight);
}; };
struct BoneSystem struct BoneSystem
@ -65,12 +66,26 @@ namespace ZL
void Interpolate(int frame); void Interpolate(int frame);
// GPU skinning: prepare per-vertex bone data for VBO upload
void PrepareGpuSkinningData();
// GPU skinning: compute skinning matrices without modifying the mesh // GPU skinning: compute skinning matrices without modifying the mesh
void ComputeSkinningMatrices(int frame, std::vector<Matrix4f>& outMatrices) const; 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;
};

View File

@ -291,24 +291,24 @@ void Character::draw(Renderer& renderer) {
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix()); renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
auto& anim = it->second; auto& anim = it->second;
anim.modelMutable.AssignFrom(anim.model.mesh); modelMutable.AssignFrom(anim.model.mesh);
anim.modelMutable.RefreshVBO(); modelMutable.RefreshVBO();
glBindTexture(GL_TEXTURE_2D, texture->getTexID()); glBindTexture(GL_TEXTURE_2D, texture->getTexID());
renderer.DrawVertexRenderStruct(anim.modelMutable); renderer.DrawVertexRenderStruct(modelMutable);
renderer.PopMatrix(); renderer.PopMatrix();
renderer.PopProjectionMatrix(); renderer.PopProjectionMatrix();
renderer.shaderManager.PopShader(); renderer.shaderManager.PopShader();
} }
void Character::prepareGpuSkinningVBOs(AnimationData& anim) { void Character::prepareGpuSkinningVBOs(BoneAnimationData& anim) {
if (anim.gpuSkinningPrepared) if (anim.gpuSkinningPrepared)
{ {
return; return;
} }
anim.model.PrepareGpuSkinningData(); anim.model.gpuBoneData.PrepareGpuSkinningData(anim.model.verticesBoneWeight);
// Upload bind-pose mesh (static, done once) // Upload bind-pose mesh (static, done once)
anim.bindPoseMutable.AssignFrom(anim.model.startMesh); anim.bindPoseMutable.AssignFrom(anim.model.startMesh);
@ -443,9 +443,9 @@ void Character::drawShadowDepthCpu(Renderer& renderer) {
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix()); renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
auto& anim = it->second; auto& anim = it->second;
anim.modelMutable.AssignFrom(anim.model.mesh); modelMutable.AssignFrom(anim.model.mesh);
anim.modelMutable.RefreshVBO(); modelMutable.RefreshVBO();
renderer.DrawVertexRenderStruct(anim.modelMutable); renderer.DrawVertexRenderStruct(modelMutable);
renderer.PopMatrix(); renderer.PopMatrix();
} }
@ -550,10 +550,10 @@ void Character::drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lig
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix()); renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
auto& anim = it->second; auto& anim = it->second;
anim.modelMutable.AssignFrom(anim.model.mesh); modelMutable.AssignFrom(anim.model.mesh);
anim.modelMutable.RefreshVBO(); modelMutable.RefreshVBO();
glBindTexture(GL_TEXTURE_2D, texture->getTexID()); glBindTexture(GL_TEXTURE_2D, texture->getTexID());
renderer.DrawVertexRenderStruct(anim.modelMutable); renderer.DrawVertexRenderStruct(modelMutable);
renderer.PopMatrix(); renderer.PopMatrix();
renderer.PopProjectionMatrix(); renderer.PopProjectionMatrix();

View File

@ -29,7 +29,7 @@ public:
void loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = ""); void loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = "");
void loadBinaryAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = ""); void loadBinaryAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = "");
// void setTexture(std::shared_ptr<Texture> texture);
void setTexture(std::shared_ptr<Texture> texture) { void setTexture(std::shared_ptr<Texture> texture) {
this->texture = texture; this->texture = texture;
} }
@ -38,6 +38,7 @@ public:
// From Python you can chain further commands (walk, wait, trigger others). // From Python you can chain further commands (walk, wait, trigger others).
void setTarget(const Eigen::Vector3f& target, void setTarget(const Eigen::Vector3f& target,
std::function<void()> onArrived = nullptr); std::function<void()> onArrived = nullptr);
void setPathPlanner(PathPlanner planner); void setPathPlanner(PathPlanner planner);
void draw(Renderer& renderer); void draw(Renderer& renderer);
void drawShadowDepth(Renderer& renderer); void drawShadowDepth(Renderer& renderer);
@ -70,29 +71,15 @@ public:
Character* attackTarget = nullptr; Character* attackTarget = nullptr;
bool isPlayer = false; bool isPlayer = false;
bool useGpuSkinning = true; bool useGpuSkinning = true;
//bool useGpuSkinning = false;
float interactionRadius = 0.0f; float interactionRadius = 0.0f;
private: private:
struct AnimationData {
BoneSystem model;
VertexRenderStruct modelMutable;
float currentFrame = 0.f;
int lastFrame = -1;
int totalFrames = 1;
// GPU skinning data (lazily initialized) std::map<AnimationState, BoneAnimationData> animations;
VertexRenderStruct bindPoseMutable; VertexRenderStruct modelMutable;
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;
};
std::map<AnimationState, AnimationData> animations;
std::shared_ptr<Texture> texture; std::shared_ptr<Texture> texture;
Eigen::Vector3f walkTarget = Eigen::Vector3f(0.f, 0.f, 0.f); Eigen::Vector3f walkTarget = Eigen::Vector3f(0.f, 0.f, 0.f);
@ -111,7 +98,7 @@ private:
AnimationState resolveActiveState() const; AnimationState resolveActiveState() const;
// GPU skinning: prepare per-animation VBOs (called lazily on first draw) // GPU skinning: prepare per-animation VBOs (called lazily on first draw)
void prepareGpuSkinningVBOs(AnimationData& anim); void prepareGpuSkinningVBOs(BoneAnimationData& anim);
// GPU skinning: draw using shader-based skinning // GPU skinning: draw using shader-based skinning
void drawGpuSkinning(Renderer& renderer); void drawGpuSkinning(Renderer& renderer);
// Shadow: draw into depth map (no texture, no projection push) // Shadow: draw into depth map (no texture, no projection push)