Hi Yzwboy here is one way I would try to make "smoothed" normals (averaged based on adjacent triangles):
In order to compute "smoothed" normals you will need to assign to each vertex a normal which is averaged across the normals of the triangles adjacent to the vertex.
I would calculate a weighted average based on the angle between the two edges adjacent to the vertex in question (cross product which is an easy calculation):
Pseudocode:
Vec3F faceNormal(int face_id, int vertex_id) // assumes C-->B-->A is clockwise
{
Vec3f A = triangleMesh.face[face_id].vertex[vertex_id]; // A
Vec3f B = triangleMesh.face[face_id].vertex[(vertex_id+1)%3]; // B
Vec3f C = triangleMesh.face[face_id].vertex[(vertex_id+2)%3]; // C
Vec3f BA = B-A;
Vec3f CA = C-A;
Vec3f Normal = BA.cross(CA);
float sin_alpha = length(Normal) / (BA.len() * CA.len() ); // depending on your implementation of Vec3f it could be .magnitude() or .length() instead of .len()
return (Normal.normalize() * asin(sin_alpha);)
}
And then to vary the normal by vertex:
void computeNormals() {
for (vertex v in triangleMesh)
{
Vec3f Normal (0,0,0);
for (int i = 0;i < TriangleCount;i++)
if (triangleMesh.face[i].contains(v) )
{
int vertID = vertexPositionInTriangle(i,v); //Can be 0,1 or 2. Use an enum to make A = 0, B=1, C=2 if that is easier to read:)
Normal = Normal + faceNormal(i,vertID);
}
addNormalToVertexV(Normal.normalize(),v); // this is a function to set the normal for a vertex, the vertex class must have a member for normal though and the arguments for the function are Vec3f, Vec3f
}
}
You could also compute the area of a each triangle to use as the weighting, though I find using the angles works best for looks most times.
I have tried to use names which match the Vec3f spec, as well as inbuilt functions to save work, but you will need to do some coding to get the pseudocode working (I dont have access to a GL Test environment here).
Hope this helps :)