Hello all,
Am having a small problem - right now I am exporting a large scene from 3ds into opengl using the .3ds format - and this does not contain any vertex normal information so i need to calculate it myself.
Before you see some code you should know my vertices (and vert normals) are organised into vector<Vector3f> where Vector3f is my own structure for a vertex. The verts are organised so that there are repeated vertex, i.e. verts 1,2,3 are for the first triangle, and 3,4,5 are for the second, but none, 1 or 2 of these vertices may in reality be the same as 1,2 or 3.
I started out using an extremely extremely time consuming method as below
void calculateSharedVerts(vector<Vector3f>& verts, vector<Vector3f>& vertNormals)
{
Vector3f temp;
//here I set the intial vertex normals to that of the face normal for the face they belong to.
for(int i=0; i< verts.size(); i+=3)
{
temp.calculateNormal_2(verts, verts[i+1], verts[i+2]);
vertNormals.push_back(temp);
vertNormals.push_back(temp);
vertNormals.push_back(temp);
}
//Now I loop through and whenever we find a shared vertex, we add the face normals from both
for(int i=0; i< verts.size(); i++)
{
for(int j=0; j< verts.size(); j++)
{
if(i!=j)
{
if(verts==verts[j])
{
vertNormals+= vertNormals[j];
}
}
}
}
//normalise the results
for(int i=0; i< vertNormals.size(); i++)
{
vertNormals.normalise();
}
}
The above worked entirely correctly, but because of the size of my scene, even just computing these normals once and writing to a file to be read later takes hours on end and so I searched for a better way of doing it.
I realised I could use the stl Map so that whenever I was addressing a shared vertex, I only needed to use that one value so no looping to find shared verts is required.
Because the other definition I use for Vector3f "less than" does not meet the requirements of "strict weak ordering" I define a new comparison function vect3fCompare to use.
Basically the normals are coming out far from correct and was hoping someone might be able to give me some insight into what I might be doing wrong here.
bool vect3fCompare(Vector3f p1, Vector3f p2) {
Vector3f zero(0,0,0);
//the below SHOULD satisfy strict weak ordering, which I read was is nessecery for this to work, defined by
//1) a<a is false
//2) equality given by (!(a<b) && !(b<a)) - i.e. less than can be used to determine equality
//3) If a<b and b<c, then a<c must be true.
if(p1.distance(zero) < p2.distance(zero))
return true;
return false;
}
void addNormals(vector<Vector3f>& verts, vector<Vector3f>& vertNormals) {
map<Vector3f, Vector3f, bool(*)(Vector3f, Vector3f)> myMap(vect3fCompare);
Vector3f temp;
//calculate the face normal, and set each vert to that face normal.
for(int i=0; i< verts.size(); i+=3)
{
temp.calculateNormal_2(verts, verts[i+1], verts[i+2]);
vertNormals.push_back(temp);
vertNormals.push_back(temp);
vertNormals.push_back(temp);
}
Vector3f zero(0,0,0);
//fill it up with 0s.
for(int i=0; i< verts.size(); i++)
myMap[verts] = zero;
//for every shared vertex, myMap will now collect all the proper face normals together to make individual vert normals.
for(int i=0; i< verts.size(); i++)
{
myMap[verts] += vertNormals;
}
//now we loop back through, setting each vertNormal to the value calculated in the map.
for(int i=0; i< verts.size(); i++)
vertNormals = myMap[verts]; //addition of all verts same as verts
//and finally normalise
for(int i=0; i< vertNormals.size(); i++)
{
vertNormals.normalise();
}
}