Пример #1
0
bool Mesh3D::loadMesh(const std::string &filename, int n) {
  OBJFileReader reader;
  reader.load(filename.c_str(),n);
  vertices = reader.getVertices();
  normals = reader.getNormals();
  indices = reader.getIndices();
  uvs = reader.getUvs();
  fuv = reader.getFloatUvs();
  fvertices = reader.getFloatVectices();
  uvIndices = reader.getUvIndices();
  uvsOriginal = reader.getUvsOriginal();

  // Do this for certain objects with bitangents and tangets
  //computeTangentBitangent(mesh);
}
Пример #2
0
void main(int argc, char *argv[])
{
	// Read in the obj file
	Solid mesh;
	OBJFileReader of;
	std::ifstream in(argv[1]);
	string filename = argv[1];
	string::size_type npos = filename.find(".obj");
	string s = ".m";
	filename.replace(npos, 4,s);
	of.readToSolid(&mesh, in);

	/******************* Put you subdivision processing here *********************/


	//1. highlights all edges  zz begin 2013-02-21 16:11:20

	SolidEdgeIterator eiter(&mesh);
	for(; !eiter.end(); ++eiter)
	{
		Edge *e = *eiter;
		e->string ()=std::string("sharp");
	}
	//end zz 2013Äê2ÔÂ21ÈÕ16:18:10

	//2. establish the adjacency list [2/21/2013 Zhe]
	list<int> Graphface[Num];
	SolidFaceIterator fiter(&mesh);
	for(; !fiter.end(); ++fiter)
	{
		Face *f = *fiter;
		FaceHalfedgeIterator hfiter(f);
		HalfEdge *hf = NULL;
		for (;!hfiter.end();++hfiter)
		{		
			hf = *hfiter;
			hf = hf->he_sym();
			Graphface[f->id()].push_back(hf->face()->id());
		}
	}
	//  [2/21/2013 Zhe]

	/************************************************************************/
	/* // 3.MST Algorithm [19:00/2/21/2013 Zhe]                                                                     */
	/************************************************************************/
	list<int> Mstqueue;
	queue<int> nLayer;
	list<int>::iterator mstiterator,Mstqueueiterator,Layeriterator;
	fiter.reset();
	int a[Num] = {0};

	Face *MSTface = *fiter;
	Mstqueue.push_back(MSTface->id());
	nLayer.push(MSTface->id()); //initialization
	a[MSTface->id()] = TRUE;
	while (!nLayer.empty())
	{
		int Faceid = nLayer.front();	
		nLayer.pop();
		//MstGraphface[Faceid].push_back(Faceid);
		for (mstiterator = Graphface[Faceid].begin();mstiterator != Graphface[Faceid].end();++mstiterator)
		{
			//Layeriterator = find (Mstqueue.begin(), Mstqueue.end(), *mstiterator);
			if (a[*mstiterator] == 0) 
			{
				Mstqueue.push_back(*mstiterator);
				nLayer.push(*mstiterator);
				a[*mstiterator] = TRUE;
				int nFaceid_father = Faceid;
				int nFaceId_son = *mstiterator;

				MeshLib::Face *f = mesh.idFace (nFaceid_father);
				MeshLib::FaceHalfedgeIterator fheiter(f);

				MeshLib::Edge * inter_edge;
				for (; !fheiter.end (); ++fheiter)
				{
					MeshLib::HalfEdge *he = *fheiter;
					he = he->he_sym ();
					if (he->face ()->id ()== nFaceId_son)
					{
						inter_edge=he->edge ();
						inter_edge->string () = std::string("");
						break;
					}
				}
			}
		}
	}



	// 3. cut the graph [23:19/2/21/2013 Zhe]
	SolidVertexIterator iter(&mesh);
	std::map<int, int> vidToObjID;

	do 
	{
		for(; !iter.end(); ++iter)
		{
			Vertex *v = *iter;
			MeshLib::VertexEdgeIterator edgeiter(v);
			MeshLib::Edge * inter_edge;
			int nsharp = 0;
			for (;!edgeiter.end();++edgeiter)
			{			
				inter_edge = *edgeiter;
				if (inter_edge->string() == "sharp")
				{
					nsharp++;
				}
			}


			//delete nsharp == 1
			if (1 == nsharp)
			{
				edgeiter.reset();
				for (;!edgeiter.end();++edgeiter)
				{			
					inter_edge = *edgeiter;
					if (inter_edge->string() == "sharp")
					{
						inter_edge->string () = std::string("");
						//nsharp = 0;
					}
				}

			}
			vidToObjID[v->id()] = nsharp;
		}
		iter.reset();

	} while (ifsharpequalone(vidToObjID));

	mesh.write (filename.c_str()); 

	//	os.close();
}
int main(int argc, char *argv[])
{
	// Read in the obj file
	Solid mesh;
	OBJFileReader of;
	std::ifstream in(argv[1]);
	of.readToSolid(&mesh, in);
	
	
	
	

	//answer part
	Solid meshCopy;
	mesh.copy(meshCopy);
	
	//storing all vertices
	int i=0;
	SolidVertexIterator veriter(&mesh);
	Vertex *allvert[mesh.numVertices()];
	for(i=0;!veriter.end();i++,++veriter)
	{
		allvert[i]=*veriter;
	}
	
	//storing all edges
	SolidEdgeIterator eiter(&mesh);
	Edge *alledges[mesh.numEdges()];
	for(i=0;!eiter.end();i++,++eiter)
	{
		alledges[i]=*eiter;
	}
	
	
	Edge *swapList[mesh.numFaces()];
	Edge *splitSwap[2]={NULL,NULL};
	
	//getting max face
	SolidFaceIterator fciter(&mesh);
	int maxfcid=-1;
	for(; !fciter.end(); ++fciter)
	{
		if((*fciter)->id()>maxfcid)
			maxfcid=(*fciter)->id();
	}
	
	//splitting and swapping by iterating through edges
	SolidEdgeIterator eitercpy(&meshCopy);
	int j;
	double x,y,z;
	for(i=0,j=0;i<(sizeof(alledges)/sizeof(*alledges));i++,++eitercpy)
	{
		splitSwap[0]=splitSwap[1]=NULL;
		Vertex *evert1= mesh.edgeVertex1(alledges[i]);
		Vertex *evert2= mesh.edgeVertex2(alledges[i]);
		Vertex *ver1=mesh.edgeSplit(alledges[i],splitSwap,maxfcid);
		if(splitSwap[0]!=NULL)
			swapList[j++]=splitSwap[0];
		if(splitSwap[1]!=NULL)
			swapList[j++]=splitSwap[1];
		
		//position of new vertex determined here
		if(mesh.isBoundary(*eitercpy))
		{
			//printf("Check");
			x=(evert1->point()(0)/2)+(evert2->point()(0)/2);
			y=(evert1->point()(1)/2)+(evert2->point()(1)/2);
			z=(evert1->point()(2)/2)+(evert2->point()(2)/2);
			//printf("\n%f %f %f\n",x,y,z);
		}
		else
		{
			x=((evert1->point()(0))+(evert2->point()(0)))*(3.0/8.0);
			y=((evert1->point()(1))+(evert2->point()(1)))*(3.0/8.0);
			z=((evert1->point()(2))+(evert2->point()(2)))*(3.0/8.0);
			x+=(((((*eitercpy)->halfedge(0))->he_next())->target())->point()(0)/8.0)+(((((*eitercpy)->halfedge(1))->he_next())->target())->point()(0)/8.0);
			y+=(((((*eitercpy)->halfedge(0))->he_next())->target())->point()(1)/8.0)+(((((*eitercpy)->halfedge(1))->he_next())->target())->point()(1)/8.0);
			z+=(((((*eitercpy)->halfedge(0))->he_next())->target())->point()(2)/8.0)+(((((*eitercpy)->halfedge(1))->he_next())->target())->point()(2)/8.0);
		}
		
		ver1->point()=Point(x,y,z);
	}
	
	
	for(i=0;i<(sizeof(swapList)/sizeof(*swapList));i++)
	{
		Edge *e=swapList[i];
		mesh.edgeSwap(e,((e->halfedge(0))->he_next())->target(),((e->halfedge(1))->he_next())->target());
	}
	
	
	
	
	//new position of old vertices determined here
	SolidVertexIterator veritercpy(&meshCopy);
	double tem1,tem2,tem3,alpha;
	for(i=0;i<(sizeof(allvert)/sizeof(*allvert));i++,++veritercpy)
	{
		Vertex *oldv=allvert[i];
		//printf("\n%f %f %f -> ",oldv->point()(0),oldv->point()(1),oldv->point()(2));
		VertexVertexIterator vviter(*veritercpy);
		//printf("Im here\n");
		tem1=tem2=tem3=0;
		j=0;
		if(mesh.isBoundary(*veritercpy))
		{
			//printf("Hi");
			for(j=0;!vviter.end();++vviter)
			{
				if(mesh.isBoundary(*vviter))
				{
					tem1+=(*vviter)->point()(0);
					tem2+=(*vviter)->point()(1);
					tem3+=(*vviter)->point()(2);
					j++;
				}
			}
			x=tem1/8.0 + oldv->point()(0)*(3.0/4.0);
			y=tem2/8.0 + oldv->point()(1)*(3.0/4.0);
			z=tem3/8.0 + oldv->point()(2)*(3.0/4.0);
		}
		else
		{
			tem1=tem2=tem3=0;
			for(j=0;!vviter.end();++vviter)
			{
				tem1+=(*vviter)->point()(0);
				tem2+=(*vviter)->point()(1);
				tem3+=(*vviter)->point()(2);
				j++;
			}
			//printf("%d\n",j);
			if(j>3)
				alpha=(1.0/j)*((5.0/8.0)-pow(((3.0/8.0)+(1.0/4.0)*(cos(2*PI/j))),2));
			else if(j==3)
				alpha=3/16;

			x=((1-j*alpha)*oldv->point()(0)) + (alpha*(tem1));
			y=((1-j*alpha)*oldv->point()(1)) + (alpha*(tem2));;
			z=((1-j*alpha)*oldv->point()(2)) + (alpha*(tem3));;
		}
		oldv->point()=Point(x,y,z);
		//printf("\n%f %f %f %f-> ",x,y,z, (1.0/4.0)*cos(2*PI/j));
		//printf("\n%f %f %f -> ",oldv->point()(0),oldv->point()(1),oldv->point()(2));
	}
	
	
	
	


	// Write out the resultant obj file
	int vObjID = 1;
	std::map<int, int> vidToObjID;

	std::ofstream os(argv[2]);

	SolidVertexIterator iter(&mesh);

	for(; !iter.end(); ++iter)
	{
		Vertex *v = *iter;
		Point p = v->point();
		os << "v " << p[0] << " " << p[1] << " " << p[2] << std::endl;
		vidToObjID[v->id()] = vObjID++;
	}
	os << "# " << (unsigned int)mesh.numVertices() << " vertices" << std::endl;

	float u = 0.0, v = 0.0;
	for(iter.reset(); !iter.end(); ++iter)
	{
		Vertex *vv = *iter;
		std::string key( "uv" );
		std::string s = Trait::getTraitValue (vv->string(), key );
		if( s.length() > 0 )
		{
			sscanf( s.c_str (), "%f %f", &u, &v );
		}
		os << "vt " << u << " " << v << std::endl;
	}
	os << "# " << (unsigned int)mesh.numVertices() << " texture coordinates" << std::endl;

	SolidFaceIterator fiter(&mesh);
	for(; !fiter.end(); ++fiter)
	{
		Face *f = *fiter;
		FaceVertexIterator viter(f);
		os << "f " ;
		for(; !viter.end(); ++viter)
		{
			Vertex *v = *viter;
			os << vidToObjID[v->id()] << "/" << vidToObjID[v->id()] << " ";
		}
		os << std::endl;
	}
	os.close();
	return 0;
}
Пример #4
0
void main(int argc, char *argv[])
{
	// Read in the obj file
	Solid mesh;
	
	OBJFileReader of;
	std::ifstream in(argv[1]);
	of.readToSolid(&mesh, in);

	SolidDelegate sodel;
	SolidVertexIterator viter(&mesh);
	SolidFaceIterator faceiter(&mesh);
	
	Point deltaPL[2502];
	Point Normal[2502];
	Point tuettePoint[2502];
	Point harmonicPoint[2502];
	double innerProduct;
	Point normalComp;
	Point aDerv;
	for (int i = 0; i < 2502; i++)
	{
		deltaPL[i][0] = 0.0;
		deltaPL[i][1] = 0.0;
		deltaPL[i][2] = 0.0;
		Normal[i][0] = 0.0;
		Normal[i][1] = 0.0;
		Normal[i][2] = 0.0;
		tuettePoint[i][0] = 0.0;
		tuettePoint[i][1] = 0.0;
		tuettePoint[i][2] = 0.0;
		harmonicPoint[i] = { 0.0, 0.0, 0.0 };

	}
	for (; !viter.end(); ++viter)
	{
		
		Vertex *vertmp = *viter;
		//VertexOutHalfedgeIterator voh(&mesh, vertmp);
		
		Point norm;//calc new Norm
		double totalArea = 0.0;
		
		norm[0] = norm[1] = norm[2] = 0.0;
		VertexFaceIterator vf(vertmp);
		for (; !vf.end(); ++vf){
			double area = 0.0;
			Face *f = *vf;
			
			Point v1 = f->halfedge()->source()->point();
			Point v2 = f->halfedge()->target()->point();
			Point v3 = f->halfedge()->he_next()->target()->point();

			area = ((v3 - v1) ^ (v2 - v1)).norm();
			

			Point n = f->norm();
			norm += n * area;
			totalArea += area;
		}
		

		Point newNorm;
		norm = norm / totalArea;
		double normN = norm.norm();
		newNorm = norm / normN;
		

		//Normal & Gauss Map
		Normal[vertmp->id() - 1] = newNorm;
	
		

	}
	
	SolidEdgeIterator edgeiter(&mesh);

	
	double tuetteEnergy = 0.0;
	double newTEnergy = 0.0;
	double harmoincEnergy = 0.0;
	double newHEnergy = 0.0;
	double stepLength = 0.01;
	double eThreshold = 0.00001;
	
	for (; !edgeiter.end(); ++edgeiter) {
		Edge *e = *edgeiter;

		Vertex *s = mesh.edgeVertex1(e);
		Vertex *t = mesh.edgeVertex2(e);
	
		tuetteEnergy += (Normal[s->id() - 1] - Normal[t->id() - 1]).norm2();
		 
		
	}

	//harmonic K
	double K, cota, cotb;


	edgeiter.reset();
	
	for (; !edgeiter.end(); ++edgeiter) {
		Edge *e = *edgeiter;
		Vertex *s = mesh.edgeVertex1(e);
		Vertex *t = mesh.edgeVertex2(e);
		HalfEdge *he = e->halfedge(1);
		he = he->ccw_rotate_about_source();
		Vertex *v1 = he->target();
		he = he->clw_rotate_about_source()->clw_rotate_about_source();
		Vertex *v2 = he->target();
		cota = (s->point() - v1->point())*(t->point() - v1->point()) / ((s->point() - v1->point()) ^ (t->point() - v1->point())).norm();
		cotb = (s->point() - v2->point())*(t->point() - v2->point()) / ((s->point() - v2->point()) ^ (t->point() - v2->point())).norm();
		
		
		K = (cota + cotb) / 2.0;
		edgemap.insert({ e, K });

	}

	viter.reset();
	//Gauss map update
	for (; !viter.end(); ++viter) {
		Vertex *vertmp = *viter;
		vertmp->point() = Normal[vertmp->id() - 1]  ;
	}

	
	
	viter.reset();
	

	for (; !viter.end(); ++viter)//step2
	{


		Vertex *vertmp = *viter;
		VertexOutHalfedgeIterator voh(&mesh, vertmp);
		Point u = vertmp->point();
		int id = vertmp->id()-1;
		double num = 0.0;
		for (; !voh.end(); ++voh)
		{
			
			HalfEdge *he1 = *voh;
			Vertex *v1 = he1->target();
			Point v = v1->point();

			deltaPL[id] += v - u;
			num = num + 1.0;
		}
		deltaPL[id] = deltaPL[id] / num;
	}

	//absolute derivatives
	viter.reset();
	for (; !viter.end(); ++viter)//step2
	{
		Vertex *vertmp = *viter;
		VertexOutHalfedgeIterator voh(&mesh, vertmp);
		Point u = vertmp->point();
		int id = vertmp->id() - 1;
		
		innerProduct = deltaPL[id] * Normal[id];
	
	
		normalComp[0] = innerProduct * Normal[id][0];
		normalComp[1] = innerProduct * Normal[id][1];
		normalComp[2] = innerProduct * Normal[id][2];
		
		Point aDerv = deltaPL[id] - normalComp;
		Point tuetteUpdate = aDerv * stepLength;
		

		tuettePoint[id] = tuetteUpdate; //step 3
		
	}

	viter.reset();
	for (; !viter.end(); ++viter)//step2
	{
		Vertex *vertmp = *viter;
		int id = vertmp->id() - 1;
		Normal[id] += tuettePoint[id];
		Normal[id] = Normal[id] / Normal[id].norm();
	}

	
		
	edgeiter.reset();
		
	for (; !edgeiter.end(); ++edgeiter) {
		Edge *e = *edgeiter;

		Vertex *s = mesh.edgeVertex1(e);
		Vertex *t = mesh.edgeVertex2(e);

		newTEnergy += (Normal[s->id() - 1] - Normal[t->id() - 1]).norm2();

   	}
	viter.reset();
		//tuette map update
	for (; !viter.end(); ++viter) {
		Vertex *vertmp = *viter;
		vertmp->point() =Normal[vertmp->id() - 1];
	}

	
	
	
	
	//while(1==0)
	while (!(fabs(newTEnergy - tuetteEnergy) < eThreshold*1000))
	{//step 5
		tuetteEnergy = newTEnergy;
		newTEnergy = 0.0;
		//printf("%f\n", tuetteEnergy);
		
		
		
		
		viter.reset();


		for (; !viter.end(); ++viter)//step2
		{


			Vertex *vertmp = *viter;
			VertexOutHalfedgeIterator voh(&mesh, vertmp);
			Point u = vertmp->point();
			int id = vertmp->id() - 1;
			double num = 0.0;
			for (; !voh.end(); ++voh)
			{

				HalfEdge *he1 = *voh;
				Vertex *v1 = he1->target();
				Point v = v1->point();

				deltaPL[id] += v - u;
				num = num + 1.0;
			}
			deltaPL[id] = deltaPL[id] / num;
		}

		viter.reset();
		for (; !viter.end(); ++viter)//step2
		{
			Vertex *vertmp = *viter;
			VertexOutHalfedgeIterator voh(&mesh, vertmp);
			Point u = vertmp->point();
			int id = vertmp->id() - 1;

			innerProduct = deltaPL[id] * Normal[id];


			normalComp[0] = innerProduct * Normal[id][0];
			normalComp[1] = innerProduct * Normal[id][1];
			normalComp[2] = innerProduct * Normal[id][2];

			Point aDerv = deltaPL[id] - normalComp;
			Point tuetteUpdate = aDerv * stepLength;


			tuettePoint[id] = tuetteUpdate; //step 3

		}

		viter.reset();
		for (; !viter.end(); ++viter)//step2
		{
			Vertex *vertmp = *viter;
			int id = vertmp->id() - 1;
			Normal[id] += tuettePoint[id];
			Normal[id] = Normal[id] / Normal[id].norm();
		}



		edgeiter.reset();

		for (; !edgeiter.end(); ++edgeiter) {
			Edge *e = *edgeiter;

			Vertex *s = mesh.edgeVertex1(e);
			Vertex *t = mesh.edgeVertex2(e);

			newTEnergy += (Normal[s->id() - 1] - Normal[t->id() - 1]).norm2();

		}
		viter.reset();
		//tuette map update
		for (; !viter.end(); ++viter) {
			Vertex *vertmp = *viter;
			vertmp->point() = Normal[vertmp->id() - 1];
		}
}

	tuetteEnergy = newTEnergy;
	harmoincEnergy = tuetteEnergy;
	//harmonic

	viter.reset();


	for (; !viter.end(); ++viter)//step2
	{


		Vertex *vertmp = *viter;
		VertexOutHalfedgeIterator voh(&mesh, vertmp);
		Point u = vertmp->point();
		int id = vertmp->id() - 1;
		double num = 0.0;
		for (; !voh.end(); ++voh)
		{

			HalfEdge *he1 = *voh;
			Edge *e = he1->edge();
			Vertex *v1 = he1->target();
			Point v = v1->point();
			std::unordered_map<Edge*,double>::const_iterator got = edgemap.find(e);
			double K = got->second;
			deltaPL[id] += (v - u) * K;
			num = num + 1.0;
		}
		deltaPL[id] = deltaPL[id] / num;
	}
	
	//absolute derivatives
	viter.reset();
	for (; !viter.end(); ++viter)//step2
	{
		Vertex *vertmp = *viter;
		VertexOutHalfedgeIterator voh(&mesh, vertmp);
		Point u = vertmp->point();
		int id = vertmp->id() - 1;

		innerProduct = deltaPL[id] * Normal[id];


		normalComp[0] = innerProduct * Normal[id][0];
		normalComp[1] = innerProduct * Normal[id][1];
		normalComp[2] = innerProduct * Normal[id][2];

		Point aDerv = deltaPL[id] - normalComp;
		Point hUpdate = aDerv * stepLength;


		harmonicPoint[id] =hUpdate; //step 3

	}
	// compute mass center
	Point mass = { 0.0, 0.0, 0.0 };
	viter.reset();

	for (; !viter.end(); ++viter)//step2
	{
		Vertex *vertmp = *viter;
		mass += vertmp->point();
	}
	mass = mass / 2502;

	// h update w/ mass
	viter.reset();
	for (; !viter.end(); ++viter)//step2
	{
		Vertex *vertmp = *viter;
		int id = vertmp->id() - 1;
		Normal[id] +=harmonicPoint[id];
		Normal[id] -= mass;
		Normal[id] = Normal[id] / Normal[id].norm();
	}

	//h energy
	edgeiter.reset();

	for (; !edgeiter.end(); ++edgeiter) {
		Edge *e = *edgeiter;

		Vertex *s = mesh.edgeVertex1(e);
		Vertex *t = mesh.edgeVertex2(e);
		
		std::unordered_map<Edge*, double>::const_iterator got = edgemap.find(e);
		double K = got->second;
		
		newHEnergy += (Normal[s->id() - 1] - Normal[t->id() - 1]).norm2()*K;

	}
	viter.reset();
	//h map update
	for (; !viter.end(); ++viter) {
		Vertex *vertmp = *viter;
		vertmp->point() = Normal[vertmp->id() - 1];
	}
	
	
	
	while (!(fabs(newHEnergy - harmoincEnergy) < eThreshold))
	{
		harmoincEnergy = newHEnergy;
		newHEnergy = 0.0;
		//printf("%f\n", harmoincEnergy);


		viter.reset();


		for (; !viter.end(); ++viter)//step2
		{


			Vertex *vertmp = *viter;
			VertexOutHalfedgeIterator voh(&mesh, vertmp);
			Point u = vertmp->point();
			int id = vertmp->id() - 1;
			double num = 0.0;
			for (; !voh.end(); ++voh)
			{

				HalfEdge *he1 = *voh;
				Edge *e = he1->edge();
				Vertex *v1 = he1->target();
				Point v = v1->point();
				std::unordered_map<Edge*, double>::const_iterator got = edgemap.find(e);
				double K = got->second;
				deltaPL[id] += (v - u) * K;
				num = num + 1.0;
			}
			deltaPL[id] = deltaPL[id] / num;
		}

		//absolute derivatives
		viter.reset();
		for (; !viter.end(); ++viter)//step2
		{
			Vertex *vertmp = *viter;
			VertexOutHalfedgeIterator voh(&mesh, vertmp);
			Point u = vertmp->point();
			int id = vertmp->id() - 1;

			innerProduct = deltaPL[id] * Normal[id];


			normalComp[0] = innerProduct * Normal[id][0];
			normalComp[1] = innerProduct * Normal[id][1];
			normalComp[2] = innerProduct * Normal[id][2];

			Point aDerv = deltaPL[id] - normalComp;
			Point hUpdate = aDerv * stepLength;


			harmonicPoint[id] = hUpdate; //step 3

		}
		// compute mass center
		Point mass = { 0.0, 0.0, 0.0 };
		viter.reset();

		for (; !viter.end(); ++viter)//step2
		{
			Vertex *vertmp = *viter;
			mass += vertmp->point();
		}
		mass = mass / 2502;

		// h update w/ mass
		viter.reset();
		for (; !viter.end(); ++viter)//step2
		{
			Vertex *vertmp = *viter;
			int id = vertmp->id() - 1;
			Normal[id] += harmonicPoint[id];
			Normal[id] -= mass;
			Normal[id] = Normal[id] / Normal[id].norm();
		}

		//h energy
		edgeiter.reset();

		for (; !edgeiter.end(); ++edgeiter) {
			Edge *e = *edgeiter;

			Vertex *s = mesh.edgeVertex1(e);
			Vertex *t = mesh.edgeVertex2(e);

			std::unordered_map<Edge*, double>::const_iterator got = edgemap.find(e);
			double K = got->second;

			newHEnergy += (Normal[s->id() - 1] - Normal[t->id() - 1]).norm2()*K;

		}
		viter.reset();
		//h map update
		for (; !viter.end(); ++viter) {
			Vertex *vertmp = *viter;
			vertmp->point() = Normal[vertmp->id() - 1];
		}

	}

	/***conformal****/


	// Write out the resultant obj file
	int vObjID = 1;
	std::map<int, int> vidToObjID;

	std::ofstream os(argv[2]);

	SolidVertexIterator iter(&mesh);

	for (; !iter.end(); ++iter)
	{
		Vertex *v = *iter;
		Point p = v->point();
		os << "v " << p[0] << " " << p[1] << " " << p[2] << std::endl;
		vidToObjID[v->id()] = vObjID++;
	}
	os << "# " << (unsigned int)mesh.numVertices() << " vertices" << std::endl;


	//texture
	float u = 0.0, v = 0.0;
	for (iter.reset(); !iter.end(); ++iter)
	{
		Vertex *vv = *iter;
		std::string key("uv");
		std::string s = Trait::getTraitValue(vv->string(), key);
		if (s.length() > 0)
		{
			sscanf(s.c_str(), "%f %f", &u, &v);
		}
		os << "vt " << u << " " << v << std::endl;
	}
	os << "# " << (unsigned int)mesh.numVertices() << " texture coordinates" << std::endl;

	SolidFaceIterator fiter(&mesh);
	for (; !fiter.end(); ++fiter)
	{
		Face *f = *fiter;
		FaceVertexIterator viter(f);
		os << "f ";
		for (; !viter.end(); ++viter)
		{
			Vertex *v = *viter;
			os << vidToObjID[v->id()] << "/" << vidToObjID[v->id()] << " ";
		}
		os << std::endl;
	}
	os.close();
}