C++ STL Map for vertex normals. Help?

Started by
0 comments, last by SiCrane 16 years, 8 months ago
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();
		}
}



Advertisement
Cross post. Closed.

This topic is closed to new replies.

Advertisement