Calculating face normals

I’ve written programs that calculate face normals for triangles before, but I’m stuck!

  
void computeFaceNormals( void ) {
		cVector3 v1, v2, faceNormal;

		for(int i = 0; i < m_numTriangles; i++) {
			v1 = m_vertices[m_triangles[i].indices[2]].point - m_vertices[m_triangles[i].indices[0]].point;
			v2 = m_vertices[m_triangles[i].indices[2]].point - m_vertices[m_triangles[i].indices[1]].point;
			faceNormal = cross(v1, v2);
			m_triangles[i].normal = normalize(faceNormal);
		}
	}

I’m drawing my polygons clockwise, but when i render it with lights, the normals are obviously screwed up!

whats the problem?

Here’s how I did it:

void CTriangle::ComputeNormal()
{
CVertex v1 = vertices[0]->Difference(vertices[2]);
CVertex v2 = vertices[2]->Difference(vertices[1]);

CVertex norm = v1.CrossProduct(v2);
norm.Normalize();

faceNormal = norm;

}

where vertices[0] - [2] reference the three vertices, and faceNomal holds the resulting normal. Difference is just subtracting one point from another and returning the result.

This code will work for n-gons, providing they are planar.

But if you want smooth lighting, you’ll need to compute the normals of each vertex…

Thanks for the reply!

But Thats the same thing that I have, here is my class:

//*---obj.h---*//

class obj { //Mesh file exported from Lightwave
public:
	int		   m_tid; //Texture ID
	int		   m_numVertices;
	int		   m_numTriangles;
	cVertex   *m_vertices;
	cTriangle *m_triangles;

	void computeFaceNormals( void ) { 
		cVector3 v1, v2, faceNormal;

		for(int i = 0; i < m_numTriangles; i++) {
			v1 = m_vertices[m_triangles[i].indices[0]].point - m_vertices[m_triangles[i].indices[2]].point;
			v2 = m_vertices[m_triangles[i].indices[2]].point - m_vertices[m_triangles[i].indices[1]].point;
			faceNormal = cross(v1, v2);
			m_triangles[i].normal = normalize(faceNormal);
		}
	}

	void loadObj(char* filename) {
		char tga[25];
		char blank[10];

		console.newCMsg("Loading mesh: %s...", filename);

		ifstream ifs(filename);

		ifs >> tga;

		m_tid = texCount;
		loadTexture(tga, false, 0);

		ifs >> blank;
		ifs >> m_numVertices;
		ifs >> blank;
		ifs >> m_numTriangles;

		m_vertices  = new cVertex[m_numVertices];
		m_triangles = new cTriangle[m_numTriangles];
		
		for(int i = 0; i < m_numVertices; i++) { //Read Vertices
			ifs >> blank;
			ifs >> m_vertices[i].point.x;
			ifs >> m_vertices[i].point.y;
			ifs >> m_vertices[i].point.z;
		}

		for(i = 0; i < m_numTriangles; i++) { //Read Triangles
			ifs >> blank;
			ifs >> m_triangles[i].u[0];
			ifs >> m_triangles[i].v[0];
			ifs >> blank;
			ifs >> m_triangles[i].u[1];
			ifs >> m_triangles[i].v[1];
			ifs >> blank;
			ifs >> m_triangles[i].u[2];
			ifs >> m_triangles[i].v[2];

			ifs >> blank;
			ifs >> m_triangles[i].indices[0];
			ifs >> blank;
			ifs >> m_triangles[i].indices[1];
			ifs >> blank;
			ifs >> m_triangles[i].indices[2];
			ifs >> blank;
		}

		computeFaceNormals();

		console.newCMsg("done");
	}

