Просмотр исходного кода

Removed memory duplication and memcpy with animations

previously the bonematrix array was stored per mesh even though this is duplicated. now points back to the model.
this saves memory and removes a memcpy.
pull/4627/head
Jett 1 год назад
Родитель
Сommit
0bc4ede7ab
2 измененных файлов: 20 добавлений и 63 удалений
  1. +3
    -1
      src/raylib.h
  2. +17
    -62
      src/rmodels.c

+ 3
- 1
src/raylib.h Просмотреть файл

@ -360,8 +360,9 @@ typedef struct Mesh {
float *animNormals; // Animated normals (after bones transformations) 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) 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) 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 int boneCount; // Number of bones
Matrix *boneMatricesPtr; // POINTER to Models bones transformation matrices
// DO NOT FREE THIS
// OpenGL identifiers // OpenGL identifiers
unsigned int vaoId; // OpenGL Vertex Array Object id unsigned int vaoId; // OpenGL Vertex Array Object id
@ -414,6 +415,7 @@ typedef struct Model {
// Animation data // Animation data
int boneCount; // Number of bones int boneCount; // Number of bones
BoneInfo *bones; // Bones information (skeleton) 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) Transform *bindPose; // Bones base transformation (pose)
} Model; } Model;

+ 17
- 62
src/rmodels.c Просмотреть файл

@ -1209,7 +1209,7 @@ void UnloadModel(Model model)
// Unload animation data // Unload animation data
RL_FREE(model.bones); RL_FREE(model.bones);
RL_FREE(model.bindPose); RL_FREE(model.bindPose);
RL_FREE(model.boneMatrices);
TRACELOG(LOG_INFO, "MODEL: Unloaded model (and meshes) from RAM and VRAM"); 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 #ifdef RL_SUPPORT_MESH_GPU_SKINNING
// Upload Bone Transforms // Upload Bone Transforms
if ((material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1) && mesh.boneMatrices)
if ((material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1) && mesh.boneMatricesPtr)
{ {
rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount);
rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatricesPtr, mesh.boneCount);
} }
#endif #endif
//----------------------------------------------------- //-----------------------------------------------------
@ -1754,9 +1754,9 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
#ifdef RL_SUPPORT_MESH_GPU_SKINNING #ifdef RL_SUPPORT_MESH_GPU_SKINNING
// Upload Bone Transforms // Upload Bone Transforms
if ((material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1) && mesh.boneMatrices)
if ((material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1) && mesh.boneMatricesPtr)
{ {
rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount);
rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatricesPtr, mesh.boneCount);
} }
#endif #endif
@ -1932,7 +1932,6 @@ void UnloadMesh(Mesh mesh)
RL_FREE(mesh.animNormals); RL_FREE(mesh.animNormals);
RL_FREE(mesh.boneWeights); RL_FREE(mesh.boneWeights);
RL_FREE(mesh.boneIds); RL_FREE(mesh.boneIds);
RL_FREE(mesh.boneMatrices);
} }
// Export mesh data to file // Export mesh data to file
@ -2270,22 +2269,6 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame)
{ {
if (frame >= anim.frameCount) frame = frame%anim.frameCount; 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. // Update all bones and boneMatrices of first mesh with bones.
for (int boneId = 0; boneId < anim.boneCount; boneId++) for (int boneId = 0; boneId < anim.boneCount; boneId++)
{ {
@ -2312,22 +2295,7 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame)
MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)), MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)),
MatrixScale(boneScale.x, boneScale.y, boneScale.z)); MatrixScale(boneScale.x, boneScale.y, boneScale.z));
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]));
}
}
model.boneMatrices[boneId] = boneMatrix;
} }
} }
} }
@ -2372,7 +2340,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
// Early stop when no transformation will be applied // Early stop when no transformation will be applied
if (boneWeight == 0.0f) continue; if (boneWeight == 0.0f) continue;
animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] }; animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] };
animVertex = Vector3Transform(animVertex,model.meshes[m].boneMatrices[boneId]);
animVertex = Vector3Transform(animVertex,model.boneMatrices[boneId]);
mesh.animVertices[vCounter] += animVertex.x*boneWeight; mesh.animVertices[vCounter] += animVertex.x*boneWeight;
mesh.animVertices[vCounter+1] += animVertex.y*boneWeight; mesh.animVertices[vCounter+1] += animVertex.y*boneWeight;
mesh.animVertices[vCounter+2] += animVertex.z*boneWeight; mesh.animVertices[vCounter+2] += animVertex.z*boneWeight;
@ -2383,7 +2351,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
if (mesh.normals != NULL) if (mesh.normals != NULL)
{ {
animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] }; animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] };
animNormal = Vector3Transform(animNormal,model.meshes[m].boneMatrices[boneId]);
animNormal = Vector3Transform(animNormal,model.boneMatrices[boneId]);
mesh.animNormals[vCounter] += animNormal.x*boneWeight; mesh.animNormals[vCounter] += animNormal.x*boneWeight;
mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight; mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight;
mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight; mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight;
@ -4807,16 +4775,10 @@ static Model LoadIQM(const char *fileName)
} }
BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose); BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose);
for (int i = 0; i < model.meshCount; i++)
model.boneMatrices = RL_CALLOC(model.boneCount,sizeof(Matrix));
for (int j = 0; j < model.boneCount; j++)
{ {
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();
}
model.boneMatrices[j] = MatrixIdentity();
} }
UnloadFileData(fileData); UnloadFileData(fileData);
@ -5907,14 +5869,10 @@ static Model LoadGLTF(const char *fileName)
} }
// Bone Transform Matrices // Bone Transform Matrices
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();
}
if (model.boneMatrices==NULL)
model.boneMatrices = RL_CALLOC(model.boneCount, sizeof(Matrix));
model.meshes[meshIndex].boneMatricesPtr = model.boneMatrices;
meshIndex++; // Move to next mesh meshIndex++; // Move to next mesh
} }
@ -6687,12 +6645,9 @@ 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].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)); memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float));
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();
}
if (model.boneMatrices==NULL)
model.boneMatrices = RL_CALLOC(model.boneCount, sizeof(Matrix));
model.meshes[i].boneMatricesPtr = model.boneMatrices;
} }
} }

Загрузка…
Отмена
Сохранить