Problem with Normals[solved]

Started by
3 comments, last by Yhonatan 15 years, 9 months ago
Hey all, I'm currently working on a 3D tank game and I have a serious problem with the normals. I'm trying to achieve smooth shading (I think that's the way this is called) by summing up all the normals of the faces of some vertex and then avaraging them. Firstly, It didnt work well on the ground, there arent many changes (when changing the position of a light source) but when the light source is below a certrain point(Y axis), that place (the place above it) is blacked out. so It looks like it got some affect on the ground, and i'm not sure what should I do. here are two screen shots the red cross is the place of the light source, and by looking at the tank you can see that this is wrong: http://img89.imageshack.us/img89/4773/normals2nz1.jpg http://img359.imageshack.us/img359/8967/normals1kn9.jpg before explaining what exacly I'm doing this is how i calculate each normal:



void VectorOffset (point *pIn, point *pOffset, point *pOut)
{
   pOut->x = pIn->x - pOffset->x;
   pOut->y = pIn->y - pOffset->y;
   pOut->z = pIn->z - pOffset->z;
}

// Compute the cross product a X b into pOut
void VectorGetNormal (point *a, point *b, point *pOut)
{
   pOut->x = a->y * b->z - a->z * b->y;
   pOut->y = a->z * b->x - a->x * b->z;
   pOut->z = a->x * b->y - a->y * b->x;
}



// Compute p1,p2,p3 face normal into pOut
bool ComputeFaceNormal (point *p1, point *p2, point *p3, point *pOut)
{
   // Uses p2 as a new origin for p1,p3
   point a;
   VectorOffset(p3, p2, &a);
   point b;
   VectorOffset(p1, p2, &b);
   // Compute the cross product a X b to get the face normal
   point pn;
   VectorGetNormal(&a, &b, &pn);

   pOut->x = pn.x;
   pOut->y = pn.y;
   pOut->z = pn.z;
return true;
}







What I'm doing is this: first I calculate all the normals for a certain vertex and I save it with a certain class i've made. After all faces are loaded, i'm chaning all the normals so they'll suit up. (NFV is an object of that class) Numosh is the place of that Vertex's normal (assuming there are 3 vertices, if i want the normal for the vertex in the place 1 Numosh=1)


for (vector <Mesh>::iterator JHJ=Meshes.begin();JHJ!=Meshes.end();JHJ++)
{
	NumTria=0;
	for (vector <Triangle>::iterator Tria = (*JHJ).Triangles.begin();Tria!=(*JHJ).Triangles.end();Tria++)
	{
		for (int i=0;i<3;i++)
		{
			int Numosh = int((*Tria).Normal.x);
	
			point OldVector;
			OldVector.x = float(NFV[Numosh].SumOfAllNormals.x/float(NFV[Numosh].numOfNormals));
			OldVector.y = float(NFV[Numosh].SumOfAllNormals.y/float(NFV[Numosh].numOfNormals));
			OldVector.z = float(NFV[Numosh].SumOfAllNormals.z/float(NFV[Numosh].numOfNormals));
			point NewN, NewN2;
			
		    NewN.x=OldVector.x;
			NewN.y=OldVector.y;
			NewN.z=OldVector.z;
			Meshes[NumMush].Triangles[NumTria].Normal.x=NewN.x;
			Meshes[NumMush].Triangles[NumTria].Normal.y=NewN.y;
			Meshes[NumMush].Triangles[NumTria].Normal.z=NewN.z;
		
		}
		NumTria++;
	}
	NumMush++;
}






Any idea why is this happening this way? Thanks in advance [Edited by - Yhonatan on July 22, 2008 5:00:28 PM]
Advertisement
Your normal vectors don't appear to ever be normalized. That could be the problem since OpenGL assumes your normal vectors are normalized.

I also don't see any logic that's accounting for winding (i.e. are your points clockwise or counter-clockwise), though that could be happening naturally assuming a consistent mesh format. Otherwise, you need to guarantee that the normal you generate is pointing "outwards" on the model. Remember that each poly has 2 normals, one facing inside, the other outside.

-me
Quote:Original post by Palidine
Your normal vectors don't appear to ever be normalized. That could be the problem since OpenGL assumes your normal vectors are normalized.

I also don't see any logic that's guaranteeing that your accounting for winding, though that could be happening naturally. Basically you need to guarantee that the normal you generate is pointing "outwards" on the model. Remember that each poly has 2 normals, one facing inside, the other outside.

-me


Hey Palidine,
Thanks for your post.
Every time that I've tried to normalize those vectors it turned out that that they always have "light" upon them, and by changing the light position it doesnt change.
I was trying to normalize them this way:

bool VectorNormalize (point *pIn, point *pOut){   GLfloat len = (GLfloat)(sqrt(sqrt(pIn->x) + sqrt(pIn->y) + sqrt(pIn->z)));   if (len)   {      pOut->x = pIn->x / len;      pOut->y = pIn->y / len;      pOut->z = pIn->z / len;      return true;   }   return false;}




How can I garuntee that the normal is pointing out of the model and not inside?


Thanks in advance

That's the wrong math for vector normalization:
http://www.fundza.com/vectors/normalize/index.html

Cross-product is right-hand rule (http://en.wikipedia.org/wiki/Right-hand_rule). Models are typically authored in a specific winding (either clockwise or counter-clockwise). So depending on the winding, you cross either AB x BC or CB x BA to get the vector pointing in/out. A,B,C are the vertices as defined by the order in which they appear in your indices list.

You should add some debug drawing code to draw your actual normal vectors at each vertex to assure yourself that they are being calculated correctly. Once you have that running it's simple trial and error to get the normals correct.

-me
Thanks a lot!!!!! Now it's working like it should have

This topic is closed to new replies.

Advertisement