diff --git a/src/raylib.h b/src/raylib.h index 18a6796aa44e..7e1a1f8380a9 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -360,9 +360,8 @@ typedef struct Mesh { float *animNormals; // Animated normals (after bones transformations) unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6) float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7) + Matrix *boneMatrices; // Bones animated transformation matrices int boneCount; // Number of bones - Matrix *boneMatricesPtr; // POINTER to Models bones transformation matrices - // DO NOT FREE THIS // OpenGL identifiers unsigned int vaoId; // OpenGL Vertex Array Object id @@ -415,7 +414,6 @@ typedef struct Model { // Animation data int boneCount; // Number of bones BoneInfo *bones; // Bones information (skeleton) - Matrix *boneMatrices; // Bones animated transformation matrices, moved these here to boost perf a little and remove wasted memory duplication Transform *bindPose; // Bones base transformation (pose) } Model; diff --git a/src/rmodels.c b/src/rmodels.c index 3c8af16370a3..d69c9035cac5 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1209,7 +1209,7 @@ void UnloadModel(Model model) // Unload animation data RL_FREE(model.bones); RL_FREE(model.bindPose); - RL_FREE(model.boneMatrices); + TRACELOG(LOG_INFO, "MODEL: Unloaded model (and meshes) from RAM and VRAM"); } @@ -1508,9 +1508,9 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) #ifdef RL_SUPPORT_MESH_GPU_SKINNING // Upload Bone Transforms - if ((material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1) && mesh.boneMatricesPtr) + if ((material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1) && mesh.boneMatrices) { - rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatricesPtr, mesh.boneCount); + rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount); } #endif //----------------------------------------------------- @@ -1754,9 +1754,9 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i #ifdef RL_SUPPORT_MESH_GPU_SKINNING // Upload Bone Transforms - if ((material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1) && mesh.boneMatricesPtr) + if ((material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1) && mesh.boneMatrices) { - rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatricesPtr, mesh.boneCount); + rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount); } #endif @@ -1932,6 +1932,7 @@ void UnloadMesh(Mesh mesh) RL_FREE(mesh.animNormals); RL_FREE(mesh.boneWeights); RL_FREE(mesh.boneIds); + RL_FREE(mesh.boneMatrices); } // Export mesh data to file @@ -2269,6 +2270,22 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame) { if (frame >= anim.frameCount) frame = frame%anim.frameCount; + // Get first mesh which have bones + int firstMeshWithBones = -1; + + for (int i = 0; i < model.meshCount; i++) + { + if (model.meshes[i].boneMatrices) + { + assert(model.meshes[i].boneCount == anim.boneCount); + if (firstMeshWithBones == -1) + { + firstMeshWithBones = i; + break; + } + } + } + // Update all bones and boneMatrices of first mesh with bones. for (int boneId = 0; boneId < anim.boneCount; boneId++) { @@ -2295,7 +2312,22 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame) MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)), MatrixScale(boneScale.x, boneScale.y, boneScale.z)); - model.boneMatrices[boneId] = boneMatrix; + model.meshes[firstMeshWithBones].boneMatrices[boneId] = boneMatrix; + } + + // Update remaining meshes with bones + // NOTE: Using deep copy because shallow copy results in double free with 'UnloadModel()' + if (firstMeshWithBones != -1) + { + for (int i = firstMeshWithBones + 1; i < model.meshCount; i++) + { + if (model.meshes[i].boneMatrices) + { + memcpy(model.meshes[i].boneMatrices, + model.meshes[firstMeshWithBones].boneMatrices, + model.meshes[i].boneCount * sizeof(model.meshes[i].boneMatrices[0])); + } + } } } } @@ -2340,7 +2372,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) // Early stop when no transformation will be applied if (boneWeight == 0.0f) continue; animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] }; - animVertex = Vector3Transform(animVertex,model.boneMatrices[boneId]); + animVertex = Vector3Transform(animVertex,model.meshes[m].boneMatrices[boneId]); mesh.animVertices[vCounter] += animVertex.x*boneWeight; mesh.animVertices[vCounter+1] += animVertex.y*boneWeight; mesh.animVertices[vCounter+2] += animVertex.z*boneWeight; @@ -2351,7 +2383,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) if (mesh.normals != NULL) { animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] }; - animNormal = Vector3Transform(animNormal,model.boneMatrices[boneId]); + animNormal = Vector3Transform(animNormal,model.meshes[m].boneMatrices[boneId]); mesh.animNormals[vCounter] += animNormal.x*boneWeight; mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight; mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight; @@ -4775,10 +4807,16 @@ static Model LoadIQM(const char *fileName) } BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose); - model.boneMatrices = RL_CALLOC(model.boneCount,sizeof(Matrix)); - for (int j = 0; j < model.boneCount; j++) + + for (int i = 0; i < model.meshCount; i++) { - model.boneMatrices[j] = MatrixIdentity(); + model.meshes[i].boneCount = model.boneCount; + model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix)); + + for (int j = 0; j < model.meshes[i].boneCount; j++) + { + model.meshes[i].boneMatrices[j] = MatrixIdentity(); + } } UnloadFileData(fileData); @@ -5869,10 +5907,14 @@ static Model LoadGLTF(const char *fileName) } // Bone Transform Matrices - if (model.boneMatrices==NULL) - model.boneMatrices = RL_CALLOC(model.boneCount, sizeof(Matrix)); + model.meshes[meshIndex].boneCount = model.boneCount; + model.meshes[meshIndex].boneMatrices = RL_CALLOC(model.meshes[meshIndex].boneCount, sizeof(Matrix)); + + for (int j = 0; j < model.meshes[meshIndex].boneCount; j++) + { + model.meshes[meshIndex].boneMatrices[j] = MatrixIdentity(); + } - model.meshes[meshIndex].boneMatricesPtr = model.boneMatrices; meshIndex++; // Move to next mesh } @@ -6645,9 +6687,12 @@ static Model LoadM3D(const char *fileName) memcpy(model.meshes[i].animVertices, model.meshes[i].vertices, model.meshes[i].vertexCount*3*sizeof(float)); memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float)); - if (model.boneMatrices==NULL) - model.boneMatrices = RL_CALLOC(model.boneCount, sizeof(Matrix)); - model.meshes[i].boneMatricesPtr = model.boneMatrices; + model.meshes[i].boneCount = model.boneCount; + model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix)); + for (j = 0; j < model.meshes[i].boneCount; j++) + { + model.meshes[i].boneMatrices[j] = MatrixIdentity(); + } } }