Jump to content
  • Advertisement
Sign in to follow this  
mazahist

smoothing normals

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

How to smooth normals?
When I calculate the normal, they become flat.
 
    
var figure = {
     vertex: [1, 1, -1, -1, 0, 0, -1, 1, -1, 1, 0, 1, 1, 0, 0, -1, 0, 1],
     index: [0, 1, 2, 3, 1, 4, 0, 4, 1, 3, 5, 1]
    };
    
    function calcNormal(vertex, index) {
     var vertNormal = [];
     var surfNormal = [];
     for (var i = 0; i < index.length; i += 3) {
     var v0_v = [vertex[index[i + 0] * 3 + 0], vertex[index[i + 0] * 3 + 1], vertex[index[i + 0] * 3 + 2]];
     var v1_v = [vertex[index[i + 1] * 3 + 0], vertex[index[i + 1] * 3 + 1], vertex[index[i + 1] * 3 + 2]];
     var v2_v = [vertex[index[i + 2] * 3 + 0], vertex[index[i + 2] * 3 + 1], vertex[index[i + 2] * 3 + 2]];
     var p = Vector3.minus(v1_v, v0_v);
     var q = Vector3.minus(v2_v, v0_v);
     var n = Vector3.cross(p, q);
     //n = Vector3.normalize(n);
     surfNormal.push(-n[0]);
     surfNormal.push(-n[1]);
     surfNormal.push(-n[2]);
    
     vertNormal[index[i + 0] * 3 + 0] = -n[0]; vertNormal[index[i + 0] * 3 + 1] = -n[1]; vertNormal[index[i + 0] * 3 + 2] = -n[2];
     vertNormal[index[i + 1] * 3 + 0] = -n[0]; vertNormal[index[i + 1] * 3 + 1] = -n[1]; vertNormal[index[i + 1] * 3 + 2] = -n[2];
     vertNormal[index[i + 2] * 3 + 0] = -n[0]; vertNormal[index[i + 2] * 3 + 1] = -n[1]; vertNormal[index[i + 2] * 3 + 2] = -n[2];
     };
     //... calculation smooth normals
     //...
     //createBuffer(vertNormal)
    }
    calcNormal(figure.vertex, figure.index);

Share this post


Link to post
Share on other sites
Advertisement

I'm not sure, but I think you are on the right track. See if this helps:

A vertex that is shared by more than one triangle must average the normal for that vertex of each triangle. It appears you are only using info from one face to calculate the normal.....

Share this post


Link to post
Share on other sites

1.) If this is just a normal 3D model that is static, why not just have 3DsMax/Maya/Blender etc calculate this for you and then export.

2.)
    surfNormal.push(-n[0]);

 

If your normals are pointing in the wrong direction, then you did the wrong cross product. Are you sure all your triangles are even wound probably since you hard coded them?

 

3.) Your algorithm looks completely wrong. You are looping through every face (which shares vertices, and computing the normal over and over again for the same vertex). It looks like then the last face to touch that vertex assigns its face normal to that vertex.

 

You need to create normals for all the faces in one loop. Then a second loop afterwards you need to do  vertexNormal[index[ blah ] += triangles normal. This gives you all the normals added.  Then in a 3rd loop, you need to divide the normal by how many faces the vertex is connected to (averaging the normal).

Share this post


Link to post
Share on other sites

It's a bit hard to work out what's going on with that, it might be worth trying to make the code a bit easier to follow. To calculate smoothed normals you need to do 2 passes.
First work out face normals, I see you already do that.
Second part depends how you want to weigh your normal contributions. For example if you have a tiny face joined to a huge face shouldn't the huge face contribute more than the smaller face? If you don't take that into account your normals will look off. For simplicity sake though:
Initialise all the vertex normals to 0
Go through each vertex
    For every attached face add the face normal onto the vertex normal
    normalize the normal
 
If you want larger faces to contribute more you could do:
 
for each vertex:
   normal = Vector(0, 0, 0)
   for each attached face
      normal += face.normal*face.area
   normal.Normalize();
 
That way larger faces contribute more and you won't get weird looking lighting when small faces attach to larger ones at differing angles.
 

You need to create normals for all the faces in one loop. Then a second loop afterwards you need to do  vertexNormal[index[ blah ] += triangles normal. This gives you all the normals added.  Then in a 3rd loop, you need to divide the normal by how many faces the vertex is connected to (averaging the normal).


Just a comment on the third pass, you don't need to know how many faces there are since normalizing will take care of that no matter the number of faces.

Edited by Nanoha

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!