In which you take on the job of computing a model's normals.
Not all 3D models have their normals defined in the file. If that's the case, you can compute them yourself. A normal is, after all, nothing more than a description of which way a triangle faces. You can derive that information from the vertex positions.
To compute a normal for a triangle, you first need two vectors that run through the triangle in different directions. The triangle's edges are good sources for these vectors. Take two of these edge vectors and cross them to get a vector perpendicular to both. That vector points away from the triangle; it's the triangle's normal.
This renderer shows a triangle with the two edge vectors that are crossed to generate the normal:
Normals for all the triangles are computed using this pseudocode:
for each triangle
# Look up vertex positions.
positionA = triangle's first position
positionB = triangle's second position
positionC = triangle's third position
# Find two edge vectors.
vectorAB = positionB - positionA
vectorAC = positionC - positionA
faceNormal = cross vectorAB and vectorAC
normalize faceNormal
A normal that's uniform across a face is nice, but you can only render models with data defined at the vertices. A vertex's normal is the average of its adjacent faces' normals. To compute the average, you must sum up the normals. You can do this as you process each triangle:
for each triangle
# compute faceNormal as described above
for each vertex in triangle
add faceNormal to vertexNormal
The vertex normals must be initialized to zero vectors before the face normals start accumulating. And they need to averaged after they are accumulated. Usually averaging is done by dividing the sum by the size of a population. In the case of normals, you can just normalize them. That leads to this complete algorithm for computing a mesh's normals:
for each vertex
set vertexNormal to zero-vector
for each triangle
# Look up vertex positions.
positionA = triangle's first position
positionB = triangle's second position
positionC = triangle's third position
# Find two edge vectors.
vectorAB = positionB - positionA
vectorAC = positionC - positionA
faceNormal = cross vectorAB and vectorAC
normalize faceNormal
for each vertex in triangle
add faceNormal to vertexNormal
for each vertex
normalize vertexNormal
This algorithm deserves its own method in your Trimesh
class. See the algorithm at work in this renderer:
The blue normals are the face normals. These are averaged together to form the orange vertex normals. Observe how these normals change as you drag the vertices around.