Calculate Vertex Normal

I read in a file to create my object. The format is pretty basic, the first int tells you the number of vertices and the second int tells you the number of polygons. Then the coordinates for the vertices are listed followed by the information for the polygons (the first number tells you how many vertices make up the polygon and the subsequent numbers tell you what vertex to use). Below is a very basic object in the described format (other objects have 40000+ polygons).

In order to perform the shading for the object I calculate the polygon normal. The problem I am running into is that you can see the polygons that form the object. I was told that in order to see a more realistic object I need to calculate the vertex normal for the object.

My question is: has anyone done something like this before? Like I stated earlier these objects can be relatively large. What do you think would be the best way to determine this information?

I would hate to have to traverse the file and create some data structure to store the polygons that share a common vertex (although I am assuming this is my only course of action). Is my thought process correct or is there a better way to get the results that I am looking for…

 data 12	8
-.5	0.0	-.5
0.0	0.0	-.5
0.0	.5	-.5
.5	.5	-.5
.5	-.5	-.5
-.5	-.5	-.5
-.5	0.0	.5
0.0	0.0	.5
0.0	.5	.5
.5	.5	.5
.5	-.5	.5
-.5	-.5	.5
4	3	9	10	4
4	1	7	8	2
4	12	6	5	11
4	7	1	6	12
4	9	3	2	8
4	10	11	5	4
6	9	8	7	12	11	10
6	4	5	6	1	2	3 

Hi !

As far as I know you do need to find the shared vertices (one way or another) to calculate vertex normals, there are a number of ways to do it, Graphics Gems IV or V has a complete code example doing vertex normal calculations.

Mikael

Whoever came up with the file format, has made your life a lot easier, by splitting the vertices and polygons.
(Not to mention the benefits when you want to start using vertex arrays).

  1. Allocate as many vertex normals as there are unique vertices (i.e. as many as there are vertices in the file), and also allocate a usage array.
  2. initialise them all to (0,0,0), and the usage array to 0.
  3. go through the polys, determining their plane normals (cross product of two vectors between three successive vertices - presuming all vertices are coplanar),
    and then do the following:
 vertexnormal[vertexindex] = ((vertexnormal[vertexindex]*usage[vertexindex]+planenormal)/(usage[vertexindex]+1.0);
 usage[vertexindex]+=1.0;

This makes all vertex normals the average of the plane normals of the planes they are used in.
4. Go through the list of vertex normals and normalize them. (i.e. make sure their length is 1)

PS: it really pays to have a vector class for this sort of stuff.

I don’t have my code in front of me, as I am at work, but I will definitly try your suggestions this afternoon.

Quick question:

I have already calculated the plane normals (cross product of two vectors), and I store this information. Are you saying as I loop through the plane normals I should do your suggestions

  
for( int i = 0; i<numPolygons; i++ )
{
  calculate polygonNormal
  Normalize polygonNormal
  for( int vertexindex = 0; vertexindex < numVertices; vertexindex++ )  
  {
   vertexnormal[vertexindex] = ((vertexnormal[vertexindex]*usage[vertexindex]+planenormal[i])/(usage[vertexindex]+1.0);
 usage[vertexindex]+=1.0;
   Normalize vertexNormal
  }
}

Is this a correct assumption or am I off?

You’re a little bit off.

The polygons contain indices into the vertex array, so you would loop through the plane’s array of indices and use those indices to point into the actual vertex data.

More something like:

 
int vertexindex;
for(vertexindex=0;vertexindex<NumVertices;vertexindex++) {
 vertexnormal[vertexindex]=vector(0,0,0);
 usage[vertexindex]=0;
}
for( int i = 0; i<numPolygons; i++ ){
  calculate polygonNormal  
  planenormal[i].normalize();
  for( int vi = 0; vi < polygon[i].NumVertices; vi++ ) {
   vertexindex=polygon.corner[in];
   vertexnormal[vertexindex] = ((vertexnormal[vertexindex]*usage[vertexindex]+planenormal[i])/(usage[vertexindex]+1.0);
   usage[vertexindex]+=1.0;
  }
}
for(vertexindex=0;vertexindex<NumVertices;vertexindex++) {
   vertexnormal[vertexindex].normalize();
}
 

(Again, it’s a lot nicer to write if you have a vector class)