	void renderObj(float x, float y, float z, bool vertexNormals) { //Render mesh
		glEnable(GL_TEXTURE_2D);

		glTranslatef(x, y, z);

		glBindTexture(GL_TEXTURE_2D, texture[m_tid].texID);

		if(vertexNormals) {
			glBegin(GL_TRIANGLES);
			for(int i = 0; i < m_numTriangles; i++) {
				glNormal3f(m_vertices[m_triangles[i].indices[0]-1].normal.x, m_vertices[m_triangles[i].indices[0]-1].normal.y, m_vertices[m_triangles[i].indices[0]-1].normal.z); glTexCoord2f(m_triangles[i].u[2], m_triangles[i].v[2]); glVertex3f(m_vertices[m_triangles[i].indices[0]-1].point.x, m_vertices[m_triangles[i].indices[0]-1].point.y, m_vertices[m_triangles[i].indices[0]-1].point.z);
				glNormal3f(m_vertices[m_triangles[i].indices[0]-1].normal.x, m_vertices[m_triangles[i].indices[0]-1].normal.y, m_vertices[m_triangles[i].indices[0]-1].normal.z); glTexCoord2f(m_triangles[i].u[1], m_triangles[i].v[1]); glVertex3f(m_vertices[m_triangles[i].indices[1]-1].point.x, m_vertices[m_triangles[i].indices[1]-1].point.y, m_vertices[m_triangles[i].indices[1]-1].point.z);
				glNormal3f(m_vertices[m_triangles[i].indices[0]-1].normal.x, m_vertices[m_triangles[i].indices[0]-1].normal.y, m_vertices[m_triangles[i].indices[0]-1].normal.z); glTexCoord2f(m_triangles[i].u[0], m_triangles[i].v[0]); glVertex3f(m_vertices[m_triangles[i].indices[2]-1].point.x, m_vertices[m_triangles[i].indices[2]-1].point.y, m_vertices[m_triangles[i].indices[2]-1].point.z);
			}
			glEnd();
		}
		else {
			glBegin(GL_TRIANGLES);
			for(int i = 0; i < m_numTriangles; i++) {
				glNormal3f(m_triangles[i].normal.x, m_triangles[i].normal.y, m_triangles[i].normal.z); 
				glTexCoord2f(m_triangles[i].u[2], m_triangles[i].v[2]); glVertex3f(m_vertices[m_triangles[i].indices[0]-1].point.x, m_vertices[m_triangles[i].indices[0]-1].point.y, m_vertices[m_triangles[i].indices[0]-1].point.z);
				glTexCoord2f(m_triangles[i].u[1], m_triangles[i].v[1]); glVertex3f(m_vertices[m_triangles[i].indices[1]-1].point.x, m_vertices[m_triangles[i].indices[1]-1].point.y, m_vertices[m_triangles[i].indices[1]-1].point.z);
				glTexCoord2f(m_triangles[i].u[0], m_triangles[i].v[0]); glVertex3f(m_vertices[m_triangles[i].indices[2]-1].point.x, m_vertices[m_triangles[i].indices[2]-1].point.y, m_vertices[m_triangles[i].indices[2]-1].point.z);
			}
			glEnd();
		}

		glTranslatef(-x, -y, -z);
	}
};

My normals aren’t calculated correctly! It loks like it in the code, but when I draw the object with lighting it looks way screwed up…

What can possibly be wrong?!

Hard to say.
How are you normalizing you’re, er, normals?

For flat shading, you only need to call glNormal() once per poly,

Have you set glEnable(GL_NORMALIZE)?

Have you set up the camera correctly? The default settings are rather poor.

Also, you don’t need to reverse the transform to rest the model matrix. Just wrap you’re code in glPushMatrix and glPopMatrix calls which is much safer and cleaner.

Have you set rendermode to GL_FLAT?

I tried posting the code I use but I get some error about parenthesis tags not be allowed fot html tags. I’m not using HTML!

And is it just my machine or is the message field really small?

if you looks closly in my code its set up to render vertex normals or poly normals… so i am calling glNormal once like you said…

I have tried everything that you posted, but I got nothing, Ill post my math functions, maybe they are wrong:

//*---3dmath.h---*//

struct cVector3 { //Structure for a 3d vector
public:
	float x, y, z;	
	
	cVector3() {}

	cVector3(float X, float Y, float Z) { 
		x = X; y = Y; z = Z;
	}

	cVector3 operator+(cVector3 vVector) {
		return cVector3(vVector.x + x, vVector.y + y, vVector.z + z);
	}

	cVector3 operator-(cVector3 vVector) {
		return cVector3(x - vVector.x, y - vVector.y, z - vVector.z);
	}
	
	cVector3 operator*(float num) {
		return cVector3(x * num, y * num, z * num);
	}

	cVector3 operator/(float num) {
		return cVector3(x / num, y / num, z / num);
	}	
};

cVector3 cross(cVector3 vVector1, cVector3 vVector2) {  //Cross Product
	cVector3 vNormal;

	vNormal.x = ((vVector1.y * vVector2.z) - (vVector1.z * vVector2.y));
	vNormal.y = ((vVector1.z * vVector2.x) - (vVector1.x * vVector2.z));
	vNormal.z = ((vVector1.x * vVector2.y) - (vVector1.y * vVector2.x));

	return vNormal;										 
}

float magnitude(cVector3 vNormal) { //Get magnitude of normal
	return (float)sqrt( (vNormal.x * vNormal.x) + 
						(vNormal.y * vNormal.y) + 
						(vNormal.z * vNormal.z) );
}

cVector3 normalize(cVector3 vVector) { //Normalize a vector
	float magnitude1 = magnitude(vVector);				
	
	vVector = vVector / magnitude1;		

	return vVector;										
}

struct cVertex { //Struct for vertex
	cVector3 point;
	cVector3 normal;
};

struct cTriangle { //Struct for Triangle
	int      indices[3];
	float    u[3];
	float    v[3];
	cVector3 normal;
};

I checked all of that too! and found nothing wrong!