opengl normal averageing
Im looking for some normal averaging algorithims so i can do smooth shadeing correctly.
The basic one is for each vertex to add all the normal vectors of the surrounding faces and then normalise it.
First off im a little unsure on how to weight it. Whats a good weighting formula?
Also it seems to be very slow and my athlon 750 dies if i try to do normal averageing on a large model. Any fast algorithims for this?
Cheers for any help/web links
adam
hamfdeath@yahoo.com
But you can calculate normals only once. Also you can save your model to file with averaged normals.
i assume you want a one-time normal calculation of your model.
well, just find all adjacent faces around a vertex, calculate their normals, add them up, and normalize the vector you get.
i have been doing this for a 20000 triangle landscape for testing purposes, and it takes about 5-10secs on my athlon 700.
and my algorithm is REALLY lame, i am sure you can do a lot better if you think about it some time
rid
well, just find all adjacent faces around a vertex, calculate their normals, add them up, and normalize the vector you get.
i have been doing this for a 20000 triangle landscape for testing purposes, and it takes about 5-10secs on my athlon 700.
and my algorithm is REALLY lame, i am sure you can do a lot better if you think about it some time
rid
Well, i'll answer you question: Heres the code.
I hope this helps.
P.S. It probably is slow
Edited by - Ferrit on October 18, 2000 2:39:56 PM
//usage: float *Normals = CalcVertexNormals(Array containing the models vertices, Number of vertices, Array of indexes to all triangles)float* CalcVertexNormals(float *fVertices,unsigned int num_verts,unsigned int *uiTriList, unsigned int num_tri_list){ int total=0; float *fVertNorms = (float*)malloc((sizeof(float))*num_verts*3); for(unsigned int VertexNum=0;VertexNum<num_verts;VertexNum++) { unsigned int tri = 0; //tri represent no. of shared triangles in a vertex unsigned int *triangles = (unsigned int*)malloc(sizeof(unsigned int)*3*6); //Allocate memory for 6 tri's, inc. x,y,z. Triangles is //an array [6][3] to hold 6 (max. number of triangles //sharing a vertex) triangles // for(unsigned int ctr=0;ctr<num_tri_list;ctr++) { if((uiTriList[(ctr*3)] == VertexNum) || (uiTriList[(ctr*3)+1] == VertexNum) || (uiTriList[(ctr*3)+2] == VertexNum))//"If Triangle ctr's x,y or z index is equal to the current vertex (VertexNum) then store it//in triangles array, and increase tri by one" { triangles[(tri*3)] = uiTriList[(ctr*3)]; triangles[(tri*3)+1] = uiTriList[(ctr*3)+1]; triangles[(tri*3)+2] = uiTriList[(ctr*3)+2]; tri++; } }//We now have all the triangles sharing the current vertex in the triangles array float NormalBuffer[3]; NormalBuffer[0] = 0; NormalBuffer[1] = 0; NormalBuffer[2] = 0; for(unsigned int ctr=0;ctr<tri;ctr++) { float VectorIn[3][3]; float NormalOut[3]; int temp; temp = triangles[(ctr*3)]; //Triangle vertex A VectorIn[0][0] = fVertices[(temp*3)]; //A's x component VectorIn[0][1] = fVertices[(temp*3)+1]; //A's y component VectorIn[0][2] = fVertices[(temp*3)+2]; //A's z component temp = triangles[(ctr*3)+1]; //Triangle Vertex B VectorIn[1][0] = fVertices[(temp*3)]; //etc. VectorIn[1][1] = fVertices[(temp*3)+1]; VectorIn[1][2] = fVertices[(temp*3)+2]; temp = triangles[(ctr*3)+2]; //Triangle Vertex C VectorIn[2][0] = fVertices[(temp*3)]; VectorIn[2][1] = fVertices[(temp*3)+1]; VectorIn[2][2] = fVertices[(temp*3)+2]; calcNormal(VectorIn,NormalOut,FALSE); NormalBuffer[0] += NormalOut[0]; //Add to normal buffer NormalBuffer[1] += NormalOut[1]; NormalBuffer[2] += NormalOut[2];//To find a vertex normal, we average the face normals of the triangles which share that vertex.//Hence we must put all the normal info into a buffer, and divide by no. of triangles } NormalBuffer[0] = (NormalBuffer[0]/tri); NormalBuffer[1] = (NormalBuffer[1]/tri); NormalBuffer[2] = (NormalBuffer[2]/tri); //Above code has averaged the normal. We do this BEFORE reducing it to unit ReduceToUnit(NormalBuffer); fVertNorms[(VertexNum*3)] = NormalBuffer[0]; fVertNorms[(VertexNum*3)+1] = NormalBuffer[1]; fVertNorms[(VertexNum*3)+2] = NormalBuffer[2]; //Vertex no. (VertexNUm) has now got the averaged, unit-length normal. Wahey! } return fVertNorms;}void ReduceToUnit(float vector[3]){ float length; length = (float)sqrt((vector[0]*vector[0]) + (vector[1]*vector[1]) + (vector[2]*vector[2])); if(length == 0.0f) length = 1.0f; vector[0] /= length; vector[1] /= length; vector[2] /= length;}void calcNormal(float v[3][3], float out[3], unsigned int Reduce){ float v1[3],v2[3]; static const int x = 0; static const int y = 1; static const int z = 2; v1[x] = v[0][x] - v[1][x]; v1[y] = v[0][y] - v[1][y]; v1[z] = v[0][z] - v[1][z]; v2[x] = v[1][x] - v[2][x]; v2[y] = v[1][y] - v[2][y]; v2[z] = v[1][z] - v[2][z]; out[x] = v1[y]*v2[z] - v1[z]*v2[y]; out[y] = v1[z]*v2[x] - v1[x]*v2[z]; out[z] = v1[x]*v2[y] - v1[y]*v2[x]; if(Reduce == TRUE) { ReduceToUnit(out); }}
I hope this helps.
P.S. It probably is slow
Edited by - Ferrit on October 18, 2000 2:39:56 PM
a more correct smooth would be to do like the red book saiz and average the normals depending on the faces angles
http://members.xoom.com/myBollux
http://members.xoom.com/myBollux
Ferrit, thats the exact algo im useing (well its in c++ not c!) but if the model has 50000 triangles and 20000 vertexs it does take a while to do it.
Yeah the red book says weight it my angles but im a little unsure what that means. Im asuming you only do a average if the dot product is greater than the cosine of a pre-defined angle (say 90) or something like that.
So im looking for that weight function and a better way of doing it. Finding the list of triangles which each vertex is connected to is costly. Any better ways guys?
adam
Yeah the red book says weight it my angles but im a little unsure what that means. Im asuming you only do a average if the dot product is greater than the cosine of a pre-defined angle (say 90) or something like that.
So im looking for that weight function and a better way of doing it. Finding the list of triangles which each vertex is connected to is costly. Any better ways guys?
adam
To be honest, seeing as the calculation sin''t at runtime, speed
shouldn''t really be such a problem
The tin-foil lining in my baseball cap stops the government reading my thoughts. ok? OK??
shouldn''t really be such a problem
The tin-foil lining in my baseball cap stops the government reading my thoughts. ok? OK??
i dont know of any other ways except for checking against all the other tris in the model. do what i do precalculate the normals and include them in the model data
http://members.xoom.com/myBollux
http://members.xoom.com/myBollux
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement