PDA

View Full Version : calculate the normals of all the triangles in an array of vertices

Nico
04-28-2000, 05:32 AM
Hi...

I have an array of 36 vertices: cube[36][3]...

I'd like to write functions that compute normals for each individual triangle of the array...

How could I?

Humus
04-28-2000, 06:54 AM
Use vector cross product. If vertices are
v1,v2,v3 then the normal is
N = (v2 - v1) x (v3 - v1)
You'll have to scale it down to length 1 also.

Nico
04-28-2000, 07:12 AM
Welll... I know the basics... what I don't know is how to apply it to programming...

Here are my functions...

void calculateNormals(float v[3][3], float n[3])
{
float v1[3], v2[3];
x=0; y=1; z=2;

v1[x] = v[0][x] - v[1][x];
v1[y] = v[0][y] - v[1][y];
v1[z] = v[0][z] - v[1][z];

v2[x] = v[1][x] - v[2][x];
v2[y] = v[1][y] - v[2][y];
v2[z] = v[1][z] - v[2][z];

n[x] = v1[y]*v2[z] - v1[z]*v2[y];
n[y] = v1[z]*v2[x] - v1[x]*v2[z];
n[z] = v1[x]*v2[y] - v1[y]*v2[x];

ReduceToUnit(n);
}

void ReduceToUnit(float vector[3])
{

Length=(float)sqrt((vector[0]*vector[0])+(vector[1]*vector[1])+(vector[2]*vector[2]));

if (Length==0.0f) Length = 1.0f;

vector[0] /= Length;
vector[1] /= Length;
vector[2] /= Length;
}

What I can't get to do is... calculate the normals of the triangles of my object... The vertices of my object are stored in cube[36][3]...

How could I use the calculateNormals function to actually calculate all the normals of all the triangles of my object?...

Another thing is I don't understand the arguments v[3][3] and n[3]...

And how could I draw these normals to check them out?

I gues my question is better written this time...

Many thanks...

Humus
04-28-2000, 08:29 AM
First, use cube[3][36] instead of cube[36][3]. Then rewrite calculateNormals(float v[3][3], float n[3]) to calculateNormals(float v0[3], float v1[3], float v2[3], float n[3]).
Replace every v[0][x] with v0[x] ... and the same with the others.
Then you can use it like calculateNormals(cube[7], cube[21], cube[14]) or whatever.

Nico
04-29-2000, 05:29 AM
I tried what you told me... however I still don't know how to use the function to compute the normals of all the triangles of my object... here are the changes I made...

First of all... this is how I use the function... does it compute the normal of the first triangle?:
calculateNormals( cube[0], cube[1], cube[2], normals);

I guess this compute the normal for the second triangle?:
calculateNormals( cube[1], cube[2], cube[3], normals);

By the way this is how I declared the variable normals: static float normals[3];
I guess it's not big enough to store all the normals?

Here the two functions I use to calculate the normals:

void calculateNormals(float p0[3], float p1[3], float p2[3], float n[3])
{
float v1[3], v2[3];

x=0; y=1; z=2;

//Vector offset
v1[x] = p0[x] - p1[x];
v1[y] = p0[y] - p1[y];
v1[z] = p0[z] - p1[z];

v2[x] = p1[x] - p2[x];
v2[y] = p1[y] - p2[y];
v2[z] = p1[z] - p2[z];

//Get normals: cross product of two vectors v1 and v2
n[x] = v1[y]*v2[z] - v1[z]*v2[y];
n[y] = v1[z]*v2[x] - v1[x]*v2[z];
n[z] = v1[x]*v2[y] - v1[y]*v2[x];

//normalize the vector (shorten to one)
ReduceToUnit(n);
}

void ReduceToUnit(float vector[3])
{
Length=(float)sqrt((vector[x]*vector[x])+(vector[y]*vector[y])+(vector[z]*vector[z]));

if (Length==0.0f) Length =1.0f;

vector[x] /= Length;
vector[y] /= Length;
vector[z] /= Length;
}

How could I draw the normal?

Many thanks

Humus
04-29-2000, 09:49 AM
If the first triangle has vertices cube[0],cube[1] and cube[2] then calculateNormals( cube[0], cube[1], cube[2], normals[0]) places the normal to this triangle in the normals[0] array. You should make normals an array like
float normals[3][WHATEVER_NEEDED];

To draw the normal just draw a line from the vertex to vertex + normal.

Nico
04-30-2000, 05:23 AM
Hi...

If I want calculate 12 normals of my cube(I have 12triangles)... I need to declare normals[3][12]... is that right?

Can you explain more in detais how to draw the normals please... I did not get it...

Many thanks

Humus
04-30-2000, 07:39 AM
Yes, that's right.
To draw the normal, say you have a vertex v and a normal n:
float v[3],n[3];

Your first point is (v[0],v[1],v[2]) and the other is (v[0] + k * n[0], v[1] + k * n[1], v[2] * k * n[2]) ... you may perhaps need to scale the normal, so choose k suitable.

Nico
05-02-2000, 05:12 AM
Thanks for the answer... What is k? (sorry if it is a stupid question!)

Humus
05-02-2000, 06:40 AM
k is just a constant you can choose whatever you think is appropriate. You'll probably not want normals that is too short to be seen or too long to fit on screen.

Nico
05-02-2000, 10:36 AM
A simple question... How come a normal vector is only defined by x, y and z as it is not a point but a vector... I'm just a beginner... http://www.opengl.org/discussion_boards/ubb/smile.gif

Humus
05-02-2000, 11:16 AM
Well ... a vector is something that points out a direction and doesn't have any kind of position.

Nico
05-03-2000, 04:02 AM
Thanks to your help I managed to display the normals correctly... however, I'd like to draw them in the middle of the triangles... how can I?

Thanks

dmy
05-03-2000, 04:25 AM
nico:
a vector express a direction and a magnitude. the direction is across the line from the origin (0,0,0) to the vector endpoint, the magnitude is the lenght of the vector.
a special vector is the unit vector, also called versor, wich has lenght =1, and in fact express only a direction.
so, normals are substantially versors.

a way to find the triangle baricenter is to average the the triangle vertices together.

in pseudocode:

center=(a+b+c)/3
endpoint=center+normalize(center)*NORMAL_LEN;

glBegin(GL_LINES);
glVertex3fv((float *)&center);
glVertex3fv((float *)&endpoint);
glEnd();

a,b,c are the triangle verts.
center,endpoint are your normal line endpoints.

i recommend you to write overloaded operators to work easily with vector operations http://www.opengl.org/discussion_boards/ubb/smile.gif

Dolo/\/\ightY

Nico
05-03-2000, 05:36 AM