This is an old problem of mine. I think it's about time i search for an answer.
Consider these cubes:
To calculate the vertex normal for "p" on the left cube, i would do this:
Add the normals for all surfaces connected to vertex "p". (A, B and C)
Then i would normalize the result.
If i do the same on the right (Add the normals of A,B,C,D and E) , however
the normal for p won't be the same as the normal for p in the left cube.
Isn't this the way to do it?
Aren't the normals for "p" in both cubes supposed to be the same? (It's the same cube, basically)
I've also heard about calculating vertex normals using the Cross-product. can this be done with this example?
I bet there's some simple solution.... i predict i'm gonna go "DOH!" when i see an answer. [embarrass]

**0**

# Calculating Vertex Normals...

Started by SimonTheSorcerer, Nov 14 2005 02:07 AM

12 replies to this topic

Sponsor:

###
#2
Members - Reputation: **440**

Posted 14 November 2005 - 02:38 AM

Quote:

Original post by SimonTheSorcerer

This is an old problem of mine. I think it's about time i search for an answer.

Consider these cubes:

To calculate the vertex normal for "p" on the left cube, i would do this:

Add the normals for all surfaces connected to vertex "p". (A, B and C)

Then i would normalize the result.

If i do the same on the right (Add the normals of A,B,C,D and E) , however

the normal for p won't be the same as the normal for p in the left cube.

Isn't this the way to do it?

Aren't the normals for "p" in both cubes supposed to be the same? (It's the same cube, basically)

I've also heard about calculating vertex normals using the Cross-product. can this be done with this example?

I bet there's some simple solution.... i predict i'm gonna go "DOH!" when i see an answer. [embarrass]

There are three types of normals of possible use in this case:

- face normals: the normals of the faces/triangles of your model. These are perpendicular to the plane in which a triangle lies and can be calculated by taking the cross product of two vectors in that plane (for a triangle with points p1,p2 and p3 this would be something like: (p2 - p1) x (p3 - p1)).

- edge normals: these are not very popular as they cannot be easily (if at all) expressed in OpenGL or Direct3D, but can be calculated by averaging the face normals of the 2 faces it separates.

- vertex normals: these are typically calculated by averaging the normals of all faces it is part of (e.g. on the left cube it would be the average of the normals of quads A, B and C, on the right cube the average of the normals of triangles A, B, C, D and E which indeed gives a different result as the plane of triangle A counts less to the average). Note that this calculation depends on knowing the face normals, so those must already have been calculated. The result could also be calculated from averaging the normals of all edges leaving that vertex.

Anyway, it is important to know when to use vertex normals and when to use face normals. Vertex normals are use to "smooth" curved surfaces, whereas face normals give sharp edges. Obviously, there is nothing smooth about a cube, so I suggest using face normals here.

This is how the drawing code differs for the two approaches in pseudo OpenGL:

// face normals, a single normal applies to all vertices:

glBegin(GL_TRIANGLES);

glNormal(triangle.face_normal);

glVertex(triangle.p1);

glVertex(triangle.p2);

glVertex(triangle.p3);

glEnd();

// vertex normals, each vertex has its own normal:

glBegin(GL_TRIANGLES);

glNormal(triangle.n1);

glVertex(triangle.p1);

glNormal(triangle.n2);

glVertex(triangle.p2);

glNormal(triangle.n3);

glVertex(triangle.p3);

glEnd();

Tom

###
#3
Members - Reputation: **250**

Posted 14 November 2005 - 02:48 AM

Well, the reason you can't work out a vertex normal for p is because there isn't one. Mathematically, vertices don't have normals - faces and points on surfaces have normals, but not vertices. Vertex normals are used in Computer Graphics to simulate smooth surfaces. Since you're making a cube, which is made of faces, you should be using face normals (or use 3 vertices for point p; 1 for each face)

I hope this helps clarify things.

I hope this helps clarify things.

###
#4
Members - Reputation: **645**

