PDA

View Full Version : Smooth plane help


Iceman
2002.07.21, 03:13 PM
I'm trying to make one normal out of three verticies. For example this:
glNormal3f(0.0, 0.0, 0.0);
glVertex3f( 0.0, 0.0, 0.0);
glVertex3f( 0.0, 0.0, 0.0);
glVertex3f( 0.0, 0.0, 0.0);

The reason I don't just use GL_FLAT is because I want a smoothed flat plane. What am I doing wrong? Here's the code:

void triNorm(float triNormx[3], float triNormy[3], float triNormz[3]) {
float normCrossx;
float normCrossy;
float normCrossz;

float normDx;
float normDy;
float normDz;
float distance;

normCrossx = (triNormx[0] - triNormx[1]) * (triNormx[1] - triNormx[2]);
normCrossy = (triNormy[0] - triNormy[1]) * (triNormy[1] - triNormy[2]);
normCrossz = (triNormz[0] - triNormz[1]) * (triNormz[1] - triNormz[2]);

distance = sqrt(normCrossx * normCrossx + normCrossy * normCrossy + normCrossz * normCrossz);

normDx = normCrossx / distance;
normDy = normCrossy / distance;
normDz = normCrossz / distance;

glNormal3f(normDx, normDy, normDz);
}

void geTri1VertNorm3f(float vertx1, float verty1, float vertz1) {
triNorm( vertx1, verty1, vertz1);
glVertex3f( vertx1, verty1, vertz1);
}

void geTri2VertNorm3f(float vertx2, float verty2, float vertz2) {
triNorm( vertx2, verty2, vertz2);
glVertex3f( vertx2, verty2, vertz2);
}

void geTri3VertNorm3f(float vertx3, float verty3, float vertz3) {
triNorm( vertx3, verty3, vertz3);
glVertex3f( vertx3, verty3, vertz3);
}

Thanks,
Iceman

inio
2002.07.21, 05:39 PM
in all of these, p1, p3, and p3 are the three verticies of the triangle. [0] is the x componant, [1] is the y componant, and [2] is the z componant.

void CalcFaceNorm(float p1[3], float p2[3], float p3[3], float norm[3]) {
float inverseLength;

float d1[3], d2[3];

// step 1: subtract p1 from p2 to make d1 the vector of the first edge
d1[0] = p2[0] - p1[0];
d1[1] = p2[1] - p1[1];
d1[2] = p2[2] - p1[2];

// step 2: subtract p1 from p3 to make d2 the vector of the last edge
d2[0] = p3[0] - p1[0];
d2[1] = p3[1] - p1[1];
d2[2] = p3[2] - p1[2];

// step 3: calculate the cross product of d1 and d2 into norm
norm[0] = d1[1]*d2[2]-d1[2]*d2[1];
norm[1] = d1[2]*d2[0]-d1[0]*d2[2];
norm[2] = d1[0]*d2[1]-d1[1]*d2[0];

// step 4: calculate the inverse length of the normal vector.

inverseLength = norm[0]*norm[0]+norm[1]*norm[1]+norm[2]*norm[2];
inverseLength = 1.0/sqrt(inverseLength);

// step 5: scale the normal by this factor
norm[0] *= inverseLength;
norm[1] *= inverseLength;
norm[2] *= inverseLength;
}

Not sure what that last bit of code was for, but if you want something to draw a single flat-shaded triangle (this assumes glBegin(GL_TRIANGLES) has been called allready)

void DrawTri(float p1[3], float p2[3], float p3[3]) {
float normal[3];
CalcFaceNorm(p1, p2, p3, normal);
glNormal3fv(normal);
glVertex3fv(p1);
glVertex3fv(p2);
glVertex3fv(p3);
}

Iceman
2002.07.21, 06:29 PM
Thanks. I was trying to make something like your "void DrawTri(float p1[3], float p2[3], float p3[3])", but I wasn't sure how to go about programming it. Obviously "void geTri1VertNorm3f(float vertx1, float verty1, float vertz1)" was not the answer.

Thanks,
Iceman

Iceman
2002.07.22, 03:40 PM
Hmm it's still not working. here's the part that I think is the problem:

void geTriVertNormal3f( float vertx[3], float verty[3], float vertz[3]) {

glVertex3f( vertx[0], verty[0], vertz[0]);
glVertex3f( vertx[1], verty[1], vertz[1]);
glVertex3f( vertx[2], verty[2], vertz[2]);
}

then I write the verticies in like this:

geTriVertNormal3f( 0.0, 0.0, 1.2);
geTriVertNormal3f( 1.0, -2.0, 0.3);
geTriVertNormal3f( 2.0, -1.0, 0.3);

I get an incompatible type error when I try to build this. What am I doing wrong?

Thanks,
Iceman

kainsin
2002.07.22, 03:55 PM
geTriVertNormal3f wants three arrays of floats with three elements each. You are trying to pass it three floating point numbers instead.

Iceman
2002.07.23, 06:32 PM
Ok I figured it out. Sorry for all the confusion my coding needs to get better :rolleyes:.

void geTriVertNorm3f( float vertx1, float verty1, float vertz1,
float vertx2, float verty2, float vertz2,
float vertx3, float verty3, float vertz3) {
float normAverx;
float normAvery;
float normAverz;

float normdx;
float normdy;
float normdz;
float distance;

normAverx = vertx1 + vertx2 + vertx3 / 3;
normAvery = verty1 + verty2 + verty3 / 3;
normAverz = vertz1 + vertz2 + vertz3 / 3;

distance = sqrt(normAverx * normAverx + normAvery * normAvery + normAverz * normAverz);

normdx = normAverx / distance;
normdy = normAvery / distance;
normdz = normAverz / distance;

glNormal3f(normdx, normdy, normdz);
glVertex3f( vertx1, verty1, vertz1);
glVertex3f( vertx2, verty2, vertz2);
glVertex3f( vertx3, verty3, vertz3);
}


Thanks,
Iceman

inio
2002.07.23, 08:31 PM
That won't do what you want. Averaging the vertex coordinates does not give you a normal vector. If you need a version that takes scalar arguments, heres my code with scalar arguments:


void DrawTri(float vertx1, float verty1, float vertz1,
float vertx2, float verty2, float vertz2,
float vertx3, float verty3, float vertz3) {
float p1[3], p2[3], p3[3], normal[3];

p1[0]=vertx1; p1[1]=verty1; p1[2]=vertz1;
p2[0]=vertx2; p2[1]=verty2; p2[2]=vertz2;
p3[0]=vertx3; p3[1]=verty3; p3[2]=vertz3;

CalcFaceNorm(p1, p2, p3, normal);
glNormal3fv(normal);
glVertex3fv(p1);
glVertex3fv(p2);
glVertex3fv(p3);
}

use the CalcFaceNorm I posted above.

Iceman
2002.07.26, 02:48 PM
Wow that looks a lot smoother. Thanks :D .

Iceman