diff --git a/src/BoneAnimatedModel.cpp b/src/BoneAnimatedModel.cpp index 40d6799..710cf03 100644 --- a/src/BoneAnimatedModel.cpp +++ b/src/BoneAnimatedModel.cpp @@ -196,35 +196,18 @@ namespace ZL } 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); } 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)); } - - /*if (boneName == "Bone.020") - { - std::cout << i << std::endl; - }*/ } startBones = bones; currentBones = bones; - ///std::cout << "Hello!" << std::endl; - std::getline(f, tempLine); //vertice count int numberVertices; @@ -258,8 +241,6 @@ namespace ZL //==== process uv and normals begin - //std::cout << "Hello x1" << std::endl; - std::getline(f, tempLine); //===UV Coordinates: std::getline(f, tempLine); //triangle count @@ -319,19 +300,10 @@ namespace ZL uvCoords[i][j] = Vector2f{ floatValues[0],floatValues[1] }; } - - - - - - } - //std::cout << "Hello eee" << std::endl; - std::getline(f, tempLine); //===Normals: - std::vector normals; normals.resize(numberVertices); @@ -436,8 +408,6 @@ namespace ZL std::getline(f, tempLine);//=== Animation Keyframes === std::getline(f, tempLine);//=== Bone Transforms per Keyframe === - - std::getline(f, tempLine); int numberKeyFrames; @@ -466,11 +436,6 @@ namespace ZL 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].bones.resize(numberBones); @@ -479,7 +444,7 @@ namespace ZL { std::getline(f, tempLine); std::string boneName = tempLine.substr(8); - //std::cout << "Processing keyframe " << i << ", bone: " << j << " " << boneName << std::endl; + int boneNumber = getIndexByValue(boneName, boneNames); 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 + 3 * 4] = floatValues[3]; - std::getline(f, tempLine); b = tempLine.cbegin(); 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 + 2 * 4] = floatValues[2]; animations[0].keyFrames[i].bones[boneNumber].boneMatrixWorld.data()[2 + 3 * 4] = floatValues[3]; - - std::getline(f, tempLine); b = tempLine.cbegin(); 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 + 3 * 4] = floatValues[3]; - //std::getline(f, tempLine);// ignore last matrix line - //=============== Matrix end ================== } @@ -587,6 +547,14 @@ namespace ZL } 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) @@ -747,49 +715,57 @@ namespace ZL } 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(max(0, verticesBoneWeight[i][0].boneIndex)), - static_cast(max(0, verticesBoneWeight[i][1].boneIndex)), - static_cast(max(0, verticesBoneWeight[i][2].boneIndex)), - static_cast(max(0, verticesBoneWeight[i][3].boneIndex)) - ); - gpuBoneData.boneIndices1[i] = Vector2f( - static_cast(max(0, verticesBoneWeight[i][4].boneIndex)), - static_cast(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) { 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 GpuBoneData::PrepareGpuSkinningData(const std::vector>& 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(max(0, verticesBoneWeight[i][0].boneIndex)), + static_cast(max(0, verticesBoneWeight[i][1].boneIndex)), + static_cast(max(0, verticesBoneWeight[i][2].boneIndex)), + static_cast(max(0, verticesBoneWeight[i][3].boneIndex)) + ); + boneIndices1[i] = Vector2f( + static_cast(max(0, verticesBoneWeight[i][4].boneIndex)), + static_cast(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& outMatrices) const { int startingKeyFrame = -1; diff --git a/src/BoneAnimatedModel.h b/src/BoneAnimatedModel.h index e2021fb..7442e19 100644 --- a/src/BoneAnimatedModel.h +++ b/src/BoneAnimatedModel.h @@ -42,6 +42,7 @@ namespace ZL 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 @@ -65,12 +66,26 @@ namespace ZL 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 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; + }; + diff --git a/src/Character.cpp b/src/Character.cpp index c3f6413..999037d 100644 --- a/src/Character.cpp +++ b/src/Character.cpp @@ -291,24 +291,24 @@ void Character::draw(Renderer& renderer) { renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix()); auto& anim = it->second; - anim.modelMutable.AssignFrom(anim.model.mesh); - anim.modelMutable.RefreshVBO(); + modelMutable.AssignFrom(anim.model.mesh); + modelMutable.RefreshVBO(); glBindTexture(GL_TEXTURE_2D, texture->getTexID()); - renderer.DrawVertexRenderStruct(anim.modelMutable); + renderer.DrawVertexRenderStruct(modelMutable); renderer.PopMatrix(); renderer.PopProjectionMatrix(); renderer.shaderManager.PopShader(); } -void Character::prepareGpuSkinningVBOs(AnimationData& anim) { +void Character::prepareGpuSkinningVBOs(BoneAnimationData& anim) { if (anim.gpuSkinningPrepared) { return; } - anim.model.PrepareGpuSkinningData(); + anim.model.gpuBoneData.PrepareGpuSkinningData(anim.model.verticesBoneWeight); // Upload bind-pose mesh (static, done once) anim.bindPoseMutable.AssignFrom(anim.model.startMesh); @@ -443,9 +443,9 @@ void Character::drawShadowDepthCpu(Renderer& renderer) { renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix()); auto& anim = it->second; - anim.modelMutable.AssignFrom(anim.model.mesh); - anim.modelMutable.RefreshVBO(); - renderer.DrawVertexRenderStruct(anim.modelMutable); + modelMutable.AssignFrom(anim.model.mesh); + modelMutable.RefreshVBO(); + renderer.DrawVertexRenderStruct(modelMutable); renderer.PopMatrix(); } @@ -550,10 +550,10 @@ void Character::drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lig renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix()); auto& anim = it->second; - anim.modelMutable.AssignFrom(anim.model.mesh); - anim.modelMutable.RefreshVBO(); + modelMutable.AssignFrom(anim.model.mesh); + modelMutable.RefreshVBO(); glBindTexture(GL_TEXTURE_2D, texture->getTexID()); - renderer.DrawVertexRenderStruct(anim.modelMutable); + renderer.DrawVertexRenderStruct(modelMutable); renderer.PopMatrix(); renderer.PopProjectionMatrix(); diff --git a/src/Character.h b/src/Character.h index 52d0f55..e3d1a49 100644 --- a/src/Character.h +++ b/src/Character.h @@ -29,7 +29,7 @@ public: 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 setTexture(std::shared_ptr texture); + void setTexture(std::shared_ptr texture) { this->texture = texture; } @@ -38,6 +38,7 @@ public: // From Python you can chain further commands (walk, wait, trigger others). void setTarget(const Eigen::Vector3f& target, std::function onArrived = nullptr); + void setPathPlanner(PathPlanner planner); void draw(Renderer& renderer); void drawShadowDepth(Renderer& renderer); @@ -70,29 +71,15 @@ public: Character* attackTarget = nullptr; bool isPlayer = false; bool useGpuSkinning = true; + //bool useGpuSkinning = false; float interactionRadius = 0.0f; private: - struct AnimationData { - BoneSystem model; - VertexRenderStruct modelMutable; - 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; - }; - - std::map animations; + std::map animations; + VertexRenderStruct modelMutable; std::shared_ptr texture; Eigen::Vector3f walkTarget = Eigen::Vector3f(0.f, 0.f, 0.f); @@ -111,7 +98,7 @@ private: AnimationState resolveActiveState() const; // 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 void drawGpuSkinning(Renderer& renderer); // Shadow: draw into depth map (no texture, no projection push)