Posted 14 November 2005 - 02:56 AM

Hi,

héhé, this problem is quite annoying ^^ It comes from the fact that in the right figure, for 2 faces of the cube, you have 2 TRIANGLES (E, D for the top face, and B, C for the right face) connected to p, and the third face (the front face) only has ONE TRIANGLE connected to p. So the normal at that point will lean toward the Z and X axis.

You will always have that problem with triangles. I partially solved this problem by computing my normals BEFORE triangulating my meshes.

But if you want to solve this problem, you can use the following algorithm :

If fact, here, your checking for coplanar triangles. For example, in your example, you'll add the E normal to vertex p, and when you want to add D's normal, you'll see that the normal is already in the list (since E and D normals are the same) and so you won't add it.

In terms of coding, it's not difficult. Instead of simply adding faces normals, you just add a little test to see if the normal was already added or not. BUT that introduce some overhead if you process big meshes ^^ (that's why I computed my normals before triangulation)

héhé, this problem is quite annoying ^^ It comes from the fact that in the right figure, for 2 faces of the cube, you have 2 TRIANGLES (E, D for the top face, and B, C for the right face) connected to p, and the third face (the front face) only has ONE TRIANGLE connected to p. So the normal at that point will lean toward the Z and X axis.

You will always have that problem with triangles. I partially solved this problem by computing my normals BEFORE triangulating my meshes.

But if you want to solve this problem, you can use the following algorithm :

for each vertex:

for each triangle:

add face normal to the vertex ONLY IF IT DOESN'T ALREADY EXSITS

average the normals

If fact, here, your checking for coplanar triangles. For example, in your example, you'll add the E normal to vertex p, and when you want to add D's normal, you'll see that the normal is already in the list (since E and D normals are the same) and so you won't add it.

In terms of coding, it's not difficult. Instead of simply adding faces normals, you just add a little test to see if the normal was already added or not. BUT that introduce some overhead if you process big meshes ^^ (that's why I computed my normals before triangulation)

###
#5
Crossbones+ - Reputation: **6524**

Posted 14 November 2005 - 02:59 AM

I agree to what dimebolt has written, but also will clarify some other things asked in your post.

They should be the same, and they become the same if considering this (this is a more general solution to those dimebolt has mentioned): Don't sum the face normals as are, but weight them with the angle they participate on the vertex. If doing, so, then your left cube has 3 faces all participating w/ 90 degrees. Looking at the right cube, then there are D and E both with 45 degrees, also B and C each with 45 degrees, and A with 90 degrees. The sum is 270 degrees. So the normals of E and D as well as those of B and C are weighted with 45/270, and those of A with 90/270. As you could see, the result will became the same as those of the left cube.

Hmm. Face normals are computed by cross-product. I can't image how to use it for vertex normals, but maybe...

Quote:

Original post by SimonTheSorcerer

If i do the same on the right (Add the normals of A,B,C,D and E) , however

the normal for p won't be the same as the normal for p in the left cube.

Isn't this the way to do it?

Aren't the normals for "p" in both cubes supposed to be the same? (It's the same cube, basically)

They should be the same, and they become the same if considering this (this is a more general solution to those dimebolt has mentioned): Don't sum the face normals as are, but weight them with the angle they participate on the vertex. If doing, so, then your left cube has 3 faces all participating w/ 90 degrees. Looking at the right cube, then there are D and E both with 45 degrees, also B and C each with 45 degrees, and A with 90 degrees. The sum is 270 degrees. So the normals of E and D as well as those of B and C are weighted with 45/270, and those of A with 90/270. As you could see, the result will became the same as those of the left cube.

Quote:

Original post by SimonTheSorcerer

I've also heard about calculating vertex normals using the Cross-product.

Hmm. Face normals are computed by cross-product. I can't image how to use it for vertex normals, but maybe...

###
#6
Members - Reputation: **122**

Posted 14 November 2005 - 05:25 AM

Ok, i got some answers.. goodie :)

Seems like there wasn't any "magic formula" that i had missed after all, haha.

Let's say you make these Cubes in e.g Maya, and then render them. Will they have the same appearance? (or will the normals give them different shading?)

If so, how does 3D-Progs solve this? do they "weigh" the normals like mentioned?

Also. let's say you create the left cube, and then triangulate it in Maya. Will the old normals be used or does the normals (and appearance) change after a triangulation?

Seems like there wasn't any "magic formula" that i had missed after all, haha.

Let's say you make these Cubes in e.g Maya, and then render them. Will they have the same appearance? (or will the normals give them different shading?)

If so, how does 3D-Progs solve this? do they "weigh" the normals like mentioned?

Also. let's say you create the left cube, and then triangulate it in Maya. Will the old normals be used or does the normals (and appearance) change after a triangulation?

###
#7
Members - Reputation: **645**

Posted 14 November 2005 - 09:57 PM

Hi,

If you triangulate in Maya, the normals won't be modified if you DON'T TOUCH the geometry anymore ! So as I said, you shouldn't triangulize the geometry before exporting it. You should do it internally in your exporter, so that you always work with good normals.

And if you still work with triangles, as I also said, you simply have to detect COPLANAR triangles to avoid adding the same normal twice to a vertex. I used that method a lot and it works perfectly.

You could also you weighted normals, as haegarr said, but I didn't test it (it works perfectly with the cube example though ^^)

If you triangulate in Maya, the normals won't be modified if you DON'T TOUCH the geometry anymore ! So as I said, you shouldn't triangulize the geometry before exporting it. You should do it internally in your exporter, so that you always work with good normals.

And if you still work with triangles, as I also said, you simply have to detect COPLANAR triangles to avoid adding the same normal twice to a vertex. I used that method a lot and it works perfectly.

You could also you weighted normals, as haegarr said, but I didn't test it (it works perfectly with the cube example though ^^)

###
#8
Members - Reputation: **122**

Posted 15 November 2005 - 01:23 AM

Quote:

Original post by paic

Hi,

If you triangulate in Maya, the normals won't be modified if you DON'T TOUCH the geometry anymore ! So as I said, you shouldn't triangulize the geometry before exporting it. You should do it internally in your exporter, so that you always work with good normals.

And if you still work with triangles, as I also said, you simply have to detect COPLANAR triangles to avoid adding the same normal twice to a vertex. I used that method a lot and it works perfectly.

You could also you weighted normals, as haegarr said, but I didn't test it (it works perfectly with the cube example though ^^)

So you should always do your modeling with quads and triangulize in the exporter then?

i'm still a bit sceptic about Coplanar triangles though. i discussed this with some friends. if B&C and D&E are coplanar than the cube will look fine, yes.

What if they only are nearly coplanar. Then those normals would be added and make a huge difference compared to if they were skipped.

Although the appearance should only be affected ever so slightly due to the ever so slightly changed normal.

###
#9
Members - Reputation: **645**

Posted 15 November 2005 - 01:46 AM

Yes, our graphists usually make models using quads (every graphist should model with quad ^^) and I triangulate myself in the exporter. This way, I'm sure the normals are not screwd up. Because even Maya has the same problem as you ! If you create the cube, triangulate it, and make Maya recalc the normal ... they will be wrong >_<

For my method, I don't say it's the perfect method. I actually think Haegarr's method is better. But I did use my method for quite a time, and I didn't test Haegarr's one. And I usually only speak about what I know ^^ So, my advice would be : try Haegarr's method first. And if you have problems, you can try my dirty trick ^^

For my method, I don't say it's the perfect method. I actually think Haegarr's method is better. But I did use my method for quite a time, and I didn't test Haegarr's one. And I usually only speak about what I know ^^ So, my advice would be : try Haegarr's method first. And if you have problems, you can try my dirty trick ^^

