Skip to content

Instantly share code, notes, and snippets.

@reinsteam
Created August 24, 2017 17:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reinsteam/8da89b9cc42149d67ec96600223c667a to your computer and use it in GitHub Desktop.
Save reinsteam/8da89b9cc42149d67ec96600223c667a to your computer and use it in GitHub Desktop.
Example of mesh normals computation
typedef struct float3
{
float x, y, z;
} float3;
typedef unsigned int u32;
/*----------------------------------------------------------------------------------------------------------------------
* input parameters:
* `vertices` - an array storing vertex positions
* `indices` - an array storing vertex indices
* `num_vertices` - number of elements in `normals` and `vertices` arrays
* `num_indices` - number elements in `indices` array
*
* input/output parameters:
* `normals` - an array (initialized to zero) where recomputed vertex normals will be outputted
*--------------------------------------------------------------------------------------------------------------------*/
void recompute_normals(float3 * normals, float3 const * vertices, u32 const * indices, u32 num_vertices, u32 num_indices)
{
for (u32 i = 0; i < num_indices; i += 3)
{
u32 i0 = indices[i + 0];
u32 i1 = indices[i + 1];
u32 i2 = indices[i + 2];
float edge0_x = vertices[i0].x - vertices[i1].x;
float edge0_y = vertices[i0].y - vertices[i1].y;
float edge0_z = vertices[i0].z - vertices[i1].z;
float edge1_x = vertices[i0].x - vertices[i2].x;
float edge1_y = vertices[i0].y - vertices[i2].y;
float edge1_z = vertices[i0].z - vertices[i2].z;
// cross product of two vectors has a length equal to area of the parallelogram formed by those two vectors
float cross_prod_x = edge0_y * edge1_z - edge0_z * edge1_y;
float cross_prod_y = edge0_z * edge1_x - edge0_x * edge1_z;
float cross_prod_z = edge0_x * edge1_y - edge0_y * edge1_x;
// accumulating every triangle's normal scaled by triangle's area * 2 per vertex gives
// a nice vector which after normalization becomes a vertex normal formed from a weighted sum of
// normals of triangles containing this vertex
normals[i0].x += cross_prod_x;
normals[i0].y += cross_prod_y;
normals[i0].z += cross_prod_z;
normals[i1].x += cross_prod_x;
normals[i1].y += cross_prod_y;
normals[i1].z += cross_prod_z;
normals[i2].x += cross_prod_x;
normals[i2].y += cross_prod_y;
normals[i2].z += cross_prod_z;
}
// do final normalization of those nice vectors
for (u32 i = 0; i < num_vertices; ++i)
{
float dp3 = normals[i].x * normals[i].x + normals[i].y * normals[i].y + normals[i].z * normals[i].z;
float invlen = (dp3 < 0.0000001f) ? 0.0f : 1.0f / sqrtf(dp3);
normals[i].x *= invlen;
normals[i].y *= invlen;
normals[i].z *= invlen;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment