PDA

View Full Version : problem w/ normals for lighting



06-05-2002, 02:28 PM
I'm new to OpenGL and I'm trying to get a function to calculate surface normals so I can put lights in my program. I've looked at a bunch of tutorials (NeHe, gametutorials) and they all pretty much say the same thing: get two vectors, find the cross product, normalize. I've tried this and it doesn't seem to work correctly. Can somebody plz help? I'm desparate...

Here's my function to get the surface normal:



void VectorNormal(point_t p1, point_t p2, point_t p3)
{
point_t cross, v1, v2, normal;
float len;

v1[0] = p3[0] - p1[0];
v1[1] = p3[1] - p1[1];
v1[2] = p3[2] - p1[2];

v2[0] = p2[0] - p1[0];
v2[1] = p2[1] - p1[1];
v2[2] = p2[2] - p1[2];

cross[0] = ((v1[1] * v2[2]) - (v1[2] * v2[1]));
cross[1] = ((v1[2] * v2[0]) - (v1[0] * v2[2]));
cross[2] = ((v1[0] * v2[1]) - (v1[1] * v2[0]));

len = (float)sqrt((cross[0] * cross[0]) +
(cross[1] * cross[1]) +
(cross[2] * cross[2]));

cross[0] /= len;
cross[1] /= len;
cross[2] /= len;

normal[0] = cross[0];
normal[1] = cross[1];
normal[2] = cross[2];

glNormal3fv(normal);
}

point_t is a typedef of an array of 3 floats. Can anyone see whats wrong w/ this code? Thanks for all your help!

reubenhawkins
06-05-2002, 06:03 PM
Pardon my spelling if you would...

How are you defining your surface? Are you creating the surface with an equation or are you just tring to find the average normal between adjacent polygons?

I need to know more about what you are doing in order to tell you exactly how you do it (assuming I know how anyway...).

Finding a normal for any tryangle is simple. For triangle ABC, the surface normal is BA X BC (that's BA cross BC).

BA X BC is always perpindicular to BA and BC and IF (BA is pointing in the direction of the positive Z-axis AND BC is pointing in the direction of the positive X-axis) THEN BA X BC is pointing in the direction of the positive Y-axis. That doesn't work the other way around though (that's the right-hand rule).

BA X BC is equal the the det of a 3x3 matrix. Another words
if BA = <a, b, c> "<>" means "vector"
and BC = <x, y, z>
then BA X BC = <bz-yc, xc-az, ay-xb>
weird ain't it?

Now that you name the normal for one triangle, You have to get the average normal with the surfaces near by. to do that...

(I'm almost sure this works though I've never actually used this in a computer program. This is what I would do on a Calc exam)

To Average normal: sum all the normals you want to average and normalize it. To normalize: devide the X Y and Z of the new normal (the sum of the normals) by
squt(X*X+Y*Y+Z*Z)
or just do a glEnable(GL_NORMALIZE) or something like that.

If your surface is defined by a math equasion then do this to find the surface normals...

Say your equastion is a cylinder along the x-axis...
//s and t are independant variable just as
//x is an independant variable in f(x)
//but x=s y=sin(t) z=cos(t)
//it's a vector valued function V(s,t)
V(s,t) = <s,sin(t),cos(t)> //cylinder

the normals are:
dV/ds X dV/dt

dV/ds is the derivative of V with respect to s. dV/dt is the derivative of V with respect to T.

dV/ds = <1, 0, 0>

dV/dt = <0, cos(t), -sin(t)>

dV/ds X dV/dt = <0, sin(t), cos(t)>

If you want a samply program send me an email...

Snikies that was long!!!

reubenhawkins
06-05-2002, 06:50 PM
say if you have three lines beginning at PointCommon and each end at point1, point2 and point3; such as the corner of a cube...

Find the vector from those point

Vector1 = point1 - PointCommon;
Vector2 = point2 - PointCommon;
Vector3 = point3 - PointCommon;

the normal on the corner of the cube would be...

Normal = Vector1 + Vector2 + Vector3;
len = -sqrt(Normal.x^2 + Normal.y^2 = Normal.z^2)
Normal.x /= len
Normal.y /= len
Normal.x /= len

glNormal3fv(&Normal.x);

Notice the "-" sign in from ot sqrt. Thats becuase without it the normal points inside of the cube. The "-" will make it point 180 degrees in the other direction...

void FindNormal(point1, point2, point3, pointcommon)
{
float len;
point Normal;

Normal.x = point1.x + point2.x + point3.x;
Normal.y = point1.y + point2.y + point3.y;
Normal.z = point1.z + point2.z + point3.z;

Normal.x -= PointCommon.x;
Normal.y -= PointCommon.y;
Normal.x -= PointCommon.x;

len = -sqrt(Normal.x^2 + Normaly^2 + Normal.z^2);

Normal.x /= len;
Normal.y /= len;
Normal.z /= len;

glNormal3fv(&Normal.x);
}

I think this might work for you.

06-06-2002, 04:22 AM
thanx for all the help, I got it to work. I think it was a problem with defining vertices counter-clockwise.