###
#10
Crossbones+ - Reputation: **2352**

Posted 15 November 2005 - 05:51 AM

Quote:

Original post by paic

Yes, our graphists usually make models using quads (every graphist should model with quad ^^)

Modelling with Quads is what GIVES you unexpected results, since co-planar polygons will inevitably be created, and there is no triangulation scheme that will be able to split a non-planar quad into an acceptable pair of triangles....

no artist should ever model with quads !!!!!! (well they can, but they had best make sure they manually fix any non-planar quads. The custom poly display options will let your artists see non-planar quads...)

Quote:

and I triangulate myself in the exporter. This way, I'm sure the normals are not screwd up. Because even Maya has the same problem as you ! If you create the cube, triangulate it, and make Maya recalc the normal ... they will be wrong

rubbish. Maya will calculate correct normals for a poly Cube everytime, since all faces are planar.

Triagulation of any sort can give unexpected results since a non planar quad can be triangulated in two different ways, ie generate one of two edges - there is NO way to correctly triangulate a non-planar quad. Maya uses edge info to determine correctly weighted vertex normals, there is NEVER a situation where Maya gets the normals wrong, it's just your artists....

Quote:

If you triangulate in Maya, the normals won't be modified if you DON'T TOUCH the geometry anymore ! So as I said, you shouldn't triangulize the geometry before exporting it. You should do it internally in your exporter, so that you always work with good normals.

Why are you triangulating at all? you don't need to. each face already stores it's triangles.... (MItMeshPolygon gives you the stuff you need). But as i said, you seem to be blaming triangulation unfairly, when you might want to start telling your art team off for using quads in the first place ;)

###
#11
Crossbones+ - Reputation: **6524**

Posted 15 November 2005 - 06:16 AM

My brother is a model designer since years. And he uses quads each time it is appropriate. Modelling apps seldom guarantee that quads are flat, but the designer may take care. There are many situations out there in which quads (and even higher corner count polygons) may make the life of the designer easier. And IMHO, it is the job of the programmer to fulfil the wishes of the artists.

The method of weighting the normals by the angles of the participating faces isn't my own one. dhk has recently made a thread about terrain generation, and I've suggested the weighting method. It has been implemented and decided to work well (however, his terrain has not such sharp angles as a cube has).

Quote:

Original post by paic

For my method, I don't say it's the perfect method. I actually think Haegarr's method is better. But I did use my method for quite a time, and I didn't test Haegarr's one. And I usually only speak about what I know ^^ So, my advice would be : try Haegarr's method first. And if you have problems, you can try my dirty trick ^^

The method of weighting the normals by the angles of the participating faces isn't my own one. dhk has recently made a thread about terrain generation, and I've suggested the weighting method. It has been implemented and decided to work well (however, his terrain has not such sharp angles as a cube has).

###
#12
Members - Reputation: **645**

Posted 15 November 2005 - 08:41 PM

@Rob : That's quite rude to say "rubish" at someone else's statement without giving any argument... Did you try to create a cube, triangulate it, switch to vertex edit mode, "set vertex normal" with "unlock normals" on. That's the procedure to recompute smooth normals on a mesh. Try that on a TRIANGULATED cube, and tell me if it gives good normals. At least on Maya 6.0, normals are NOT correct. And even when you "set to face" and "soften / harden" with 180° after that, the results are the same. So please, don't say something is rubbish without proving it. And don't say my graphists are at fault when you don't know them, and obviously never did the test with Maya.

As for modelling, well, you say modeller shouldn't model with quads ? Then 99% of the modellers I know (and I know a lot, I can assure you) have to go back to school. Ho, and techers also need to stop telling them to use quads ... Maybe I didn't understand what you said about quads, so, sorry if I didn't understand.

