Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Lionheartadi

Tips on how to calculate vertex normals that gives a nice smooth surface shading?

This topic is 5570 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

Hi I need some general help with vertex normal calculations. Well I have calculated vertex normal per triangle basis, in other words I have used one vertex normal to all of the vertexs on a triangle. But as is known this doesn''t give you a smooth shade across a surface. So I tried to calculate vertex normals that gives you a nice smooth shading surface, but I think I failed because the vertex normals are pointing way of the target. I used the dot product to get the angle between two triangles calculated normal, but the problem is when you have a vertex shared with more than two tirangles. How do I get an average normal if the vertex is shared by more than two faces. I made some pre calculation on paper and thought of the code, but my way seems to weird and to slow to perform. So if there are any tips that someone can give me please help me. I should say that math isn''t my stongest area, but I like programming and especially gameprogramming so I want to learn these things. Thank you for any help possible.

Share this post


Link to post
Share on other sites
Advertisement
Calculate the normals for each face first.
Then, for each vertex, add all the normals for the faces that shares that vertex, and renormalize the result.

Share this post


Link to post
Share on other sites
First, you need to find all the faces that connect at a specific point. Then you can average the normals for the faces that touch that point. Really easy if you are using indices.

A problem with that is that sharp faces will be lit wrong. One solution is to check if the angle between two faces is beyond a certain threshold, and average them together only if the angle is less than a certain value (45 defrees for example would work well for most meshes).

Make sure you normalize your vertex normals.

Share this post


Link to post
Share on other sites
quote:
Original post by tok_junior
Calculate the normals for each face first.
Then, for each vertex, add all the normals for the faces that shares that vertex, and renormalize the result.


Uh a little confused a different approach than I planned, or I just understand in the wrong way. Uh I think I need to loonk into this a little more. Thx I try what you suggested.

Share this post


Link to post
Share on other sites
quote:
Original post by drslush
First, you need to find all the faces that connect at a specific point. Then you can average the normals for the faces that touch that point. Really easy if you are using indices.

A problem with that is that sharp faces will be lit wrong. One solution is to check if the angle between two faces is beyond a certain threshold, and average them together only if the angle is less than a certain value (45 defrees for example would work well for most meshes).

Make sure you normalize your vertex normals.


Hmm I think I understand where you are going. I thought one of a similar approach, but my way was to complicated and as I said before weird. Thx I'll try

Something like this?
What I do below is go through every face in an object and calculate a normal for every vertex in a face. Then I add together the vertex normals for every shared face. Uh well the code may be much simpler to understand than my explanations.



void CalculateVertexNormals()
{

int x = 0;
vertex zeroVertex;
zeroVertex.x = 0;
zeroVertex.y = 0;
zeroVertex.z = 0;
zeroVertex.count = 0;
vertex tempVector;
std::vector<vertex>::iterator pTempNormalVertex;
std::vector<vertex>::iterator pTempVertex1;
std::vector<vertex>::iterator pTempVertex2;
std::vector<vertex>::iterator pTempVertex3;
int tempVal = 0;

vertex temp;

// Go through every object in the model

for(std::vector<OBJ_DATA>::iterator j = ModelA.MODEL_DATA.begin(); j != ModelA.MODEL_DATA.end(); j++)
{
for(x = 0; x < j->VERTEX_NUM; x++)
{
zeroVertex.VertexID = x;
j->OBJVERTEXNORMAL_LIST.push_back(zeroVertex);
}

// Go through every face in this objcet and calculate normals to vertex values

for(std::vector<face>::iterator FACE = j->OBJFACE_LIST.begin(); FACE != j->OBJFACE_LIST.end(); FACE++)
{
// Get the vertex values of this face

pTempVertex1 = (j->OBJVERTEX_LIST.begin()+FACE->a);
pTempVertex2 = (j->OBJVERTEX_LIST.begin()+FACE->b);
pTempVertex3 = (j->OBJVERTEX_LIST.begin()+FACE->c);

// Calculate the curent faces vertexs crossproducts

//---------------------------------------------------------

pTempNormalVertex = (j->OBJVERTEXNORMAL_LIST.begin()+FACE->a); // Get a pointer to this vertex from the vertex normal list


tempVector = CrossProduct(*pTempVertex1, *pTempVertex2, *pTempVertex3); // Do the cross product


tempVector.x *= -1;
tempVector.y *= -1;
tempVector.z *= -1;
//temp = tempVector;

//NormalizeVector(temp);

pTempNormalVertex->x += tempVector.x;
pTempNormalVertex->y += tempVector.y;
pTempNormalVertex->z += tempVector.z;

pTempNormalVertex->count++;

pTempNormalVertex = (j->OBJVERTEXNORMAL_LIST.begin()+FACE->b); // Get a pointer to this vertex from the vertex normal list


tempVector = CrossProduct(*pTempVertex2, *pTempVertex1, *pTempVertex3); // Do the cross product


//temp = tempVector;

//NormalizeVector(temp);


pTempNormalVertex->x += tempVector.x;
pTempNormalVertex->y += tempVector.y;
pTempNormalVertex->z += tempVector.z;
pTempNormalVertex->count++;

pTempNormalVertex = (j->OBJVERTEXNORMAL_LIST.begin()+FACE->c); // Get a pointer to this vertex from the vertex normal list


tempVector = CrossProduct(*pTempVertex3, *pTempVertex2, *pTempVertex1); // Do the cross product


//temp = tempVector;

//NormalizeVector(temp);


pTempNormalVertex->x += tempVector.x;
pTempNormalVertex->y += tempVector.y;
pTempNormalVertex->z += tempVector.z;
pTempNormalVertex->count++;

}

} // END OF CROSS PRODUCT CALCULATIONS


for(std::vector<OBJ_DATA>::iterator OBJ = ModelA.MODEL_DATA.begin(); OBJ != ModelA.MODEL_DATA.end(); OBJ++)
{
for(x = 0; x < OBJ->VERTEX_NUM; x++)
{
pTempNormalVertex = (OBJ->OBJVERTEXNORMAL_LIST.begin()+x);
pTempNormalVertex->x /= pTempNormalVertex->count;
pTempNormalVertex->y /= pTempNormalVertex->count;
pTempNormalVertex->z /= pTempNormalVertex->count;
NormalizeVector(*pTempNormalVertex);

}
}


}



[edited by - LionheartAdi on June 16, 2003 3:57:23 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
this has been asked too many times in the past. USE THE @#%!ing SEARCH BUTTON!

Share this post


Link to post
Share on other sites
Looks like you have the right idea. One thing you might want to consider is creating a class for your vectors and overload operators. Your code will look much cleaner and easier to read.

Share this post


Link to post
Share on other sites
AP, how many questions are ever asked on this forum that haven''t been asked before? Seriously...

Share this post


Link to post
Share on other sites
quote:
Original post by drslush
Looks like you have the right idea. One thing you might want to consider is creating a class for your vectors and overload operators. Your code will look much cleaner and easier to read.



Great thanks drslush. The vertex component is a structure values which hold just X,Y,Z and it''s used to import vertex data from ASE files. I wanted to keep the code amount low(lazy me). Then I convert the ASCI data to an another file format in to binary form. In other words lazt , but thanks again for the help. Now I can continue my code.

Share this post


Link to post
Share on other sites
Making a class and overloading operators would probably reduce the amount of code, plus it wouldn''t cost any speed, since you can inline them.

Glad to hear you got it working.

Share this post


Link to post
Share on other sites

  • 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!