This is maybe a very stupid question.

Lets say i have a glVertex3f(0.78,0.45,0.21),

how do i calculate a normal for it?

# Normals ?

You can’t really calculate a normal for a single vertex. A normal is a vector with length 1 that’s perpendicular to the surface, and a surface needs a minimum of three vectors. If you’re doing flat shading, you usually calculate one normal per polygon. If you’re doing Gouraud shading, you usually calculate one normal per vertex so that you can interpolate between them.

To calculate the normal for a triangle, pick one vertex, subtract it from the other two, find the cross product of these other two, and normalize the resulting vector (divide each component by the vector’s length).

To calculate the normal for a vertex, just average the normals for the triangles which use it.

All this stuff should be in the Red Book.

Hi !

You can not calculate a normal with only one vertex…

If you want a normal, you need at least a plane (3 points)… Then the normal for those 3 points could be the plane normal.

The thing is, if you do that, you won’t have smooth shading.

I used to calculate my normals the following way :

- For all my faces in the model, calculate the normal (normalized).
- For all the vertices in the model, find which face they belong to. Add all the normals of these faces and normalize the result : you have your vertex normal.

I know many people will shout at me coz’ it is a really simplistic approach…

In 2), you could multiply each normal you add by the surface of the face it belongs to. Then, you normalize… It means that the wider the face is, the most important is the contribution of its normal vector for the vertex normal…

Still in 2) : you do not always want to add all the normals of the faces the vertex belongs to… Usually, you add them when the angle between the normals of two faces is more or less a certain limit angle (close to 0)… Otherwise you end up with a fully-smoothed object (which is stupid, say, for a cube !).

This might sound a bit confused (well, English is not my native language !) but the point is : you can not tell the normal of a vertex from its coordinates. In fact, you can never tell the normal of a vertex (from the mathematical point of view !).

Hope this will help…

Eric

P.S. : perhaps you should have a look on the net at normals generation…

well, the hell

if your vector is X, Y, Z

Nx = X / sqrt(X*X + Y*Y + Z*Z)
Ny = Y / sqrt(X*X + Y

*Y + Z*Z)

Nz = Z / sqrt(X

*X + Y*Y + Z*Z)

But, in the context of OpenGL, Vertex is not a vector (I mean starting from 0,0,0 to you)

But anyway…

(sorry for my badd inglish)

malkia@mindless.com

malkia/eastern.analog http://EasternAnalog.hypermart.net

BTW: Anybody got idea how to do fast normalization, I was thinking about NTAB[128][128][128], where NTAB[X][Y][Z] = X / sqrt(X*X+Y*Y+Z*Z), and X,Y,Z are from 0…1 (mapped to 0…127 though), I need it for my raycaster? any ideas? The other way is to rotate all my rays

Originally posted by MikeC:

To calculate the normal for a triangle, pick one vertex, subtract it from the other two, find the cross product of these other two, and normalize the resulting vector (divide each component by the vector’s length).

Ok, but what if I have an eight sided polygon? Would I get an correct answer if I use the first three vertices? (assuming the face is ‘flat’)

And doesn’t it matter which sequences I use from the vertices, eg. (a-b, c-b) or (b-a, c-a) ?

John

Sjonny - yes, as long as your polygon is flat, you can generate a face normal from only three verts.

The order is important, and depends on your “front-facing” setting. For the default - frontfacing polys have vertices specified anticlockwise - pick three successive verts v1, v2 and v3 of your polygon in anticlockwise order. Then use the cross product of the vectors (v2-v1) and (v3-v1).

Just a precision MikeC : you can of course use any of three vertices of a flat polygon for calculating the normal providing THEY ARE NOT ALIGN ! Otherwise you end up with two colinear vectors and the dot product is nil… (not good for normalizing then !).

Well, this is just a special case but I thought it was worth mentioning it !

Eric

Eric - oops, yes, good point. Not sure why you’d have successive colinear verts in a polygon, but it’s always the unexpected that trips you up.

You could also come unstuck if you picked three verts on a concave section of the polygon boundary - since your normal would then be pointing the wrong way - but that would probably serve you right for using concave polys.

Life is *so* much simpler if you stick to triangles…

Originally posted by malkia:

BTW: Anybody got idea how to do fast normalization, I was thinking about NTAB[128][128][128]

As a general rule, lookup tables are a bad idea on modern processors. You take more of a hit for thrashing the data cache than you would for just doing the calculation.

If you aren’t too bothered about accuracy, there are fast algorithms to approximate the sqrt. Try a search for “Newton-Raphson iteration”.

Originally posted by MikeC:

[b] As a general rule, lookup tables are a bad idea on modern processors. You take more of a hit for thrashing the data cache than you would for just doing the calculation.

If you aren’t too bothered about accuracy, there are fast algorithms to approximate the sqrt. Try a search for “Newton-Raphson iteration”. [/b]

Yeah, MikeC, you are right, but I have also division - X / sqrt(X*X+Y*Y+Z*Z) - plus 3 multplications, also at the end i’ll take BYTE, which i will use at another table - CTAB[256][256] which calculates tan(a)*tan(b)/( tan(a) + tan(b) )

It’s really weird. But algorithm i’m trying to implement is called “ACCELERATED RAY CASTING OF HEIGHT FIELD, USING INVERTED CONES”

So, at all I have 4.5MB (****in L2 is max 2MB) cache. But i don’t care (for now)…

BTW: About optimization. I was trying to get ABSOLUTE value, without some JE, or JNE code, cause they causing bad pipelining

VC generates for labs(x) following

test eax, eax

jb down // or ja - can’t think now at the moment

neg eax

down:

I’ll rewrite this to:

int INLINE ABS32( int x )

{

return (x ^ (x>>31)) - (x >> 31);

}

which is i think - better (just on Pentiums only)

I got this all from the Red Book as well. But my object is only lit where Z is positive. The polygons that have a -Z component are all blacked out. But when I use just my face normals (flat shading), all polygons are lit everywhere, including -Z.

Perhaps averaging face normals followed by normalizing isn’t enough? Since only positive Z is lit when smoothing shading via vertex normals approx, then perhaps we are missing something.

Hmmm… if you take a square root, then the result can either be + or - depending on which quadrant the vertex lies in? Or am I off track?

only positive Z is lit when smoothing shading via vertex normals

Rey - could you describe this problem in more detail? I’m a bit confused, since anything with a (transformed) positive Z coordinate is behind the camera.

About the last bit; a square root can never be negative (for obvious reasons) so yes, I think you’re a bit off track there.

I meant with respect to the local coordinate system of the object that I created.

So let’s assume the object is in the origin. Then follow the usual right hand rule where X is the horizontal, Y is the vertical, and Z sticks out toward you as positive. Vertices that lie on the other side of the origin (behind the monitor hehehe) is negative. Wish I can attach a screen shot in jpg format of my app…