Created
August 24, 2017 17:10
-
-
Save reinsteam/8da89b9cc42149d67ec96600223c667a to your computer and use it in GitHub Desktop.
Example of mesh normals computation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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