Jump to content
  • Advertisement
Sign in to follow this  
c_olin

Problem calculating vertex normals...

This topic is 3936 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

When I calculate and use my mesh's vertex normals my mesh gets rendered with flat shading. Same exact results as if I use face normals. I'm using the CML library for my vector structures and math. The problem might be in how I'm using CML so I have also posted on the CML forums. But I was wondering if you guys could give it a quick look and see if I'm making a stupid mistake somewhere... Here is my code for calculating both face and vertex normals:
void Mesh::computeNormals() {
	Vector3f vector1 = Vector3f(0, 0, 0);
	Vector3f vector2 = Vector3f(0, 0, 0);
	Vector3f sum     = Vector3f(0, 0, 0);
	int shared       = 0;

	for(int i = 0; i < numSubMeshes; i++) {
		// Face Normals.
		for(int j = 0; j < subMeshes.numTriangles; j++) {
			vector1 = subMeshes.vertices[subMeshes.triangles[j].vertexIndices[2]].pos - subMeshes.vertices[subMeshes.triangles[j].vertexIndices[0]].pos;
			vector2 = subMeshes.vertices[subMeshes.triangles[j].vertexIndices[1]].pos - subMeshes.vertices[subMeshes.triangles[j].vertexIndices[0]].pos;

			subMeshes.triangles[j].normal = cml::cross(vector2, vector1);
		}

		// Vertex Normals.
		shared = 0;
		sum.set(0, 0, 0);
		for(int j = 0; j < subMeshes.numVertices; j++) {
			for(int k = 0; k < subMeshes.numTriangles; k++) {
				if(subMeshes.triangles[k].vertexIndices[0] == j ||
				   subMeshes.triangles[k].vertexIndices[1] == j ||
				   subMeshes.triangles[k].vertexIndices[2] == j) {
					sum += subMeshes.triangles[k].normal;
					shared++;
				}
			}
			
			subMeshes.vertices[j].normal = sum/(float)shared;

			shared = 0;
			sum.set(0, 0, 0);			
		}

		// Normalize Both normals.
		for(int j = 0; j < subMeshes.numTriangles; j++) 
			subMeshes.triangles[j].normal.normalize();

		for(int j = 0; j < subMeshes.numVertices; j++) 
			subMeshes.vertices[j].normal.normalize();
	}
}

And here for rendering (OpenGL):
void Renderer::preRenderSubMesh(const SubMesh& subMesh) {
	glBegin(GL_TRIANGLES);
	for(int j = 0; j < subMesh.numTriangles; j++) {
		//glNormal3fv(subMesh.triangles[j].normal.data());				   
		for(int k = 0; k < 3; k++) {
			glNormal3fv(subMesh.vertices[subMesh.triangles[j].vertexIndices[k]].normal.data());				   
			glTexCoord2fv(subMesh.vertices[subMesh.triangles[j].vertexIndices[k]].uv.data());	
			glVertex3fv(subMesh.vertices[subMesh.triangles[j].vertexIndices[k]].pos.data());
		}
	}
	glEnd();
}

Share this post


Link to post
Share on other sites
Advertisement
It looks like you have the right idea. One thing I would try would be to normalize the triangle face normals before you use them to calculate the vertex normals.

Otherwise, your bug is not obvious to me. If you set the vertex normals to something obviously wrong (perhaps set them all to (0, 1, 0) or something) does it show up obviously wrong, or does it still render with flat shading? This could tell you if the bug is somewhere besides your normal calculation.

Share this post


Link to post
Share on other sites
Setting the vertex normals to (0, 1, 0) definitely makes a difference. It makes the entire object completely lit.

Yeah I've been looking over this code and trying everything for a couple days now. It's really stumping me.

Share this post


Link to post
Share on other sites
What if in computeNormals() you randomly all vertex normals to either (0 1 0) or (0 -1 0), chosen randomly. Do you get any smooth shading in that case, or does the shading look like it's on a per polygon basis (some light up, some completely dark, no smooth interpolation between)?

It seems really weird to me that you can still have flat shading when you are setting the normal on a per vertex basis in the draw function.

This may sound like a stupid question, but are you sure each submesh has more than one triangle in it? Vertices won't be able to see triangles in different submeshes.

Share this post


Link to post
Share on other sites
I am not certain if this is related to your problem, but I think the way you calculate your vertex normals is not fully correct.

From what I understand of your code a vertex normal is the sum of all the face normals holding the vertex.

But you may want to only consider face normals that are not collinear.

For example, let's consider a box. Each corner is connected to 3 sides, but since your are dealing with triangles, each side is composed of 2 faces. Now depending on how your box is constructed, for each of the 3 sides a corner is connected to, a side will either be 2 collinear faces or only 1.

Share this post


Link to post
Share on other sites
Hi,

Have you set your output to be gouraud shaded? Flat shading might be default setting on some hardware. Also, in theory it is possible that the triangles don't share any vertices for several reasons such as different vertex coordinates or differing smoothing groups. This would lead naturally to flat shaded output.



//you could use the following loop to calculate the tri normals, it does the
//same thing as yours, but in a more efficient manner

for(int i = 0; i < numSubMeshes; i++)
{
//calculate and normalize triangle normals here, although it could be integrated in the next loop too

for(int k = 0; k < subMeshes.numTriangles; k++)
{
for(int j = 0; j < 3; ++j)
{
int index = subMeshes.triangles[k].vertexIndices[j];

subMeshes.vertices[index].normal += subMeshes.triangles[k].normal;
}
}

//normalize vertex normals here

}





Best regards!

Share this post


Link to post
Share on other sites
Yes. I have "glShadeModel(GL_SMOOTH);" set. And I tried your code kuana, and it does the same thing. Flat shaded surface... This is getting really frustrating.

Share this post


Link to post
Share on other sites
New development...

I slapped some logger calls in the calculation function and here is a part of the output...


// First 2 faces...
0 : - Face[0] -0.033499 0.858511 -0.511701
0 : - Face[1] -0.155364 0.656539 -0.738118

// Vertices that are part of the first two faces...
0 : - Vertex[0] -0.033499 0.858511 -0.511701
0 : - Vertex[1] -0.033499 0.858511 -0.511701
0 : - Vertex[2] -0.033499 0.858511 -0.511701
0 : - Vertex[3] -0.155364 0.656539 -0.738118
0 : - Vertex[4] -0.155364 0.656539 -0.738118
0 : - Vertex[5] -0.155364 0.656539 -0.738118



Obviously you can see why I'm getting flat shading. The vertex normals are the exact same as the faces they are used by. But the question is... why does this happen?

I don't get it... does anyone else have any ideas?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!