Weighted normals

I’ve calculated normals like this:

CVector Edge_12 = m_Vertices[Point2] - m_Vertices[Point1];
CVector Edge_20 = m_Vertices[Point0] - m_Vertices[Point2];
CVector Normal = Edge_20.Cross(Edge_12);

m_Normals[Point0] += Normal;
m_Normals[Point1] += Normal;
m_Normals[Point2] += Normal;

However the corners that have more triangles joining with it have the normals a litle bit wrong. This is most easily seen when looking at a cube.

I recall something about weighting the normals based on the angular portion of vertex.

I can’t quite work out the trig math needed however to scale the angles and portion up the normals. Anyone care to post a code fragement\link\insight to help me get started?

I check the red book and that only had unweighted normal generation, I also checked nate.scuzzy.net’s normal generation, but that didn’t help me either. I seem to remember something to do with taking the acos of the cross product of the two relevant ajoining lines, somethng like that.

Many thanks for any help…

From the code sample you provided I can only see 3 possible problems. The first is to make certain that your calculated normal vectors are of unit lenth (i.e. length = 1.0). The second is that you are using += instead of = when assigning the normal to the normal array. If your aray was not initialized to 0 for each element you may get erroneous results. The third possible problem is your cross product which relies on the right hand rule to work correctly or it will result in the negative (-1 * v) of the expected vector.

For vertices at the corners of a cube, there should be 3 normals associated with it and for all vertices forming the edges, there should be 2 normals associated. Not one. For objects where the surface is meant to be smooth, your method should probably work. But, be sure to unitize the vectors before addition.

After just rereading your post, that probably is the problem. You are adding the 3 normal vectors that should be associated with the corner vertices into one vector. But, for a cube, and many other objects where definite faces exist and are desired, there should be multiple normals. For objects such as a sphere, your current method would probably work correctly though be sure to unitize (length = 1) before vector addition otherwise the resulting vector may be weighted without your knowledge.

Hope it helps.

Sorry I clipped a little too much code…

  1. I normalise the vectors after all the additions are done.
  2. “+=” is used. Correct. The array is zero’ed before use.
  3. While it’s true that my cross product is dependent on CCW polygon ordering, I’m getting the poly’s from LWO n-sided polygons and triangulating them. I control the winding. so it’s cool.

Still though, when I have a large polygon angle and a small splinter polygon the proportion of the face normal has on the vertex normal I’m generating. Each polygon that touches a vertex adds it’s portion it’s angle * normal to the vertex normal. Larger angles have a larger weight on the vertex.

Does this make sence…

Two things.

1 - You should unitize vectors prior to addition. The reason is that there is no guarantee that the length of the vectors is equal, and if not, the resulting normal will be weighted toward the longest normal, which appears to be what is happening.

2 - If a vertex exists at an edge or corner where there is discontinuity (cube) there should be more than one normal. For continuous surfaces such as spheres of smooth curvatures the vertex can (doesn’t have to) share the same normal.

From what you have said it sounds as if you are looking to have each vertex have one normal which in continuous surfaces is fine, but for objects such as cubes it probably would not look right.