• ### What is your GameDev Story?

#### Archived

This topic is now archived and is closed to further replies.

# vertex normal

This topic is 6720 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

How can I calculate vertex normals from the trianglelist? I only know how to calculate normals of the polygons and that''s not enought now.

##### Share on other sites
quote:
Original post by 303
How can I calculate vertex normals from the trianglelist? I only know how to calculate normals of the polygons and that''s not enought now.

Assuming you want a smooth surface, add together the normals from all the polygons that share a particular vertex, then normalize; this gives you a normal for that vertex.

Something like this:

  // define vec3d class elsewhere struct vert { vec3d pos; vec3d norm;}; struct face { // a triangle vec3d norm; int vert[3];}; // globals arraysvert myverts[NVERTS];face myfaces[NFACES]; // calculate your face normals here // make sure your vertex normals are initially zerofor (int x = 0; x < NVERTS; ++x) { myverts[x].norm.clear();} // for each face, add its normal to its verts'' normalsfor (int x = 0; x < NFACES; ++x) { myverts[ myfaces[x].vert[0] ].norm += myfaces[x].norm; myverts[ myfaces[x].vert[1] ].norm += myfaces[x].norm; myverts[ myfaces[x].vert[2] ].norm += myfaces[x].norm;} // now normalize (ie, average) the vertex normalsfor (int x = 0; x < NVERTS; ++x) { myverts[x].norm.normalize();}

Note that the above is presented to illustrate the algorithm and won''t compile as is. Use your favorite 3d vector classes/structs and functions.

##### Share on other sites
you should really get a graphics book... or maybe read an opengl / directx help file.
anyway....
if you've got the polygon normals....
then to get the vertex normals you do the following:

a) For each vertex, find which polygons use that vertex.
b) add the normals of all those polygons together, then divide by the number of polygons.
then hey presto you've got the normal of that vertex.

An easier way is to load a 3D file format which already has the vertex normals included. (e.g. 3DS)

www.razorforce.co.uk

---------
p.s. don't use what Anonymous did.... they've got each vertex linked in with the triangle. (v-bad). Each triangle should just contain an face normal and 3 indexes into the vertex list (for each corner of the triangle)..

Edited by - Nicos on August 26, 2000 5:45:07 PM

##### Share on other sites
A simple average can be inaccurate if you have faces of very different sizes around a vertex. It''s been quite a while since I''ve done this, but if I remember correctly a better heuristic is to scale the triangles normals by the inverse area of their triangle before they''re added; this means that small faces carry more weight than larger faces, which makes sense if you think about it (imagine around a tight bend in a curved object, where the bend area is subdivided finer than the more flat areas around it).

##### Share on other sites
i donno about using the size of the triangle, commom practice is to "weight the normals by the size of the angles at the shared intersection"

##### Share on other sites
quote:
Original post by Nicos

a) For each vertex, find which polygons use that vertex.
b) add the normals of all those polygons together, then divide by the number of polygons.

---------
p.s. don''t use what Anonymous did.... they''ve got each vertex linked in with the triangle. (v-bad). Each triangle should just contain an face normal and 3 indexes into the vertex list (for each corner of the triangle)..

I don''t understand what you didn''t like about my anonymous post above. (Pardon the anon before; didn''t have my pword handy at the time.)

You say that what I did was very bad, then go on to say that each triangle should contain only a face normal and 3 indices into the vertex list. Well, what do you call this?

  struct vert { vec3d pos; vec3d norm;}; struct face { // a triangle vec3d norm; int vert[3];}; // globals arraysvert myverts[NVERTS];face myfaces[NFACES];

I yanked this exactly as I wrote in a previous post. I have exactly what you specified as what should be done. My ''face'' structure has only a normal and three indices that point into the myverts array. There is no vertex information in the ''face'' struct; the vertex normal and position is in the ''vert'' struct.

And, although you did not contest this part, realize that normalization of the summed vertex normal will give you the average just fine.

One further note: this process will give you a smoothed appearance to your surface, since the vertex position AND the vertex normal are shared between all faces that reference (read: index) that vertex. However, if you want sharp edges in your model (which is not at all unusual), then a single normal per vertex is insufficient.

To get the flexibility of having hard and smoothed edges in the same model, you must either keep multiple copies of the same vert structure with different normals (and point the faces properly at them), or move the vertex normal information into the face struct, like this:

struct face {
vec3d norm; //face normal
vec3d vnorm[3]; //vert normals
int vert[3]; //index into vertex list
};

This is how I have created my vert/face structures for several professional projects. Realize that in any algorithm you choose, you have tradeoffs. Here, I waste some memory if my model is completely smooth. But with the first post I made, the tradeoff is that it MUST be completely smooth, not something I can force on our artists. Another alternative is to set up another level of indirection (to keep vertex normals, colors and texture coords out of the vert and face structs). This provides the least memory waste for non-trivial models, but the extra indirection is a performance hit.

So, sorry to rant on like this.... Nicos, your suggestion is correct, but no different from what I originally posted anonymously. And the suggestion of some heuristic for weighting the normals by area or angle is a good suggestion, but I neglected to mention it because I felt to give the original poster something simple to start with.

---- --- -- -

##### Share on other sites
I just saw the vert [3] without seeing the int...
sorry mossmoss

##### Share on other sites
quote:
Original post by Nicos

b) add the normals of all those polygons together, then divide by the number of polygons.

Edited by - Nicos on August 26, 2000 5:45:07 PM

Dividing by the number of polygons is not the way to do it. This will not give you a normalised vector. Better to normalise the resultant vector than divide by the number of polys.

##### Share on other sites
I alway used to normalize after dividing by the number of polys.
Either way my software render produces damn fine looking images/animations. At the end of the day thats all that matters.

##### Share on other sites
  N = { 0.5, 0.5, 0.7071067811865 };M = { -0.5, 0.5, 0.7071067811865 };(N.x + M.x)/2 = 0; // now it goes bad(N.y + M.y)/2 = 0.5;(N.z + M.z)/2 = 0.7071067811865;

This is a common mistake, I also fallen for - more than once!
Normalizing is the only way!

quote:

i donno about using the size of the triangle, commom practice is to "weight the normals by the size of the angles at the shared intersection"

This might not be an easy thing to do. There was a thread that started with this some time ago: Metaballs - Normals

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 15
• 11
• 9
• 9
• 44
• ### Forum Statistics

• Total Topics
634131
• Total Posts
3015720
×