And for your last statement, I'm triangulating because DirectX wants triangles -_- And as graphists usually model with quads, I need to convert those quads into triangles. And MItMeshPolygon gives you POLYGONS, not triangles. I know the Maya C++ API quite well but if you can give me the way of getting triangle list (and NOT POLYGON) without having to do anything, I would really be happy !

Ok, sorry for the post off-topic, but I really don't like when people say "rubbish" or "your graphists suck" or stuff like that, without giving any argument.

[Edited by - paic on November 16, 2005 3:41:45 AM]

As for modelling, well, you say modeller shouldn't model with quads ? Then 99% of the modellers I know (and I know a lot, I can assure you) have to go back to school. Ho, and techers also need to stop telling them to use quads ... Maybe I didn't understand what you said about quads, so, sorry if I didn't understand.

And for your last statement, I'm triangulating because DirectX wants triangles -_- And as graphists usually model with quads, I need to convert those quads into triangles. And MItMeshPolygon gives you POLYGONS, not triangles. I know the Maya C++ API quite well but if you can give me the way of getting triangle list (and NOT POLYGON) without having to do anything, I would really be happy !

Ok, sorry for the post off-topic, but I really don't like when people say "rubbish" or "your graphists suck" or stuff like that, without giving any argument.

[Edited by - paic on November 16, 2005 3:41:45 AM]

###
#13
Crossbones+ - Reputation: **2352**

Posted 16 November 2005 - 05:55 AM

Quote:

@Rob : That's quite rude to say "rubish" at someone else's statement without giving any argument... Did you try to create a cube, triangulate it, switch to vertex edit mode, "set vertex normal" with "unlock normals" on. That's the procedure to recompute smooth normals on a mesh. Try that on a TRIANGULATED cube, and tell me if it gives good normals. At least on Maya 6.0, normals are NOT correct. And even when you "set to face" and "soften / harden" with 180° after that, the results are the same. So please, don't say something is rubbish without proving it. And don't say my graphists are at fault when you don't know them, and obviously never did the test with Maya.

you are correct, logged as bug 241378. My bad.

Quote:

Original post by paicAs for modelling, well, you say modeller shouldn't model with quads ? Then 99% of the modellers I know (and I know a lot, I can assure you) have to go back to school. Ho, and techers also need to stop telling them to use quads ... Maybe I didn't understand what you said about quads, so, sorry if I didn't understand.

Well, i taught maya for almost 4 years, over which time i taught maya to over 600 modellers, animators and programmers (so i know a few too). my lectures certainly covered the problems of non-planar quads. You can guarentee that a triangle is always planar, you can't with any other poly type. Create a quad, pull a single vertex up a bit. How will maya triangulate that? Often it's not in the way that you imagine, and so the results can look very bad. Modellers need to consider the exact triangulation on problem areas of deformation such as knees, elbows, or any other sharp contours of a model. When deforming a surface, any quads that may have been planar in a static pose, will probably be non planar when animated. It is usually at that point that the default maya triangulation (Maya has to triangulate to render the data afterall) can cause *very* ugly skinning artifacts.

It's not that modelling in quads is *bad*, but if you do, you really need to concern yourself with any quads that may be distorted later (anything skinned or blend shaped) and ideally fix those manually before going any further. Often quads are a nice primitive for modellers to work with, since there are less edges getting in the way when you split and merge faces, however leaving the model as quads is not often recommended.

Quote:

And for your last statement, I'm triangulating because DirectX wants triangles -_- And as graphists usually model with quads, I need to convert those quads into triangles. And MItMeshPolygon gives you POLYGONS, not triangles. I know the Maya C++ API quite well but if you can give me the way of getting triangle list (and NOT POLYGON) without having to do anything, I would really be happy !

check the maya docs on the following two functions :

MItMeshPolygon::numTriangles();

MItMeshPolygon::getTriangles();

you need to build up a reference between the vertex indices returned from getTriangles so you can determine which normals and UV's to use, but it does work (you can ignore the returned points, and providing any MSpace is going to be valid, since it's the indices you want and no more).