4 Commits

Author SHA1 Message Date
d8ddc8a0a6 [rmodels] UpdateModelAnimation(), compute bone normal matrices once per bone instead of per vertex (#6191)
* [rmodels] `UpdateModelAnimation()`, compute bone normal matrices once per bone instead of per vertex

* [rmodels] use a static buffer for bone normal matrices
2026-10-03 13:42:37 +02:00
8341321d1a [rcore][win32] Add missing break in WndProc switch statement (#6209) 2026-10-03 10:30:43 +02:00
51d713d54d [vox_loader] Prevent memory leak when loading voxel models (#6208) 2026-10-03 10:29:58 +02:00
3ff30034de [examples] Release mesh instancing resources on exit (#6207)
Co-authored-by: Hugohong258 <282228220+Hugohong258@users.noreply.github.com>
2026-10-03 10:26:53 +02:00
4 changed files with 17 additions and 2 deletions

View File

@ -139,6 +139,9 @@ int main(void)
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
RL_FREE(transforms); // Free transforms RL_FREE(transforms); // Free transforms
UnloadMaterial(matInstances); // Also unloads the instancing shader
UnloadMaterial(matDefault); // Unload default material
UnloadMesh(cube); // Unload cube mesh
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

View File

@ -733,6 +733,7 @@ void Vox_FreeArrays(VoxArray3D* voxarray)
// Free arrays // Free arrays
freeArrayVector3(&voxarray->vertices); freeArrayVector3(&voxarray->vertices);
freeArrayVector3(&voxarray->normals);
freeArrayUShort(&voxarray->indices); freeArrayUShort(&voxarray->indices);
freeArrayColor(&voxarray->colors); freeArrayColor(&voxarray->colors);
} }

View File

@ -2000,7 +2000,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
EndPaint(hwnd, &ps); EndPaint(hwnd, &ps);
} }
else DefWindowProc(hwnd, msg, wparam, lparam); else DefWindowProc(hwnd, msg, wparam, lparam);
} } break;
case WM_INPUT: case WM_INPUT:
{ {
//HandleRawInput(lparam); //HandleRawInput(lparam);

View File

@ -2486,6 +2486,9 @@ void UpdateModelAnimationEx(Model model, ModelAnimation animA, float frameA, Mod
// NOTE: Required for CPU skinning, uploads animated vertex buffers to GPU // NOTE: Required for CPU skinning, uploads animated vertex buffers to GPU
static void UpdateModelAnimationVertexBuffers(Model model) static void UpdateModelAnimationVertexBuffers(Model model)
{ {
static Matrix boneNormalMatrices[256] = { 0 }; // Normal matrix per bone, bone indices are unsigned char
bool boneNormalsReady = false;
for (int m = 0; m < model.meshCount; m++) for (int m = 0; m < model.meshCount; m++)
{ {
Mesh mesh = model.meshes[m]; Mesh mesh = model.meshes[m];
@ -2502,6 +2505,14 @@ static void UpdateModelAnimationVertexBuffers(Model model)
if ((mesh.boneWeights == NULL) || (mesh.boneIndices == NULL) || if ((mesh.boneWeights == NULL) || (mesh.boneIndices == NULL) ||
(mesh.animVertices == NULL) || (mesh.animNormals == NULL)) continue; (mesh.animVertices == NULL) || (mesh.animNormals == NULL)) continue;
// Normal matrix only depends on the bone, compute it once per bone instead of per vertex
if ((mesh.normals != NULL) && !boneNormalsReady)
{
memset(boneNormalMatrices, 0, 256*sizeof(Matrix));
for (unsigned int b = 0; (b < model.skeleton.boneCount) && (b < 256); b++) boneNormalMatrices[b] = MatrixTranspose(MatrixInvert(model.boneMatrices[b]));
boneNormalsReady = true;
}
for (int vCounter = 0; vCounter < vertexValuesCount; vCounter += 3) for (int vCounter = 0; vCounter < vertexValuesCount; vCounter += 3)
{ {
mesh.animVertices[vCounter] = 0; mesh.animVertices[vCounter] = 0;
@ -2534,7 +2545,7 @@ static void UpdateModelAnimationVertexBuffers(Model model)
if ((mesh.normals != NULL) && (mesh.animNormals != NULL )) if ((mesh.normals != NULL) && (mesh.animNormals != 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, MatrixTranspose(MatrixInvert(model.boneMatrices[boneIndex]))); animNormal = Vector3Transform(animNormal, boneNormalMatrices[boneIndex]);
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;