PDA

View Full Version : Calculating Normals?



hooded paladin
11-11-2001, 07:17 PM
I want to do lighting, but doing my own normals is sloppy and a pain in the ... I know there are algorithims to do it but I don't know it and I'm not into advanced math! Can anyone supply some code?

dorbie
11-11-2001, 08:15 PM
The normal is a cross product of two edges of the polygon. The winding (clockwise vs counter clockwise) determines whether the normal points 'in' or 'out' of the object.

So, search the web for "surface normal" and "cross product".

ByteZero
11-11-2001, 08:23 PM
Hi

Here is some code of for normals calculation
base on the Redbook

//Header File Code
#include <math.h>
#ifndef __VECTOR_H__
#define __VECTOR_H__

void CrossProdukt(double v1[3], double v2[3], double out[3]);
void NormalizeVector(double v[3]);
void SubDivide(double* v1, double* v2, double* v3);

#endif __VECTOR_H__

//Here is the Code your *.c or cpp file
#include <windows.h>
#include "Vector.h"


void NormalVector(double v[3])
{
double norm = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
if(norm == 0.0)
{
MessageBox(0, "Zero Vektor","VECTOR ERROR",MB_OK);
PostQuitMessage(0);
}
v[0] /= norm;
v[1] /= norm;
v[2] /= norm;
}


void CrossProdukt(double v1[3], double v2[3], double out[3])
{
out[0] = v1[1] * v2[2] - v1[2] * v2[1];
out[1] = v1[2] * v2[0] - v1[0] * v2[2];
out[2] = v1[0] * v2[1] - v1[1] * v2[0];

NormalVector(out);
}

void SubDivide(double* v1, double* v2, double* v3)
{
double v12[3], v23[3], v31[3];
for(int i = 0; i < 3; i++)
{
v12[i] = (v1[i] + v2[i]) / 2.0;
v23[i] = (v2[i] + v3[i]) / 2.0;
v31[i] = (v3[i] + v1[i]) / 2.0;
}
}
/////
for more Info's look at the OpenGL "RedBook".
they explain the Calculation of Normals, I hope that Helps

Firestar
11-11-2001, 10:55 PM
Hi!

As dorbie already said, a normal is a cross product (or the vector product) of two vectors. This two verctors form a normal plane and the normal vector is perpendictular to this two vectors and the plane.
As is goes for the calculation of the two vectors you can get them from the polygon vertices (you can get them from any 3 vertices)

vec1.x = vertex2.x - vertex1.x;
vec1.y = vertex2.y - vertex1.y;
vec1.z = vertex2.z - vertex1.z;
vec2.x = vertex3.x - vertex1.x;
vec2.y = vertex3.y - vertex1.y;
vec2.z = vertex3.z - vertex1.z;

when you have this two vectors you make a cross product with them (look for more information what a cross product is and how to calculate one on the net). Now the only important thing is that this cross product of the two vectors is another vector:

crossVector.x = v1.y*v2.z - v1.z*v2.y;
crossVector.y = v1.z*v2.x - v1.x*v2.z;
crossVector.z = v1.x*v2.y - v1.y*v2.z;

This vector is your normal vector. Now all there is left to do is to normalize this vector (to make it the length of 1). You do this by dividing all its components (x, y and z) by its length. You get the length:

length = sqrt(crossVector.x*crossVector.x+crossVector.y*cro ssVector.y+crossVector.z*crossVector.z);

normal.x = crossVector.x/length;
normal.y = crossVector.y/length;
normal.z = crossVector.z/length;

Actually it's better to check if the length is 0, so you don't get the Divide by Zero exception.

Cheers

Firestar

hooded paladin
11-12-2001, 08:15 AM
Thanks. Now, I know vertex normals for smooth shading is just the average of the normals of the planes that the vertex touches, but what is the code to implement it? Is it glNormal3f, just changing each vertex?

dorbie
11-12-2001, 10:33 PM
The simplest approach is to just average the normals by adding the components and divide by the number of normals you added. So for 3 tris touching a a vertex for example you'd need:

x_vert=(x_face1+x_face2+x_face3)/3.0;
y_vert=(y_face1+y_face2+y_face3)/3.0;
z_vert=(z_face1+z_face2+z_face3)/3.0;

You then renormalize the resulting normal by dividing by it's length.

If you have a good C++ class with operator overloads you should just be able to add the vectors and divide by the count, then normalize.

[This message has been edited by dorbie (edited 11-13-2001).]