smoothing normals

Started by
2 comments, last by Nanoha 7 years, 10 months ago
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);
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.....

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).

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

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.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

This topic is closed to new replies.

Advertisement