Calculating Vertex Normals...

Started by
11 comments, last by RobTheBloke 18 years, 5 months ago
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]
Debugging in progress...
Advertisement
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
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.
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 :
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)
I agree to what dimebolt has written, but also will clarify some other things asked in your post.

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...
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?
Debugging in progress...
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 ^^)
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.
Debugging in progress...
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 ^^
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 ;)

This topic is closed to new replies.

Advertisement