summaryrefslogtreecommitdiffhomepage
path: root/src/models.c
diff options
context:
space:
mode:
authorseanpringle <[email protected]>2020-07-20 19:05:18 +1000
committerGitHub <[email protected]>2020-07-20 11:05:18 +0200
commitcebcdea80f11400e2c1bdb13e2732b4bdb1e1dd7 (patch)
treeee36f4a0ca7fc653f304930ef776c577679729e0 /src/models.c
parent6ec847a93fafe22e2611ce86494e1c6f5b331877 (diff)
downloadraylib-cebcdea80f11400e2c1bdb13e2732b4bdb1e1dd7.tar.gz
raylib-cebcdea80f11400e2c1bdb13e2732b4bdb1e1dd7.zip
[wip] MeshNormalsSmooth() (#1317)
* MeshSmoothNormals() by average * wrong comment * spelling * use correct function naming convention
Diffstat (limited to 'src/models.c')
-rw-r--r--src/models.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/models.c b/src/models.c
index e34099e6..55621ee1 100644
--- a/src/models.c
+++ b/src/models.c
@@ -2473,6 +2473,74 @@ void MeshBinormals(Mesh *mesh)
}
}
+// Smooth (average) vertex normals
+void MeshNormalsSmooth(Mesh *mesh)
+{
+ #define EPSILON 0.000001 // A small number
+
+ int uvCounter = 0;
+ Vector3 *uniqueVertices = (Vector3 *)RL_CALLOC(mesh->vertexCount, sizeof(Vector3));
+ Vector3 *summedNormals = (Vector3 *)RL_CALLOC(mesh->vertexCount, sizeof(Vector3));
+
+ int uiCounter = 0;
+ int *uniqueIndices = (int *)RL_CALLOC(mesh->vertexCount, sizeof(int));
+
+ // Sum normals grouped by vertex
+ for (int i = 0; i < mesh->vertexCount; i++)
+ {
+ Vector3 v = { mesh->vertices[(i + 0)*3 + 0], mesh->vertices[(i + 0)*3 + 1], mesh->vertices[(i + 0)*3 + 2] };
+ Vector3 n = { mesh->normals[(i + 0)*3 + 0], mesh->normals[(i + 0)*3 + 1], mesh->normals[(i + 0)*3 + 2] };
+
+ bool matched = false;
+
+ // TODO: Matching vertices is brute force O(N^2). Do it more efficiently?
+ for (int j = 0; j < uvCounter; j++)
+ {
+ Vector3 uv = uniqueVertices[j];
+
+ bool match = true;
+ match = match && fabs(uv.x - v.x) < EPSILON;
+ match = match && fabs(uv.y - v.y) < EPSILON;
+ match = match && fabs(uv.z - v.z) < EPSILON;
+
+ if (match)
+ {
+ matched = true;
+ summedNormals[j] = Vector3Add(summedNormals[j], n);
+ uniqueIndices[i] = j;
+ break;
+ }
+ }
+
+ if (!matched)
+ {
+ int j = uvCounter++;
+ uniqueVertices[j] = v;
+ summedNormals[j] = n;
+ uniqueIndices[i] = j;
+ }
+ }
+
+ // Average and update normals
+ for (int i = 0; i < mesh->vertexCount; i++)
+ {
+ int j = uniqueIndices[i];
+ Vector3 n = Vector3Normalize(summedNormals[j]);
+ mesh->normals[(i + 0)*3 + 0] = n.x;
+ mesh->normals[(i + 0)*3 + 1] = n.y;
+ mesh->normals[(i + 0)*3 + 2] = n.z;
+ }
+
+ // 2=normals, see rlUpdateMeshAt()
+ rlUpdateMesh(*mesh, 2, mesh->vertexCount);
+
+ RL_FREE(uniqueVertices);
+ RL_FREE(summedNormals);
+ RL_FREE(uniqueIndices);
+
+ TRACELOG(LOG_INFO, "MESH: Normals smoothed (%d vertices, %d unique)", mesh->vertexCount, uvCounter);
+}
+
// Draw a model (with texture if set)
void DrawModel(Model model, Vector3 position, float scale, Color tint)
{