I have created a class that reads a 3d studio asc file into a standard format ( list of verticies , list of faces , list of models) and i have successfully calculated the normals for the faces. this works fine when i render the model but I want to be able to make it look smooth.
i have written a piece of code to calculate vertex normals based on the average of the normals for each of the faces that share a particulatr vertex.
this gives me a horrible result (all the faces are shaded in a very strange way) and i cant work out whats wrong.
// set the vertex normal to the sum of all the shared face normals
for(int kk=0; kk<3; kk++) {
m_model[ii].faceList[jj].vertex[kk]->normal[0] +=
m_model[ii].faceList[jj].normal[0];
m_model[ii].faceList[jj].vertex[kk]->normal[1] +=
m_model[ii].faceList[jj].normal[1];
m_model[ii].faceList[jj].vertex[kk]->normal[2] +=
m_model[ii].faceList[jj].normal[2];
m_model[ii].faceList[jj].vertex[kk]->m_numSharedFaces++;
}
}
// average the vertex normals
for(int ll=0;ll<m_model[ii].numVertices;ll++) {
m_model[ii].vertexList[ll].normal[0] = m_model[ii].vertexList[ll].normal[0] /
m_model[ii].vertexList[ll].m_numSharedFaces;
m_model[ii].vertexList[ll].normal[1] = m_model[ii].vertexList[ll].normal[1] /
m_model[ii].vertexList[ll].m_numSharedFaces;
m_model[ii].vertexList[ll].normal[2] = m_model[ii].vertexList[ll].normal[2] /
m_model[ii].vertexList[ll].m_numSharedFaces;
Normalise(m_model[ii].vertexList[ll].normal[0],
m_model[ii].vertexList[ll].normal[1],
m_model[ii].vertexList[ll].normal[2]);
}
}
}
You don’t have to divide the vertex normals by the number of shared faces before the normalization. The direction of the vector stays the same, so you only need to normalize.
Anyway, your method seems to be ok. It is possible that
a) your rendering code does something wrong
b) ‘Normalise’ function is not working correctly (not likely, your face normal calculation works)
c) the face normals haven’t been calculated before the vertex normal calculation (not likely)
glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,surface);
// Used for face normals
// glNormal3fv(m_model[nn].faceList[ii].normal);
for(int jj=0; jj<3; jj++)
{
// Used for vertex normals
glNormal3fv(m_model[nn].faceList[ii].vertex[jj]->normal);
glVertex3fv(m_model[nn].faceList[ii].vertex[jj]->point);
}
glEnd();
}
}
to create vertex normals there are two basic approaches, imo: use smoothing groups and don’t use soothing groups
SG’s are a way to identify surfaces into meshes.
a cube has 6 surfaces, a sphere has one, a cylinder has 3 surfaces…
a torus have one surface, like the sphere.
surfaces can be made of any number of polygons, and vertex normals for a given SG have to be evaluated separately from the other polygons, not belonging to the same SG.
this leads to the fact that vertices that lay on the seam between two different SG have more than one normal.
if your model is, for simplicity, a sphere (any object with a single surface), you don’t have to mess with SG’s.
if your model is more complex, to say, a cube with a cylinder coming out the center of a cube’s face, then you can’t simply average normals from faces wich share a vertex.
you will get wrong lighting.
if your model is complex, you have to care abous SG’s, and it’s a bit complex…
to avoid troubles, i suggest you to use 3D studio MAX scene ascii export files (.ASE): they have multiple normals for vertices.
Originally posted by kevin: the .asc file has AB:1 BC:1 CA:1 for every face - this is the only info i havent used to construct my model and i’m not sure what it means.
These are boolean flags used to determine which edges to draw when rendering a wireframe of the model.
Originally posted by Eric:
[b]Oops, forgot something : did you specify glShadeModel(GL_SMOOTH) somewhere in your code ???
Eric[/b]
Agraaaaaaaaahah - i cant believe i have been so dumb!
I was trying to render it with vertex normals and i forgot to change the shade model from flat to smooth. i’ve changed it to smooth and it works just fine! - thanks for all your help.