1 #ifndef TRI_PARAMETRIZATION
2 #define TRI_PARAMETRIZATION
3 
4 // stuff to define the mesh
5 //#include <vcg/space/triangle3.h>
6 //#include <vcg/simplex/face/component_rt.h>
7 //#include <vcg/complex/complex.h>
8 #include "local_parametrization.h"
9 #include "uv_grid.h"
10 #include <vcg/complex/algorithms/clean.h>
11 #include <vcg/complex/algorithms/stat.h>
12 #include "param_mesh.h"
13 
14 ///ABSTRACT MESH THAT MAINTAINS THE WHOLE PARAMETERIZATION
15 class AbstractVertex;
16 class AbstractFace;
17 
18 class AbstractUsedTypes: public vcg::UsedTypes < vcg::Use<AbstractVertex>::AsVertexType,
19                                           vcg::Use<AbstractFace  >::AsFaceType >{};
20 
21 
22 class AbstractVertex  : public vcg::Vertex< AbstractUsedTypes,
23     vcg::vertex::VFAdj,
24     vcg::vertex::Coord3f,
25     vcg::vertex::TexCoord2f,
26     vcg::vertex::BitFlags>
27   //vcg::face::Normal3f>
28 {
29 public:
30     CoordType RPos;
31 
32   template < class LeftV>
ImportData(const LeftV & left)33     void ImportData(const LeftV  & left )
34   {
35             vcg::Vertex< AbstractUsedTypes, vcg::vertex::VFAdj, vcg::vertex::Coord3f,vcg::vertex::TexCoord2f,vcg::vertex::BitFlags>::ImportData( left);
36       this->RPos = left.RPos;
37   }
38 };
39 
40 class AbstractFace    : public vcg::Face  < AbstractUsedTypes,
41     vcg::face::VFAdj,
42     vcg::face::FFAdj,
43     vcg::face::VertexRef,
44     vcg::face::Color4b,
45     vcg::face::BitFlags,
46     vcg::face::Quality3f>
47 //vcg::face::Normal3f>
48 {};
49 
50 class AbstractMesh: public vcg::tri::TriMesh<std::vector<AbstractVertex>, std::vector<AbstractFace> > {
51 //public:
52 //	static const bool Has_Auxiliary(){return false;}
53 };
54 
55 ///HIGH RESOLUTION MESH THAT HAS TO BE PARAMETERIZED
56 class ParamVertex;
57 class ParamFace;
58 
59 
60 class ParamUsedTypes: public vcg::UsedTypes < vcg::Use<ParamVertex>::AsVertexType,
61                                           vcg::Use<ParamFace  >::AsFaceType >{};
62 
63 
64 class ParamVertex: public vcg::Vertex< ParamUsedTypes,
65                                             vcg::vertex::Normal3f, vcg::vertex::VFAdj,
66                                             vcg::vertex::Coord3f,vcg::vertex::Color4b,
67                                             vcg::vertex::TexCoord2f,vcg::vertex::BitFlags,
68                                             vcg::vertex::CurvatureDirf,
69                                             vcg::vertex::Qualityf>
70 {
71 public:
72     template < class LeftV>
ImportData(const LeftV & left)73         void ImportData(const LeftV  & left )
74     {
75                 vcg::Vertex< ParamUsedTypes, vcg::vertex::Normal3f, vcg::vertex::VFAdj, vcg::vertex::Coord3f,vcg::vertex::Color4b, vcg::vertex::TexCoord2f,vcg::vertex::BitFlags, vcg::vertex::CurvatureDirf,vcg::vertex::Qualityf >::ImportData( left);
76     }
77 
78 
ImportData(const ParamVertex & left)79         void ImportData(const ParamVertex  & left )
80     {
81                 vcg::Vertex< ParamUsedTypes, vcg::vertex::Normal3f, vcg::vertex::VFAdj, vcg::vertex::Coord3f,vcg::vertex::Color4b, vcg::vertex::TexCoord2f,vcg::vertex::BitFlags, vcg::vertex::CurvatureDirf,vcg::vertex::Qualityf >::ImportData( left);
82         this->RPos = left.RPos;
83     }
84 
ImportData(const BaseVertex & left)85     void ImportData(const BaseVertex  & left )
86     {
87                 vcg::Vertex< ParamUsedTypes, vcg::vertex::Normal3f, vcg::vertex::VFAdj, vcg::vertex::Coord3f,vcg::vertex::Color4b, vcg::vertex::TexCoord2f,vcg::vertex::BitFlags, vcg::vertex::CurvatureDirf,vcg::vertex::Qualityf >::ImportData( left);
88         this->RPos = left.RPos;
89     }
90 
91     CoordType RPos;
Has_Auxiliary()92   static bool Has_Auxiliary(){return false;}
93 };
94 
95 class ParamFace: public vcg::Face <  ParamUsedTypes,
96     vcg::face::VFAdj,vcg::face::FFAdj,vcg::face::VertexRef,
97   vcg::face::Color4b,vcg::face::BitFlags,
98   vcg::face::Normal3f,
99     vcg::face::WedgeTexCoord2f,
100     vcg::face::Mark,
101     vcg::face::Quality3f>
102 {
103 public:
104     /*template < class LeftV>
105         void ImportData(const LeftV  & left )
106     {
107        vcg::FaceSimp2  <  ParamVertex, ParamEdge, ParamFace,
108     vcg::face::VFAdj,vcg::face::FFAdj,vcg::face::VertexRef,
109   vcg::face::Color4b,vcg::face::BitFlags,
110   vcg::face::WedgeTexCoord2f,vcg::face::Normal3f,
111     vcg::face::Qualityf>::ImportData( left);
112     }*/
113 };
114 class ParamMesh: public vcg::tri::TriMesh<std::vector<ParamVertex>, std::vector<ParamFace> >
115 {
116 //public:
117     //static const bool Has_Auxiliary(){return false;}
118 };
119 
120 template <class MeshType>
CopyMeshFromFacesAbs(const std::vector<typename MeshType::FaceType * > & faces,std::vector<typename MeshType::VertexType * > & orderedVertex,MeshType & new_mesh)121 void CopyMeshFromFacesAbs(const std::vector<typename MeshType::FaceType*> &faces,
122                           std::vector<typename MeshType::VertexType*> &orderedVertex,
123                           MeshType & new_mesh)
124 {
125     typedef typename MeshType::VertexType VertexType;
126     typedef typename MeshType::FaceType FaceType;
127 
128     ///get set of faces
129     std::map<VertexType*,VertexType*> vertexmap;
130         std::vector<VertexType*> vertices;
131     FindVertices(faces,vertices);
132 
133     ///initialization of new mesh
134     new_mesh.Clear();
135     new_mesh.vn=0;
136     new_mesh.fn=0;
137     new_mesh.face.resize(faces.size());
138     new_mesh.vert.resize(vertices.size());
139     new_mesh.vn=vertices.size();
140     new_mesh.fn=faces.size();
141 
142     ///add new vertices
143         typename std::vector<VertexType*>::const_iterator iteV;
144     int i=0;
145     for (iteV=vertices.begin();iteV!=vertices.end();iteV++)
146     {
147         ///copy position
148         assert(!(*iteV)->IsD());
149         new_mesh.vert[i].P()=(*iteV)->P();
150         new_mesh.vert[i].RPos=(*iteV)->RPos;
151         new_mesh.vert[i].T().P()=(*iteV)->T().P();
152         new_mesh.vert[i].T().N()=(*iteV)->T().N();
153         //new_mesh.vert[i].N()=(*iteV)->N();
154         ///*assert(new_mesh.vert[i].brother!=NULL);*/
155         ////if (MeshType::Has_Auxiliary())
156         //new_mesh.vert[i].brother=(*iteV)->brother;
157         new_mesh.vert[i].ClearFlags();
158 
159         orderedVertex.push_back((*iteV));
160         vertexmap.insert(std::pair<VertexType*,VertexType*>((*iteV),&new_mesh.vert[i]));
161         i++;
162     }
163 
164     ///setting of new faces
165         typename std::vector<FaceType*>::const_iterator iteF;
166         typename std::vector<FaceType>::iterator iteF1;
167     for (iteF=faces.begin(),iteF1=new_mesh.face.begin()
168         ;iteF!=faces.end();iteF++,iteF1++)
169     {
170         //(*iteF1).areadelta=(*iteF)->areadelta;
171     /*	if ((*iteF1).areadelta>1)
172             assert(0);*/
173         ///for each vertex get new reference
174         ///and associate face-vertex
175         for (int j=0;j<3;j++)
176         {
177             VertexType* v=(*iteF)->V(j);
178                         typename std::map<VertexType*,VertexType*>::iterator iteMap=vertexmap.find(v);
179             assert(iteMap!=vertexmap.end());
180             (*iteF1).V(j)=(*iteMap).second;
181         }
182     }
183 }
184 
185 ///create a mesh considering just the faces that share all three vertex
186 template <class MeshType>
CopyMeshFromVerticesAbs(std::vector<typename MeshType::VertexType * > & vertices,std::vector<typename MeshType::VertexType * > & OrderedVertices,std::vector<typename MeshType::FaceType * > & OrderedFaces,MeshType & new_mesh)187 void CopyMeshFromVerticesAbs(std::vector<typename MeshType::VertexType*> &vertices,
188                           std::vector<typename MeshType::VertexType*> &OrderedVertices,
189                           std::vector<typename MeshType::FaceType*> &OrderedFaces,
190                           MeshType & new_mesh)
191 {
192         typedef typename MeshType::VertexType VertexType;
193         typedef typename MeshType::FaceType FaceType;
194 
195         typename std::vector<VertexType*>::const_iterator iteV;
196     for (iteV=vertices.begin();iteV!=vertices.end();iteV++)
197         (*iteV)->ClearV();
198 
199 
200 
201     OrderedVertices.clear();
202 
203     ///vertex-vertex reference
204     std::map<VertexType*,VertexType*> vertexmap;
205 
206     ///get set of faces
207     std::vector<typename MeshType::FaceType*> faces;
208 
209     getSharedFace<MeshType>(vertices,faces);
210 
211     ///initialization of new mesh
212     new_mesh.Clear();
213     new_mesh.vn=0;
214     new_mesh.fn=0;
215 
216     ///set vertices as selected
217 
218     for (iteV=vertices.begin();iteV!=vertices.end();iteV++)
219         (*iteV)->SetV();
220 
221     ///getting inside faces
222         typename std::vector<FaceType*>::const_iterator iteF;
223     for (iteF=faces.begin();iteF!=faces.end();iteF++)
224     {
225         ///for each vertex get new reference
226         ///if there isn't one reference means the face does not appartain to group
227         VertexType* v0=(*iteF)->V(0);
228         VertexType* v1=(*iteF)->V(1);
229         VertexType* v2=(*iteF)->V(2);
230         bool inside=((*v0).IsV()&&(*v1).IsV()&&(*v2).IsV());
231         if (inside)
232             OrderedFaces.push_back((*iteF));
233     }
234 
235     ///find internal vertices
236     FindVertices(OrderedFaces,OrderedVertices);
237 
238     ///setting size
239     new_mesh.face.resize(OrderedFaces.size());
240     new_mesh.vert.resize(OrderedVertices.size());
241     new_mesh.vn=OrderedVertices.size();
242     new_mesh.fn=OrderedFaces.size();
243 
244     ///setting of internal vertices
245     int i=0;
246         typename std::vector<typename MeshType::VertexType*>::iterator iteVI;
247     for (iteVI=OrderedVertices.begin();iteVI!=OrderedVertices.end();iteVI++)
248     {
249         ///copy position
250         assert(!(*iteVI)->IsD());
251         new_mesh.vert[i].P()=(*iteVI)->P();
252         new_mesh.vert[i].RPos=(*iteVI)->RPos;
253         new_mesh.vert[i].T().P()=(*iteVI)->T().P();
254         new_mesh.vert[i].T().N()=(*iteVI)->T().N();
255         new_mesh.vert[i].C()=(*iteVI)->C();
256         /*new_mesh.vert[i].father=(*iteVI)->father;
257         new_mesh.vert[i].Bary=(*iteVI)->Bary;*/
258         //new_mesh.vert[i].Damp=(*iteVI)->Damp;
259         /*new_mesh.vert[i].RestUV=(*iteVI)->RestUV;*/
260         //new_mesh.vert[i].N()=(*iteVI)->N();
261         //new_mesh.vert[i].C()=(*iteVI)->C();
262         /*new_mesh.vert[i].OriginalCol=(*iteVI)->OriginalCol;*/
263         new_mesh.vert[i].ClearFlags();
264         ///map setting
265         vertexmap.insert(std::pair<VertexType*,VertexType*>((*iteVI),&new_mesh.vert[i]));
266         i++;
267     }
268 
269     ///setting of new faces
270         typename std::vector<FaceType>::iterator iteF1;
271     for (iteF=OrderedFaces.begin(),iteF1=new_mesh.face.begin()
272         ;iteF!=OrderedFaces.end();iteF++,iteF1++)
273     {
274         ///for each vertex get new reference
275         ///and associate face-vertex
276         for (int j=0;j<3;j++)
277         {
278             VertexType* v=(*iteF)->V(j);
279                         typename std::map<VertexType*,VertexType*>::iterator iteMap=vertexmap.find(v);
280             assert(iteMap!=vertexmap.end());
281             (*iteF1).V(j)=(*iteMap).second;
282         }
283     }
284 
285     ///clear flags
286     for (iteV=vertices.begin();iteV!=vertices.end();iteV++)
287         (*iteV)->ClearV();
288 
289 }
290 
291 
292 
293 
294 //template <class InputMesh>
295 //static int Parametrize(InputMesh &to_param,
296 //					   AbstractMesh &AbsMesh,
297 //					   InputMesh &Parametrized,
298 //					   int &approx_face_num)
299 //{
300 //	vcg::tri::UpdateTopology<InputMesh>::FaceFace(to_param);
301 //
302 //	///test input conditions
303 //	bool b=vcg::tri::Clean<InputMesh>::IsTwoManifoldFace(to_param);
304 //	b&=vcg::tri::Clean<InputMesh>::IsTwoManifoldVertexFF(to_param);
305 //	int n=vcg::tri::Clean<InputMesh>::BorderEdges(to_param);
306 //	b&=(n==0);
307 //	int num=vcg::tri::Clean<InputMesh>::ConnectedComponents(to_param);
308 //	b&=(num==1);
309 //	if (!b)
310 //		return -1;
311 //
312 //	///then parameteterize
313 //	IsoParametrizator TrImage;
314 //	TrImage.Parametrize<MyMesh>(&mesh,num1,num2);
315 //	TrImage.ExportMeshes(to_param,AbsMesh);
316 //	return 0;
317 //}
318 
319 ///class that maintains the whole meh parametrerization with relitive operators
320 class IsoParametrization
321 {
322     AbstractMesh * abstract_mesh;
323     ParamMesh	 * param_mesh;
324 
325 public:
326     typedef ParamMesh::ScalarType PScalarType;
327     typedef ParamMesh::CoordType CoordType;
328 
329 private:
330 
331     ///this class maintains submeshes and hresolution meshes
332     ///for the selected parametrization domain
333     struct param_domain{
334         AbstractMesh *domain;
335         std::vector<int> local_to_global;
336 
337         ParamMesh *HresDomain;
338         UVGrid<ParamMesh> grid;
339         std::vector<ParamFace*> ordered_faces;
340 
Local2Globalparam_domain341         int Local2Global(const int &localFace)
342         {return local_to_global[localFace];}
343 
Global2Localparam_domain344         int Global2Local(const int &GlobalFace)
345         {
346             int ret=-1;
347             for (unsigned int i=0;i<local_to_global.size();i++)
348                 if (local_to_global[i]==GlobalFace)
349                     return i;
350             return ret;
351         }
352 
InitGridparam_domain353         void InitGrid()
354         {grid.Init(*HresDomain);}
355 
Projectparam_domain356         bool Project(vcg::Point2<PScalarType> UV,
357                     std::vector<ParamFace*> &face,
358                     std::vector<CoordType> &baryVal)
359         {
360             std::vector<ParamFace*> faceParam;
361             bool found=grid.ProjectPoint(UV,faceParam,baryVal);
362             if (!found)
363                 return false;
364             ///calculate the index corresponding to the face
365             for (unsigned int i=0;i<faceParam.size();i++)
366             {
367                 ParamFace* f=faceParam[i];
368                 int index=f-&(*HresDomain->face.begin());
369                 assert(index<HresDomain->fn);
370                 face.push_back(ordered_faces[index]);
371             }
372             return true;
373         }
374 
getClosestparam_domain375         bool getClosest(vcg::Point2<PScalarType> UV,
376                         std::vector<ParamFace*> &face,
377                         std::vector<CoordType> &baryVal)
378         {
379             face.resize(1);
380             baryVal.resize(1);
381             bool found=grid.getClosest(UV,face[0],baryVal[0]);
382             int index=face[0]-&(*HresDomain->face.begin());
383             assert(index<HresDomain->fn);
384             face[0]=ordered_faces[index];
385             return found;
386         }
387     };
388 
389     ///summeshes and subdomains
390     std::vector<param_domain> star_meshes;
391     std::vector<param_domain> diamond_meshes;
392     std::vector<param_domain> face_meshes;
393 
394     typedef std::pair<AbstractVertex*,AbstractVertex*> keyEdgeType;
395     std::map<keyEdgeType,int> EdgeTab;
396 
397     ///temporary structure for face_to_vert adjacency
398     std::vector<std::vector<ParamVertex*> > face_to_vert;
399 
InitFaceToVert()400     void InitFaceToVert()
401     {
402         face_to_vert.resize(abstract_mesh->face.size());
403         for (unsigned int i=0;i<param_mesh->vert.size();i++)
404         {
405             int I=param_mesh->vert[i].T().N();
406             face_to_vert[I].push_back(&param_mesh->vert[i]);
407         }
408     }
409 
410 
GetHresVert(int & I,std::vector<ParamVertex * > & HresVert)411     void GetHresVert(int &I,std::vector<ParamVertex*> &HresVert)
412     {
413         for (unsigned int k=0;k<face_to_vert[I].size();k++)
414         {
415             ParamVertex* v=face_to_vert[I][k];
416             HresVert.push_back(v);
417         }
418     }
419 
420     ///initialize star parametrization
InitStar()421     void InitStar()
422     {
423         ///for each vertex
424         int index=0;
425         for (unsigned int i=0;i<abstract_mesh->vert.size();i++)
426         {
427             if (!(abstract_mesh->vert[i].IsD()))
428             {
429                 std::vector<AbstractVertex*> starCenter;
430                 starCenter.push_back(&abstract_mesh->vert[i]);
431 
432                 star_meshes[index].domain=new AbstractMesh();
433                 star_meshes[index].HresDomain=new ParamMesh();
434 
435                 ///create star
436                 std::vector<AbstractFace*> ordered_faces;
437                 std::vector<AbstractVertex*> ordered_vert;
438                 //CreateMeshVertexStar(starCenter,ordered_faces,*star_meshes[index].domain);
439                 ///get faces referenced by vertices
440                 getSharedFace<AbstractMesh>(starCenter,ordered_faces);
441 
442                 CopyMeshFromFacesAbs<AbstractMesh>(ordered_faces,ordered_vert,*star_meshes[index].domain);
443 
444                 UpdateTopologies(star_meshes[index].domain);
445 
446                 ///and parametrize it
447                 ParametrizeStarEquilateral<AbstractMesh>(*star_meshes[index].domain,1.0);
448 
449                 ///set other components as reefrence to original faces
450                 star_meshes[index].local_to_global.resize(star_meshes[index].domain->face.size());
451                 std::vector<ParamVertex*> HresVert;
452                 for (unsigned int k=0;k<star_meshes[index].domain->face.size();k++)
453                 {
454                     int IndexF;
455                     getFaceIndexFromPointer(ordered_faces[k],IndexF);
456                     star_meshes[index].local_to_global[k]=IndexF;
457                     ///get H res vertex
458                     GetHresVert(IndexF,HresVert);
459                 }
460 
461                 ///copy Hres mesh
462                 std::vector<ParamVertex*> OrderedVertices;
463                 CopyMeshFromVerticesAbs(HresVert,OrderedVertices,star_meshes[index].ordered_faces,*star_meshes[index].HresDomain);
464                 ///set new parametrization values
465                 for (unsigned int k=0;k<star_meshes[index].HresDomain->vert.size();k++)
466                 {
467                     ParamVertex * v=&star_meshes[index].HresDomain->vert[k];
468                     CoordType bary=CoordType(v->T().U(),v->T().V(),1-v->T().U()-v->T().V());
469                     AbstractMesh *paramDomain=star_meshes[index].domain;
470                     ///get the right face on the parametrized domain
471                     int Father=v->T().N();
472                     int faceNum=-1;
473                     for (unsigned int i=0;i<star_meshes[index].local_to_global.size();i++)
474                     {
475                         if (star_meshes[index].local_to_global[i]==Father)
476                             faceNum=i;
477                     }
478                     AbstractFace *faceDom=&paramDomain->face[faceNum];
479                     v->T().P()=(faceDom->V(0)->T().P())*bary.X()+(faceDom->V(1)->T().P())*bary.Y()+(faceDom->V(2)->T().P())*bary.Z();
480                     assert(faceNum!=-1);
481                 }
482                 star_meshes[index].InitGrid();
483                 index++;
484 
485             }
486         }
487     }
488 
489 
490 
491     void InitDiamond(const PScalarType &edge_len=1.0)
492     {
493 
494         ///for each face
495         int index=0;
496         EdgeTab.clear();
497         for (unsigned int i=0;i<abstract_mesh->face.size();i++)
498         {
499             if (!(abstract_mesh->face[i].IsD()))
500             {
501                 AbstractFace *f0=&abstract_mesh->face[i];
502                 //for each edge
503                 for (int j=0;j<3;j++)
504                 {
505                     AbstractFace * f1=f0->FFp(j);
506                     if (f1>f0)
507                     {
508 
509                         int num0=j;
510                         int num1=f0->FFi(j);
511 
512                         ///add to domain map
513                         AbstractVertex *v0,*v1;
514                         v0=f0->V(j);
515                         v1=f0->V1(j);
516                         keyEdgeType k;
517                         if (v0<v1)
518                             k=keyEdgeType(v0,v1);
519                         else
520                             k=keyEdgeType(v1,v0);
521 
522                         std::pair<keyEdgeType,int> entry=std::pair<keyEdgeType,int>(k,index);
523                         EdgeTab.insert(entry);
524 
525 
526 
527                         ///copy the mesh
528                         std::vector<AbstractFace*> faces;
529                         faces.push_back(f0);
530                         faces.push_back(f1);
531 
532                         diamond_meshes[index].domain=new AbstractMesh();
533                         diamond_meshes[index].HresDomain=new ParamMesh();
534 
535                         ///create a copy of the mesh
536                         std::vector<AbstractVertex*> orderedVertex;
537                         CopyMeshFromFacesAbs<AbstractMesh>(faces,orderedVertex,*diamond_meshes[index].domain);
538                         UpdateTopologies<AbstractMesh>(diamond_meshes[index].domain);
539 
540                         ///set other components
541                         int index0,index1;
542                         getFaceIndexFromPointer(f0,index0);
543                         getFaceIndexFromPointer(f1,index1);
544                         diamond_meshes[index].local_to_global.resize(2);
545                         diamond_meshes[index].local_to_global[0]=index0;
546                         diamond_meshes[index].local_to_global[1]=index1;
547 
548                         ///parametrize locally
549                         ParametrizeDiamondEquilateral<AbstractMesh>(*diamond_meshes[index].domain,num0,num1,edge_len);
550                         ///add h resolution vertices
551                         std::vector<ParamVertex*> HresVert;
552                         GetHresVert(index0,HresVert);
553                         GetHresVert(index1,HresVert);
554                         std::vector<ParamVertex*> OrderedVertices;
555                         CopyMeshFromVerticesAbs(HresVert,OrderedVertices,diamond_meshes[index].ordered_faces,*diamond_meshes[index].HresDomain);
556                         ///set new parametrization values
557                         for (unsigned int k=0;k<diamond_meshes[index].HresDomain->vert.size();k++)
558                         {
559                             ParamVertex * v=&diamond_meshes[index].HresDomain->vert[k];
560                             CoordType bary=CoordType(v->T().U(),v->T().V(),1-v->T().U()-v->T().V());
561                             AbstractMesh *paramDomain=diamond_meshes[index].domain;
562                             ///get the right face on the parametrized domain
563                             int Father=v->T().N();
564                             int faceNum=-1;
565                             for (unsigned int i=0;i<diamond_meshes[index].local_to_global.size();i++)
566                             {
567                                 if (diamond_meshes[index].local_to_global[i]==Father)
568                                     faceNum=i;
569                             }
570                             assert(faceNum!=-1);
571                             AbstractFace *faceDom=&paramDomain->face[faceNum];
572                             v->T().P()=(faceDom->V(0)->T().P())*bary.X()+(faceDom->V(1)->T().P())*bary.Y()+(faceDom->V(2)->T().P())*bary.Z();
573 
574 
575                         }
576                         diamond_meshes[index].InitGrid();
577                         index++;
578                     }
579                 }
580             }
581         }
582     }
583 
584 
585     void InitFace(const PScalarType &edge_len=1)
586     {
587         ///for each face
588         int index=0;
589         for (unsigned int i=0;i<abstract_mesh->face.size();i++)
590         {
591             if (!(abstract_mesh->face[i].IsD()))
592             {
593                 AbstractFace *f0=&abstract_mesh->face[i];
594 
595                 std::vector<AbstractFace*> faces;
596                 faces.push_back(f0);
597 
598                 ///create the mesh
599                 face_meshes[index].domain=new AbstractMesh();
600                 face_meshes[index].HresDomain=new ParamMesh();
601 
602                 std::vector<AbstractVertex*> orderedVertex;
603                 CopyMeshFromFacesAbs<AbstractMesh>(faces,orderedVertex,*face_meshes[index].domain);
604 
605                 assert(face_meshes[index].domain->vn==3);
606                 assert(face_meshes[index].domain->fn==1);
607 
608                 ///initialize auxiliary structures
609                 face_meshes[index].local_to_global.resize(1);
610                 face_meshes[index].local_to_global[0]=i;
611 
612                 ///parametrize it
613                 ParametrizeFaceEquilateral<AbstractMesh>(*face_meshes[index].domain,edge_len);
614 
615                 ///add h resolution vertices
616                 std::vector<ParamVertex*> HresVert;
617                 GetHresVert(index,HresVert);
618                 std::vector<ParamVertex*> OrderedVertices;
619                 CopyMeshFromVerticesAbs(HresVert,OrderedVertices,face_meshes[index].ordered_faces,*face_meshes[index].HresDomain);
620                 ///set new parametrization values
621                 for (unsigned int k=0;k<face_meshes[index].HresDomain->vert.size();k++)
622                 {
623                     ParamVertex * v=&face_meshes[index].HresDomain->vert[k];
624                     CoordType bary=CoordType(v->T().U(),v->T().V(),1-v->T().U()-v->T().V());
625                     AbstractMesh *paramDomain=face_meshes[index].domain;
626                     AbstractFace *faceDom=&paramDomain->face[0];
627                     v->T().P()=(faceDom->V(0)->T().P())*bary.X()+(faceDom->V(1)->T().P())*bary.Y()+(faceDom->V(2)->T().P())*bary.Z();
628                 }
629 
630                 face_meshes[index].InitGrid();
631                 index++;
632             }
633         }
634     }
635 
getFaceIndexFromPointer(AbstractFace * f,int & index)636     void getFaceIndexFromPointer(AbstractFace * f,int &index)
637     {
638       index = vcg::tri::Index(*abstract_mesh,f);
639     }
640 
getStarFromPointer(AbstractVertex * center,int & index)641     void getStarFromPointer(AbstractVertex * center,int &index)
642     {
643         index=center-&(*abstract_mesh->vert.begin());
644     }
645 
getDiamondFromPointer(AbstractVertex * v0,AbstractVertex * v1,int & index)646     void getDiamondFromPointer(AbstractVertex * v0,AbstractVertex * v1,int &index)
647     {
648         assert(v0!=v1);
649         keyEdgeType key;
650         if (v0<v1)
651             key=keyEdgeType(v0,v1);
652         else
653             key=keyEdgeType(v1,v0);
654 
655         std::map<keyEdgeType,int>::iterator k=EdgeTab.find(key);
656         assert(k!=EdgeTab.end());
657         index=((*k).second);
658     }
659 
660 
Test()661     bool Test()
662     {
663         /*int index=0;*/
664         for (unsigned int i=0;i<abstract_mesh->face.size();i++)
665         {
666             if (!(abstract_mesh->face[i].IsD()))
667             {
668                 AbstractFace *f0=&abstract_mesh->face[i];
669                 //for each edge
670                 for (int j=0;j<3;j++)
671                 {
672                     AbstractFace * f1=f0->FFp(j);
673                     if (f1>f0)
674                     {
675                         ///add to domain map
676                         AbstractVertex *v0,*v1;
677                         v0=f0->V(j);
678                         v1=f0->V1(j);
679                         keyEdgeType k;
680                         if (v0<v1)
681                             k=keyEdgeType(v0,v1);
682                         else
683                             k=keyEdgeType(v1,v0);
684 
685                         //std::pair<keyEdgeType,int> entry=std::pair<keyEdgeType,int>(k,index);
686                         std::map<keyEdgeType,int>::iterator iteE=EdgeTab.find(k);
687 
688                         int index0F,index1F;
689                         getFaceIndexFromPointer(f0,index0F);
690                         getFaceIndexFromPointer(f1,index1F);
691 #ifndef NDEBUG
692                         int edgeIndex=(*iteE).second;
693                         assert(diamond_meshes[edgeIndex].local_to_global[0]==index0F);
694                         assert(diamond_meshes[edgeIndex].local_to_global[1]==index1F);
695 #endif
696                     }
697                 }
698             }
699         }
700         ///test if for each face there is a right domain
701         for (unsigned int i=0;i<param_mesh->face.size();i++)
702         {
703             ParamFace * f=&param_mesh->face[i];
704             vcg::Point2f uvI0,uvI1,uvI2;
705             int IndexDomain=-1;
706             int ret=InterpolationSpace(f,uvI0,uvI1,uvI2,IndexDomain);
707             if (ret==-1)
708                 return false;
709         }
710     return true;
711     }
712 
getSharedVertices(AbstractFace * f0,AbstractFace * f1,AbstractFace * f2,AbstractVertex * shared[3])713     int getSharedVertices(AbstractFace *f0,AbstractFace *f1,AbstractFace *f2,
714                           AbstractVertex *shared[3])
715     {
716         AbstractVertex *vert0[3],*vert1[3],*vert2[3];
717 
718         vert0[0]=f0->V(0);
719         vert0[1]=f0->V(1);
720         vert0[2]=f0->V(2);
721 
722         vert1[0]=f1->V(0);
723         vert1[1]=f1->V(1);
724         vert1[2]=f1->V(2);
725 
726         vert2[0]=f2->V(0);
727         vert2[1]=f2->V(1);
728         vert2[2]=f2->V(2);
729 
730         int num=0;
731         for (int i=0;i<3;i++)
732         {
733             AbstractVertex * test=vert0[i];
734             bool found0=false,found1=false;
735             if ((vert1[0]==test)||(vert1[1]==test)||(vert1[2]==test))
736                     found0=true;
737             if (found0)
738             {
739                 if ((vert2[0]==test)||(vert2[1]==test)||(vert2[2]==test))
740                     found1=true;
741             }
742             if ((found0)&&(found1))
743             {
744                 shared[num]=test;
745                 num++;
746             }
747         }
748 
749         return num;
750     }
751 
getSharedVertices(AbstractFace * f0,AbstractFace * f1,AbstractVertex * shared[3])752     int getSharedVertices(AbstractFace *f0,AbstractFace *f1,AbstractVertex *shared[3])
753     {
754         AbstractVertex *vert0[3],*vert1[3];
755 
756         vert0[0]=f0->V(0);
757         vert0[1]=f0->V(1);
758         vert0[2]=f0->V(2);
759 
760         vert1[0]=f1->V(0);
761         vert1[1]=f1->V(1);
762         vert1[2]=f1->V(2);
763 
764 
765         int num=0;
766         for (int i=0;i<3;i++)
767         {
768             AbstractVertex * test=vert0[i];
769             bool found0=false;
770             if ((vert1[0]==test)||(vert1[1]==test)||(vert1[2]==test))
771                     found0=true;
772             if (found0)
773             {
774                 shared[num]=test;
775                 num++;
776             }
777         }
778 
779         return num;
780     }
781 
782     int getSharedVertices(const std::vector<int> &I,AbstractVertex *shared[3],int *_num=NULL)
783     {
784         ///else test the number of vertices shared
785         AbstractVertex * shared_vert[3];
786         bool sharedB[3];
787         int size;
788         if (_num==NULL)
789             size=I.size();
790         else
791             size=*_num;
792 
793         ///quick test for 2 or 3 cases
794         if (size==2)
795             return getSharedVertices(&AbsMesh()->face[I[0]],&AbsMesh()->face[I[1]],shared);
796         else
797         if (size==3)
798             return getSharedVertices(&AbsMesh()->face[I[0]],&AbsMesh()->face[I[1]],&AbsMesh()->face[I[2]],shared);
799 
800         AbstractFace* f0=&AbsMesh()->face[I[0]];
801         AbstractVertex *v0=f0->V(0);
802         AbstractVertex *v1=f0->V(1);
803         AbstractVertex *v2=f0->V(2);
804         shared_vert[0]=v0;
805         shared_vert[1]=v1;
806         shared_vert[2]=v2;
807         sharedB[0]=true;
808         sharedB[1]=true;
809         sharedB[2]=true;
810         //for each face
811         for (int i=1;i<size;i++)
812         {
813             AbstractFace* f=&AbsMesh()->face[I[i]];
814             //for each vertex
815             for (int j=0;j<3;j++)
816             {
817                 if (sharedB[j])
818                 {
819                     AbstractVertex *v_test=shared_vert[j];
820                     if (!((v_test==f->V(0))||(v_test==f->V(1))||(v_test==f->V(2))))
821                         sharedB[j]=false;
822                 }
823             }
824         }
825 
826         ///return vertices correctly
827         int num=0;
828         for (int i=0;i<3;i++)
829             if (sharedB[i])
830             {
831                 shared[num]=shared_vert[i];
832                 num++;
833             }
834         return num;
835     }
836 
837 
Clamp(vcg::Point2f & UV)838     void Clamp(vcg::Point2f &UV)
839     {
840         float eps=0.00001f;
841     if (UV.X() < eps) UV.X()=0;
842     if (UV.X()>1-eps) UV.X()=1;
843     if (UV.Y() < eps) UV.Y()=0;
844     if (UV.Y()>1-eps) UV.Y()=1;
845     if (UV.X()+UV.Y() > 1.) UV.X()=1.-UV.Y();
846     }
847 
848 
849     float Area3d;
850     float AbstractArea;
851 
852 public:
853 
854     ///return the minimum interpolation space shared by a face changing coordinates
855     ///return 0 if is a face 1 is a diamaond and 2 is a star
InterpolationSpace(ParamFace * f,vcg::Point2f & uvI0,vcg::Point2f & uvI1,vcg::Point2f & uvI2,int & IndexDomain)856     int InterpolationSpace(ParamFace *f,
857         vcg::Point2f &uvI0,
858         vcg::Point2f &uvI1,
859         vcg::Point2f &uvI2,
860         int &IndexDomain)
861     {
862         ParamVertex *v0=f->V(0);
863         ParamVertex *v1=f->V(1);
864         ParamVertex *v2=f->V(2);
865 
866         int I0=v0->T().N();
867         int I1=v1->T().N();
868         int I2=v2->T().N();
869 
870         vcg::Point2f UV0=v0->T().P();
871         vcg::Point2f UV1=v1->T().P();
872         vcg::Point2f UV2=v2->T().P();
873 
874         ///if they are equal it's is triavially the interpolation of UV coords
875         ///and the same face I as the domain
876         if ((I0==I1)&&(I1==I2))
877         {
878             GE2(I0,UV0,uvI0);
879             GE2(I1,UV1,uvI1);
880             GE2(I2,UV2,uvI2);
881             IndexDomain=I0;
882             return 0;
883         }
884 
885         ///else find the right interpolation domain in which the face belongs
886         ///test if they share an edge then use half diamond
887         AbstractFace *f0=&abstract_mesh->face[I0];
888         AbstractFace *f1=&abstract_mesh->face[I1];
889         AbstractFace *f2=&abstract_mesh->face[I2];
890         AbstractVertex *shared[3];
891 
892         int num=getSharedVertices(f0,f1,f2,shared);
893         if (num<1)
894         {
895             return -1;
896         }
897         //assert((num==1)||(num==2));
898         if (num==2)///ude diamond
899         {
900             AbstractVertex* v0=shared[0];
901             AbstractVertex* v1=shared[1];
902             int EdgeIndex;
903 
904             getDiamondFromPointer(v0,v1,EdgeIndex);
905 
906             GE1(I0,UV0,EdgeIndex,uvI0);
907             GE1(I1,UV1,EdgeIndex,uvI1);
908             GE1(I2,UV2,EdgeIndex,uvI2);
909 
910             IndexDomain=EdgeIndex;
911             return 1;
912         }
913 
914         ///use the star domain
915 
916         AbstractVertex* center=shared[0];
917         int StarIndex;
918         getStarFromPointer(center,StarIndex);
919         bool b0=GE0(I0,UV0,StarIndex,uvI0);
920         bool b1=GE0(I1,UV1,StarIndex,uvI1);
921         bool b2=GE0(I2,UV2,StarIndex,uvI2);
922         IndexDomain=StarIndex;
923         if ((!b0)||(!b1)||(!b2))
924         {
925             printf("AZZZ 1\n");
926             return -1;
927         }
928         assert((uvI0.X()>=-1)&&(uvI0.Y()>=-1)&&(uvI0.X()<=1)&&(uvI0.Y()<=1));
929         assert((uvI1.X()>=-1)&&(uvI1.Y()>=-1)&&(uvI1.X()<=1)&&(uvI1.Y()<=1));
930         assert((uvI2.X()>=-1)&&(uvI2.Y()>=-1)&&(uvI2.X()<=1)&&(uvI2.Y()<=1));
931 
932 
933 
934         return 2;
935 
936     }
937 
938     ///return the minimum interpolation space shared by two faces of abstarct domain
939     ///return 0 if is a face 1 is a diamaond and 2 is a star
InterpolationSpace(const int & I0,const int & I1,int & IndexDomain)940     int InterpolationSpace(const int &I0,const int &I1,int &IndexDomain)
941     {
942         ///that case is the face itself
943         if (I0==I1)
944         {
945             IndexDomain=I0;
946             return 0;
947         }
948         AbstractFace* f0=&AbsMesh()->face[I0];
949         AbstractFace* f1=&AbsMesh()->face[I1];
950     /*	AbstractVertex *v0=f0->V(0);
951         AbstractVertex *v1=f0->V(1);
952         AbstractVertex *v2=f0->V(2);
953         AbstractVertex *v3=f1->V(0);
954         AbstractVertex *v4=f1->V(1);
955         AbstractVertex *v5=f1->V(2);*/
956 
957 
958         AbstractVertex *shared[3];
959 
960         int num=getSharedVertices(f0,f1,shared);
961         if (!((num==1)||(num==2)))
962             return -1;
963         if (num==2)///use diamond
964         {
965             AbstractVertex* v0=shared[0];
966             AbstractVertex* v1=shared[1];
967             int EdgeIndex;
968 
969             getDiamondFromPointer(v0,v1,EdgeIndex);
970 
971             IndexDomain=EdgeIndex;
972             return 1;
973         }
974 
975         ///use the star domain
976 
977         AbstractVertex* center=shared[0];
978         int StarIndex;
979         getStarFromPointer(center,StarIndex);
980         IndexDomain=StarIndex;
981 
982         return 2;
983 
984     }
985 
986     ///return 0 if is a face 1 is a diamaond and 2 is a star
987     int InterpolationSpace(const std::vector<int> &I,int &IndexDomain,int *_num=NULL)
988     {
989         int size;
990         if (_num==NULL)
991             size=I.size();
992         else
993             size=*_num;
994 
995         ///simple cases
996         assert(I.size()>0);
997         ///1 element
998         if (size==1)
999         {
1000             IndexDomain=I[0];
1001             return 0;
1002         }
1003         ///2 elements
1004         if (size==2)
1005             return InterpolationSpace(I[0],I[1],IndexDomain);
1006 
1007         ///test if they all are the same
1008         ///that case is the face itself
1009         bool sameface=true;
1010         int i=1;
1011         int I0=I[0];
1012         while ((i<size)&&(sameface))
1013         {
1014             sameface&=(I[i]==I0);
1015             i++;
1016         }
1017         if (sameface)
1018         {
1019             IndexDomain=I0;
1020             return 0;
1021         }
1022 
1023         ///else test the number of vertices shared
1024         AbstractVertex *shared[3];
1025         int num=getSharedVertices(I,shared,_num);
1026         assert(num!=3); ///no same yet face possible
1027         if (num==0)
1028             return -1;  ///no interpolation space exists
1029 
1030         if (num==2)///ude diamond
1031         {
1032             AbstractVertex* v0=shared[0];
1033             AbstractVertex* v1=shared[1];
1034             int EdgeIndex;
1035 
1036             getDiamondFromPointer(v0,v1,EdgeIndex);
1037 
1038             IndexDomain=EdgeIndex;
1039             return 1;
1040         }
1041 
1042         ///use the star domain
1043 
1044         AbstractVertex* center=shared[0];
1045         int StarIndex;
1046         getStarFromPointer(center,StarIndex);
1047         IndexDomain=StarIndex;
1048 
1049         return 2;
1050 
1051     }
1052 
getHStarIndex(const int & I,const vcg::Point2<PScalarType> & UV)1053     int getHStarIndex(const int &I,
1054         const vcg::Point2<PScalarType> &UV)
1055     {
1056         int vertStar=2;
1057         CoordType bary=CoordType(UV.X(),UV.Y(),(PScalarType)1.0-UV.X()-UV.Y());
1058 
1059         if ((bary.X()>bary.Y())&&(bary.X()>bary.Z()))
1060             vertStar=0;
1061         else
1062             if ((bary.Y()>bary.X())&&(bary.Y()>bary.Z()))
1063                 vertStar=1;
1064 
1065         AbstractFace *f=&abstract_mesh->face[I];
1066         AbstractVertex *Center=f->V(vertStar);
1067 
1068         int StarIndex;
1069         getStarFromPointer(Center,StarIndex);
1070         return StarIndex;
1071     }
1072 
getHDiamIndex(const int & I,const vcg::Point2<PScalarType> & UV)1073     int getHDiamIndex(const int &I,
1074         const vcg::Point2<PScalarType> &UV)
1075     {
1076         CoordType bary=CoordType(UV.X(),UV.Y(),1-UV.X()-UV.Y());
1077         PScalarType sum0=bary.X()+bary.Y();
1078         PScalarType sum1=bary.Y()+bary.Z();
1079         PScalarType sum2=bary.X()+bary.Z();
1080         int edge=2;
1081         if ((sum0>sum1)&&(sum0>sum2))
1082             edge=0;
1083         else
1084             if ((sum1>sum0)&&(sum1>sum2))
1085                 edge=1;
1086 
1087         ///get the half-diamond mesh
1088         int DiamIndex;
1089         getDiamondFromPointer(abstract_mesh->face[I].V(edge),abstract_mesh->face[I].V1(edge),DiamIndex);
1090         return(DiamIndex);
1091     }
1092 
1093     ///give the face and barycentric coordinate return I and UV coordinates
Phi(const ParamFace * f,const CoordType & bary3D,int & I,vcg::Point2<PScalarType> & UV)1094     void Phi(const ParamFace *f,
1095         const CoordType &bary3D,
1096         int &I,
1097         vcg::Point2<PScalarType> &UV)
1098     {
1099 #ifndef NDEBUG
1100         float eps=0.00001f;
1101 #endif
1102         ///control right domain
1103         int I0=f->cV(0)->T().N();
1104         int I1=f->cV(1)->T().N();
1105         int I2=f->cV(2)->T().N();
1106 
1107         ///if they are equal it's is triavially the interpolation of UV coords
1108         ///and the same face I as the domain
1109         if ((I0==I1)&&(I1==I2))
1110         {
1111             UV=bary3D.X()*f->cV(0)->T().P()+bary3D.Y()*f->cV(1)->T().P()+bary3D.Z()*f->cV(2)->T().P();
1112             Clamp(UV);
1113             assert((UV.X()>=0)&&(UV.Y()>=0)&&(UV.X()<=1)&&(UV.Y()<=1)&&(UV.X()+UV.Y()<=1));
1114             I=I0;
1115             return;
1116         }
1117 
1118 
1119         ///else find the right interpolation domain in which the face belongs
1120         ///test if they share an edge then use half diamond
1121         AbstractFace *f0=&abstract_mesh->face[I0];
1122         AbstractFace *f1=&abstract_mesh->face[I1];
1123         AbstractFace *f2=&abstract_mesh->face[I2];
1124         AbstractVertex *shared[3];
1125 
1126         int num=getSharedVertices(f0,f1,f2,shared);
1127 
1128         /*///if num==1
1129         if (num==0)
1130         {
1131             float alpha=bary3D.X();
1132             float beta =bary3D.Y();
1133             float gamma=bary3D.Z();
1134 #ifndef _MESHLAB
1135             printf("problems with interpolation, solved...");
1136 #endif
1137             if ((alpha>beta)&&(alpha>gamma))
1138             {
1139                 I=I0;
1140                 UV=f->V(0)->T().P();
1141             }
1142             else
1143             if ((beta>alpha)&&(beta>gamma))
1144             {
1145                 I=I1;
1146                 UV=f->V(1)->T().P();
1147             }
1148             else
1149             {
1150                 I=I2;
1151                 UV=f->V(2)->T().P();
1152             }
1153 
1154             return;
1155         }*/
1156 
1157         assert((num==1)||(num==2));
1158         if ((num!=1)&&(num!=2))
1159         {
1160             printf("DOMAIN %d\n",num);
1161             assert(0);
1162         }
1163         if (num==1)///use the star domain
1164         {
1165             //printf("phi 0\n");
1166             AbstractVertex* center=shared[0];
1167             int StarIndex;
1168             getStarFromPointer(center,StarIndex);
1169             vcg::Point2<PScalarType> UVs0,UVs1,UVs2;
1170             vcg::Point2<PScalarType> UV0=f->cV(0)->T().P();
1171             vcg::Point2<PScalarType> UV1=f->cV(1)->T().P();
1172             vcg::Point2<PScalarType> UV2=f->cV(2)->T().P();
1173 
1174             GE0(I0,UV0,StarIndex,UVs0);
1175             GE0(I1,UV1,StarIndex,UVs1);
1176             GE0(I2,UV2,StarIndex,UVs2);
1177             assert((UVs0.X()>=-1)&&(UVs0.Y()>=-1)&&(UVs0.X()<=1)&&(UVs0.Y()<=1));
1178             assert((UVs1.X()>=-1)&&(UVs1.Y()>=-1)&&(UVs1.X()<=1)&&(UVs1.Y()<=1));
1179             assert((UVs2.X()>=-1)&&(UVs2.Y()>=-1)&&(UVs2.X()<=1)&&(UVs2.Y()<=1));
1180 
1181             ///interpolate star value
1182             vcg::Point2<PScalarType> UV_interp=bary3D.X()*UVs0+bary3D.Y()*UVs1+bary3D.Z()*UVs2;
1183             inv_GE0(StarIndex,UV_interp,I,UV);
1184             Clamp(UV);
1185             assert((UV.X()>=0)&&(UV.Y()>=0)&&(UV.X()<=1)&&(UV.Y()<=1)&&(UV.X()+UV.Y()<=1+eps));
1186             return;
1187         }
1188         else			///use the diamond domain
1189         {
1190             //printf("phi 1\n");
1191             //std::set<AbstractVertex*>::iterator it=temp2.begin();
1192             //std::vector<AbstractVertex*>::iterator it=shared[0];
1193             AbstractVertex* v0=shared[0];
1194             //it++;
1195             AbstractVertex* v1=shared[1];
1196             int EdgeIndex;
1197             getDiamondFromPointer(v0,v1,EdgeIndex);
1198 
1199             vcg::Point2<PScalarType> UVd0,UVd1,UVd2;
1200             vcg::Point2<PScalarType> UV0=f->cV(0)->T().P();
1201             vcg::Point2<PScalarType> UV1=f->cV(1)->T().P();
1202             vcg::Point2<PScalarType> UV2=f->cV(2)->T().P();
1203 
1204             GE1(I0,UV0,EdgeIndex,UVd0);
1205             GE1(I1,UV1,EdgeIndex,UVd1);
1206             GE1(I2,UV2,EdgeIndex,UVd2);
1207 
1208             ///interpolate star value
1209             vcg::Point2<PScalarType> UV_interp=bary3D.X()*UVd0+bary3D.Y()*UVd1+bary3D.Z()*UVd2;
1210             inv_GE1(EdgeIndex,UV_interp,I,UV);
1211             Clamp(UV);
1212       //assert((UV.X()>=0)&&(UV.Y()>=0)&&(UV.X()<=1)&&(UV.Y()<=1)&&(UV.X()+UV.Y()<=1+eps));
1213             assert((I==I0)||(I==I1)||(I==I2));
1214             return;
1215         }
1216 
1217     }
1218 
1219     ///given the I and UV coordinates return the face and barycentric coords
1220     ///return the domain used for interpolation 0=face 1=half diam 2=half star
Theta(const int & I,const vcg::Point2<PScalarType> & UV,std::vector<ParamFace * > & face,std::vector<CoordType> & baryVal)1221     int Theta(const int &I,
1222         const vcg::Point2<PScalarType> &UV, // alphaBeta
1223         std::vector<ParamFace*> &face,
1224         std::vector<CoordType> &baryVal)
1225     {
1226         #ifndef NDEBUG
1227         const PScalarType eps=(PScalarType)0.0001;
1228         #endif
1229         assert(UV.X()<=1);
1230         assert(UV.Y()<=1);
1231         assert(UV.X()>=0);
1232         assert(UV.Y()>=0);
1233         //printf("%f,%f \n",UV.X(),UV.Y());
1234         assert((UV.X()+UV.Y())<=(1+eps));
1235 
1236         //printf("%f,%f \n",UV.X(),UV.Y());
1237         ///FACE SEARCH
1238         ///first test if is in the face domain
1239         //printf("face\n");
1240         bool found=false;
1241         int indexFace=I;
1242         /*if (indexFace>=face_meshes.size())
1243             printf("B");*/
1244 
1245         vcg::Point2<PScalarType> UVFace;
1246         GE2(indexFace,UV,UVFace);
1247         found=face_meshes[indexFace].Project(UVFace,face,baryVal);
1248         if (found)
1249             return 0;
1250 
1251         ///DIAMOND SEARCH
1252         ///search in the diamond domain
1253         //printf("diam\n");
1254         int indexDiam=getHDiamIndex(I,UV);///get diamond index
1255         vcg::Point2<PScalarType> UVDiam;
1256         ///transform UV coordids in diamond
1257         GE1(I,UV,indexDiam,UVDiam);
1258         /*if (indexDiam>=diamond_meshes.size())*/
1259             /*printf("C");*/
1260         found=diamond_meshes[indexDiam].Project(UVDiam,face,baryVal);
1261         if (found)
1262             return 1;
1263 
1264         ///STAR SEARCH
1265         //printf("star\n");
1266         int indexStar=getHStarIndex(I,UV);///get star index
1267         vcg::Point2<PScalarType> UVStar;
1268         ///transform UV coords in star
1269         GE0(I,UV,indexStar,UVStar);
1270         found=star_meshes[indexStar].Project(UVStar,face,baryVal);
1271         if (!found)
1272         {
1273             //printf("\n problems projecting u,v:%lf,%lf (RESOLVED)\n",UV.X(),UV.Y());
1274 #ifndef NDEBUG
1275             bool found=star_meshes[indexStar].getClosest(UVStar,face,baryVal);
1276             assert(found);
1277 #else
1278             star_meshes[indexStar].getClosest(UVStar,face,baryVal);
1279             /*printf("D");*/
1280 #endif
1281         }
1282         return 2;
1283     }
1284 
1285     ///given the I and UV coordinates return the face and barycentric coords
1286     ///return the domain used for interpolation 0=face 1=half diam 2=half star
Theta(const int & I,const vcg::Point2<PScalarType> & UV,ParamFace * & face,CoordType & baryVal)1287     int Theta(const int &I,
1288         const vcg::Point2<PScalarType> &UV, // alphaBeta
1289         ParamFace* &face,
1290         CoordType &baryVal)
1291     {
1292         std::vector<ParamFace*> faces;
1293         std::vector<CoordType>  baryVals;
1294         int ret=Theta(I,UV,faces,baryVals);
1295         if (ret!=-1)
1296         {
1297             face=faces[0];
1298             baryVal=baryVals[0];
1299         }
1300         return ret;
1301     }
1302 
1303     ///given the I and UV coordinates return the face and barycentric coords
1304     ///return the domain used for interpolation 0=face 1=half diam 2=half star
1305     ///and 3D Coordinates
Theta(const int & I,const vcg::Point2<PScalarType> & UV,CoordType & pos3D)1306     int Theta(const int &I,
1307         const vcg::Point2<PScalarType> &UV,
1308         CoordType &pos3D)
1309     {
1310         std::vector<ParamFace*> face;
1311         std::vector<CoordType> baryVal;
1312 
1313         int ret=Theta(I,UV,face,baryVal);
1314 
1315         pos3D=CoordType(0,0,0);
1316         for (int i=0;i<(int)face.size();i++)
1317         {
1318             CoordType pos=face[i]->V(0)->P()*baryVal[i].X()+
1319                           face[i]->V(1)->P()*baryVal[i].Y()+
1320                           face[i]->V(2)->P()*baryVal[i].Z();
1321             pos3D+=pos;
1322         }
1323 
1324         pos3D/=(PScalarType)face.size();
1325         return ret;
1326     }
1327 
1328     ///return the coordinate on the half star domain
GE0(const int & I,const vcg::Point2<PScalarType> & UV,const int & StarIndex,vcg::Point2<PScalarType> & UVHstar)1329     bool GE0(const int &I,
1330         const vcg::Point2<PScalarType> &UV,
1331         const int &StarIndex,
1332         vcg::Point2<PScalarType> &UVHstar)
1333     {
1334         //int vertStar=2;
1335         CoordType bary=CoordType(UV.X(),UV.Y(),1-UV.X()-UV.Y());
1336 
1337         ///then transform to the star domain
1338 
1339         ///get star mesh
1340         AbstractMesh* star_domain=star_meshes[StarIndex].domain;
1341         int LocalIndex=star_meshes[StarIndex].Global2Local(I);
1342         if (LocalIndex==-1)
1343             return false;
1344 
1345     InterpolateUV<AbstractMesh>(&star_domain->face[LocalIndex],bary,UVHstar.X(),UVHstar.Y());
1346         return true;
1347     }
1348 
1349     ///return the coordinate on the half star domain
inv_GE0(int & StarIndex,vcg::Point2<PScalarType> & UVHstar,int & I,vcg::Point2<PScalarType> & UV)1350     bool inv_GE0(int &StarIndex,
1351         vcg::Point2<PScalarType> &UVHstar,
1352         int &I,
1353         vcg::Point2<PScalarType> &UV)
1354     {
1355         AbstractMesh* star_domain=star_meshes[StarIndex].domain;
1356         CoordType bary;
1357         int index;
1358         bool done=GetBaryFaceFromUV(*star_domain,UVHstar.X(),UVHstar.Y(),bary,index);
1359         if (!done)
1360             return false;
1361         UV.X()=bary.X();
1362         UV.Y()=bary.Y();
1363         I=star_meshes[StarIndex].Local2Global(index);
1364         return done;
1365     }
1366 
1367 
InterpParam(vcg::Point2f p1,vcg::Point2f p2,vcg::Point2f p3,vcg::Point2f p_test,PScalarType & b1,PScalarType & b2,PScalarType & b3)1368     void InterpParam(vcg::Point2f p1,vcg::Point2f p2,vcg::Point2f p3,vcg::Point2f p_test,
1369                      PScalarType &b1,PScalarType &b2,PScalarType &b3)
1370     {
1371         PScalarType x0=p_test.X();
1372         PScalarType y0=p_test.Y();
1373         PScalarType x1=p1.X();
1374         PScalarType y1=p1.Y();
1375         PScalarType x2=p2.X();
1376         PScalarType y2=p2.Y();
1377         PScalarType x3=p3.X();
1378         PScalarType y3=p3.Y();
1379 
1380         PScalarType b0 =  (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
1381         b1 = ((x2 - x0) * (y3 - y0) - (x3 - x0) * (y2 - y0)) / b0;
1382         b2 = ((x3 - x0) * (y1 - y0) - (x1 - x0) * (y3 - y0)) / b0;
1383         b3 = ((x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0)) / b0;
1384     }
1385 
1386     ///return the coordinate on the half diamond domain
GE1(const int & I,const vcg::Point2<PScalarType> & UV,const int & DiamIndex,vcg::Point2<PScalarType> & UVDiam)1387     void GE1(const int &I,
1388         const vcg::Point2<PScalarType> &UV,
1389         const int &DiamIndex,
1390         vcg::Point2<PScalarType> &UVDiam)
1391     {
1392         ///get the right edge index
1393         CoordType bary=CoordType(UV.X(),UV.Y(),1-UV.X()-UV.Y());
1394 
1395         ///then transform to the half-diamond domain
1396         ///get edge mesh
1397         AbstractMesh* diam_domain=diamond_meshes[DiamIndex].domain;
1398         int LocalIndex=diamond_meshes[DiamIndex].Global2Local(I);
1399         if(LocalIndex!=-1)
1400         {
1401       InterpolateUV<AbstractMesh>(&diam_domain->face[LocalIndex],bary,UVDiam.X(),UVDiam.Y());
1402             return;
1403         }
1404         ///if ! found search in the star space
1405         else
1406         {
1407             AbstractFace *f_diam=&diam_domain->face[0];
1408             int indexF0=diamond_meshes[DiamIndex].Local2Global(0);
1409             int indexF1=diamond_meshes[DiamIndex].Local2Global(1);
1410 
1411             //getFaceIndexFromPointer(f0,indexF0);
1412             vcg::Point2<PScalarType> UVHstar;
1413             //int StarIndex=getHStarIndex(I,UV);
1414             int StarIndex=getHStarIndex(I,UV);
1415             ///get star coordinates
1416 #ifndef NDEBUG
1417             bool found=GE0(I,UV,StarIndex,UVHstar);
1418             assert(found);
1419 #else
1420             GE0(I,UV,StarIndex,UVHstar);
1421 #endif
1422 
1423             ///then find which face is in the star
1424             int indexParam;
1425             int indexParam0=star_meshes[StarIndex].Global2Local(indexF0);
1426             int indexParam1=star_meshes[StarIndex].Global2Local(indexF1);
1427             if(indexParam0==-1)
1428                 indexParam=indexParam1;
1429             else
1430                 indexParam=indexParam0;
1431 
1432             AbstractFace *f_param=&star_meshes[StarIndex].domain->face[indexParam];
1433             vcg::Point2f p0=f_param->V(0)->T().P();
1434             vcg::Point2f p1=f_param->V(1)->T().P();
1435             vcg::Point2f p2=f_param->V(2)->T().P();
1436 
1437             vcg::Point3f coord;
1438             //bool inside=vcg::InterpolationParameters2<float>(p0,p1,p2,UVHstar,coord);
1439             InterpParam(p0,p1,p2,UVHstar,coord.X(),coord.Y(),coord.Z());
1440             ///finally reinterpolate in diamond space
1441             UVDiam=coord.X()*f_diam->V(0)->T().P()+coord.Y()*f_diam->V(1)->T().P()+coord.Z()*f_diam->V(2)->T().P();
1442             return;
1443         }
1444         //CoordType bary=CoordType(UV.X(),UV.Y(),1-UV.X()-UV.Y());
1445 
1446     }
1447 
1448     ///given the diamond coordinates return the coordinates in the parametrization space
inv_GE1(const int & DiamIndex,const vcg::Point2<PScalarType> & UVDiam,int & I,vcg::Point2<PScalarType> & UV)1449     void inv_GE1(const int &DiamIndex,
1450         const vcg::Point2<PScalarType> &UVDiam,
1451         int &I,
1452         vcg::Point2<PScalarType> &UV)
1453     {
1454         AbstractMesh* diam_domain=diamond_meshes[DiamIndex].domain;
1455         CoordType bary;
1456         int index;
1457 #ifndef NDEBUG
1458         bool done=GetBaryFaceFromUV(*diam_domain,UVDiam.X(),UVDiam.Y(),bary,index);
1459         assert(done);
1460 #else
1461         GetBaryFaceFromUV(*diam_domain,UVDiam.X(),UVDiam.Y(),bary,index);
1462 #endif
1463         UV.X()=bary.X();
1464         UV.Y()=bary.Y();
1465         I=diamond_meshes[DiamIndex].Local2Global(index);
1466 
1467     }
1468 
1469     ///given the diamond coordinates return the coordinates in the parametrization space
1470     ///in this case I is fixed and should falls also outside the face I
inv_GE1_fixedI(const int & DiamIndex,const vcg::Point2<PScalarType> & UVDiam,const int & I,vcg::Point2<PScalarType> & bary)1471     void inv_GE1_fixedI(const int &DiamIndex,
1472         const vcg::Point2<PScalarType> &UVDiam,
1473         const int &I,
1474         vcg::Point2<PScalarType> &bary)
1475     {
1476         /*AbstractMesh* diam_domain=diamond_meshes[DiamIndex].domain;*/
1477         //int index;
1478         CoordType bary3d;
1479         ///then find barycentryc coordinates with respect to such face
1480         int local_face=diamond_meshes[DiamIndex].Global2Local(I);
1481         AbstractFace* f=&diamond_meshes[DiamIndex].domain->face[local_face];
1482         vcg::Point2<PScalarType> p0=f->V(0)->T().P();
1483         vcg::Point2<PScalarType> p1=f->V(1)->T().P();
1484         vcg::Point2<PScalarType> p2=f->V(2)->T().P();
1485         InterpParam(p0,p1,p2,UVDiam,bary3d.X(),bary3d.Y(),bary3d.Z());
1486         bary.X()=bary3d.X();
1487         bary.Y()=bary3d.Y();
1488     }
1489 
1490     ///given the star return the coordinates in the parametrization space
1491     ///in this case I is fixed and should falls also outside the face I
inv_GE0_fixedI(const int & StarIndex,const vcg::Point2<PScalarType> & UVStar,const int & I,vcg::Point2<PScalarType> & bary)1492     void inv_GE0_fixedI(const int &StarIndex,
1493         const vcg::Point2<PScalarType> &UVStar,
1494         const int &I,
1495         vcg::Point2<PScalarType> &bary)
1496     {
1497         //AbstractMesh* star_domain=star_meshes[StarIndex].domain;
1498         /*int index;*/
1499         CoordType bary3d;
1500         ///then find barycentryc coordinates with respect to such face
1501         int local_face=star_meshes[StarIndex].Global2Local(I);
1502         AbstractFace* f=&star_meshes[StarIndex].domain->face[local_face];
1503         vcg::Point2<PScalarType> p0=f->V(0)->T().P();
1504         vcg::Point2<PScalarType> p1=f->V(1)->T().P();
1505         vcg::Point2<PScalarType> p2=f->V(2)->T().P();
1506         InterpParam(p0,p1,p2,UVStar,bary3d.X(),bary3d.Y(),bary3d.Z());
1507         bary.X()=bary3d.X();
1508         bary.Y()=bary3d.Y();
1509     }
1510 
1511     ///given the diamond coordinates AS A QUAD return the coordinates in the parametrization space
inv_GE1Quad(const int & DiamIndex,const vcg::Point2<PScalarType> & UVQuad,int & I,vcg::Point2<PScalarType> & UV)1512     void inv_GE1Quad(const int &DiamIndex,
1513                     const vcg::Point2<PScalarType> &UVQuad,
1514                     int &I,
1515                     vcg::Point2<PScalarType> &UV)
1516     {
1517         assert((UVQuad.X()>=0)&&(UVQuad.X()<=1));
1518         assert((UVQuad.Y()>=0)&&(UVQuad.Y()<=1));
1519 
1520         ///get the abstract mesh
1521         AbstractMesh* diam_domain=diamond_meshes[DiamIndex].domain;
1522         ///get the 4 vertices on the full diamond
1523 
1524         ///transform in diamond coordinates
1525         vcg::Point2<PScalarType> c0=vcg::Point2<PScalarType>(0,(PScalarType)-0.5);
1526         vcg::Point2<PScalarType> c1=vcg::Point2<PScalarType>((sqrt((PScalarType)3.0)/(PScalarType)6.0),0);
1527 //		vcg::Point2<PScalarType> c2=vcg::Point2<PScalarType>(0,(PScalarType)0.5);
1528         vcg::Point2<PScalarType> c3=vcg::Point2<PScalarType>(-(sqrt((PScalarType)3.0)/(PScalarType)6.0),0);
1529 
1530         ///get 2 directions
1531         vcg::Point2<PScalarType> v0=c1-c0;
1532         //v0.Normalize();
1533         vcg::Point2<PScalarType> v1=c3-c0;
1534         //v1.Normalize();
1535 
1536         ///value in diamond coordinates
1537         vcg::Point2<PScalarType> UVDiam=c0+UVQuad.X()*v0;
1538         vcg::Point2<PScalarType> diry=UVQuad.Y()*v1;
1539         UVDiam=UVDiam+diry;
1540 
1541         //printf("Diamond: %d,%f,%f \n",DiamIndex,UVDiam.X(),UVDiam.Y());
1542 
1543         int index;
1544         CoordType bary;
1545 #ifndef NDEBUG
1546         bool done=GetBaryFaceFromUV(*diam_domain,UVDiam.X(),UVDiam.Y(),bary,index);
1547 #else
1548         GetBaryFaceFromUV(*diam_domain,UVDiam.X(),UVDiam.Y(),bary,index);
1549 #endif
1550         UV.X()=bary.X();
1551         UV.Y()=bary.Y();
1552 
1553         I=diamond_meshes[DiamIndex].Local2Global(index);
1554         assert(done);
1555     }
1556 
1557     ///TO RESCALE?
1558     ///given the coordinates in the parametrization space return return the coordinates AS A QUAD
GE1Quad(const int & I,const vcg::Point2<PScalarType> & UV,int & DiamIndex,vcg::Point2<PScalarType> & UVQuad)1559     void GE1Quad(const int &I,
1560                  const vcg::Point2<PScalarType> &UV,
1561                  int &DiamIndex,
1562                  vcg::Point2<PScalarType> &UVQuad)
1563     {
1564         ///first get the right half diamond index
1565         DiamIndex=getHDiamIndex(I,UV);
1566 
1567         ///transform in diamond space
1568         vcg::Point2<PScalarType> UVDiam;
1569         GE1(I,UV,DiamIndex,UVDiam);
1570 
1571         ///transform in diamond coordinates
1572         vcg::Point2<PScalarType> c0=vcg::Point2<PScalarType>(0,(PScalarType)-0.5);
1573         vcg::Point2<PScalarType> c1=vcg::Point2<PScalarType>((sqrt((PScalarType)3.0)/(PScalarType)6.0),0);
1574 //		vcg::Point2<PScalarType> c2=vcg::Point2<PScalarType>(0,(PScalarType)0.5);
1575         vcg::Point2<PScalarType> c3=vcg::Point2<PScalarType>(-(sqrt((PScalarType)3.0)/(PScalarType)6.0),0);
1576 
1577         ///get 2 directions
1578         vcg::Point2<PScalarType> v0=c1-c0;
1579         //v0.Normalize();
1580         vcg::Point2<PScalarType> v1=c3-c0;
1581         //v1.Normalize();
1582 
1583         ///translate respect to zero
1584         UVDiam-=c0;
1585 
1586         ///then transform in new coordspace
1587         UVQuad.X()=v0.X()*UVDiam.X()+v0.Y()*UVDiam.Y();
1588         UVQuad.Y()=v1.X()*UVDiam.X()+v1.Y()*UVDiam.Y();
1589 
1590     }
1591 
1592     ///given the diamond coordinates return return the coordinates AS A QUAD
GE1Quad(const int &,const vcg::Point2<PScalarType> & UVDiam,vcg::Point2<PScalarType> & UVQuad)1593     void GE1Quad(const int &/*DiamIndex*/,
1594                  const vcg::Point2<PScalarType> &UVDiam,
1595                  vcg::Point2<PScalarType> &UVQuad)
1596     {
1597         //assert(UVDiam.Y()<0);
1598         ///transform in diamond coordinates
1599         vcg::Point2<PScalarType> c0=vcg::Point2<PScalarType>(0,(PScalarType)-0.5);
1600         vcg::Point2<PScalarType> c1=vcg::Point2<PScalarType>((sqrt((PScalarType)3.0)/(PScalarType)6.0),0);
1601 //		vcg::Point2<PScalarType> c2=vcg::Point2<PScalarType>(0,(PScalarType)0.5);
1602         vcg::Point2<PScalarType> c3=vcg::Point2<PScalarType>(-(sqrt((PScalarType)3.0)/(PScalarType)6.0),0);
1603 
1604         ///get 2 directions
1605         vcg::Point2<PScalarType> v0=c1-c0;
1606         vcg::Point2<PScalarType> v1=c3-c0;
1607 
1608         ///translate respect to zero
1609         vcg::Point2<PScalarType> temp=UVDiam;
1610         //temp=c3;
1611         temp-=c0;
1612         PScalarType det=(PScalarType)1.0/(v0.X()*v1.Y()-v1.X()*v0.Y());
1613         ///then transform in new coordspace
1614         UVQuad.X()=v1.Y()*temp.X()-v1.X()*temp.Y();
1615         UVQuad.Y()=-v0.Y()*temp.X()+v0.X()*temp.Y();
1616         UVQuad.X()*=det;
1617         UVQuad.Y()*=det;
1618     /*	printf("UVtr1=%f, %f \n",UVQuad.X(),UVQuad.Y());
1619         system("pause");*/
1620     }
1621 
1622     ///return the coordinate on the face domain
GE2(const int & I,const vcg::Point2<PScalarType> & UV,vcg::Point2<PScalarType> & UVFace)1623     void GE2(const int &I,
1624         const vcg::Point2<PScalarType> &UV,
1625         vcg::Point2<PScalarType> &UVFace)
1626     {
1627         ///get the right edge index
1628         CoordType bary=CoordType(UV.X(),UV.Y(),1-UV.X()-UV.Y());
1629 
1630         ///then transform to the face domain
1631         ///get face mesh
1632         AbstractMesh* face_domain=face_meshes[I].domain;
1633         AbstractFace* f=&(face_domain->face[0]);
1634 
1635         UVFace=bary.X()*f->V(0)->T().P()+bary.Y()*f->V(1)->T().P()+bary.Z()*f->V(2)->T().P();
1636     }
1637 
1638     ///given the face coordinates return the coordinates in the parametrization space
inv_GE2(const int & FaceIndex,const vcg::Point2<PScalarType> & UVFace,vcg::Point2<PScalarType> & UV)1639     void inv_GE2(const int &FaceIndex,
1640         const vcg::Point2<PScalarType> &UVFace,
1641         vcg::Point2<PScalarType> &UV)
1642     {
1643         AbstractMesh* face_domain=face_meshes[FaceIndex].domain;
1644         CoordType bary;
1645         int index;
1646 #ifndef NDEBUG
1647         bool done=GetBaryFaceFromUV(*face_domain,UVFace.X(),UVFace.Y(),bary,index);
1648         assert(done);
1649 #else
1650         GetBaryFaceFromUV(*face_domain,UVFace.X(),UVFace.Y(),bary,index);
1651 #endif
1652         UV.X()=bary.X();
1653         UV.Y()=bary.Y();
1654 
1655     }
1656 
Clear()1657     void Clear()
1658     {
1659         face_to_vert.clear();
1660         star_meshes.clear();
1661         face_meshes.clear();
1662         diamond_meshes.clear();
1663     }
1664 
1665     bool Update(bool test=true)
1666     {
1667         UpdateTopologies(abstract_mesh);
1668         UpdateTopologies(param_mesh);
1669         int nonmanif = vcg::tri::Clean<AbstractMesh>::CountNonManifoldEdgeFF(*abstract_mesh);
1670         if(nonmanif>0)
1671           return false;
1672         int edge_count = abstract_mesh->FN()*3 / 2;
1673 
1674         ///test param mesh
1675         for (unsigned int i=0;i<param_mesh->vert.size();i++)
1676         {
1677             if (!(param_mesh->vert[i].IsD()))
1678             {
1679                 ParamVertex *v0=&param_mesh->vert[i];
1680                 ParamMesh::CoordType bary=ParamMesh::CoordType(v0->T().U(),v0->T().V(),1-v0->T().U()-v0->T().V());
1681                 int patchNum=v0->T().N();
1682                 if (!testBaryCoords(bary))
1683                     return false;
1684                 if (patchNum<0)
1685                     return false;
1686                 if (patchNum>AbsMesh()->fn)
1687                     return false;
1688             }
1689         }
1690         Area3d=vcg::tri::Stat<ParamMesh>::ComputeMeshArea(*param_mesh);
1691 
1692         float fix_num=sqrt((PScalarType)3.0)/(PScalarType)4.0;
1693         AbstractArea=(PScalarType)abstract_mesh->fn*fix_num;
1694 
1695         face_to_vert.clear();
1696         star_meshes.clear();
1697         face_meshes.clear();
1698         diamond_meshes.clear();
1699         star_meshes.resize(abstract_mesh->vn);
1700         face_meshes.resize(abstract_mesh->fn);
1701         diamond_meshes.resize(edge_count);
1702         InitFaceToVert();
1703         InitFace();
1704         InitDiamond();
1705         InitStar();
1706         if (test)
1707             return (Test());
1708         return true;
1709     }
1710 
1711     bool Init(AbstractMesh * _abstract_mesh,
1712               ParamMesh	 * _param_mesh,bool test=true)
1713     {
1714 
1715         abstract_mesh=_abstract_mesh;
1716         param_mesh=_param_mesh;
1717 
1718         UpdateTopologies(abstract_mesh);
1719         UpdateTopologies(param_mesh);
1720 
1721         return (Update(test));
1722     }
1723 
AbsMesh()1724     AbstractMesh *&AbsMesh(){return abstract_mesh;}
ParaMesh()1725     ParamMesh	 *&ParaMesh(){return param_mesh;}
1726 
1727     ///given the index of face and the index of the edge return the
1728     ///index of diamond
GetDiamond(const int & I,const int & edge)1729     int GetDiamond(const int &I,const int & edge)
1730     {
1731         AbstractVertex *v0=AbsMesh()->face[I].V0(edge);
1732         AbstractVertex *v1=AbsMesh()->face[I].V1(edge);
1733         int index;
1734         getDiamondFromPointer(v0,v1,index);
1735         return index;
1736     }
1737 
GetStarIndex(const int & I,const int & indexV)1738     int GetStarIndex(const int &I,const int & indexV)
1739     {
1740         AbstractVertex *v=AbsMesh()->face[I].V(indexV);
1741         int index;
1742         getStarFromPointer(v,index);
1743         return index;
1744     }
1745 
SaveBaseDomain(const char * pathname)1746     void SaveBaseDomain(const char *pathname)
1747     {
1748         /*vcg::tri::io::ExporterPLY<AbstractMesh>::Save(*AbsMesh(),pathname);*/
1749         /*Warp(0);*/
1750         FILE *f;
1751         f=fopen(pathname,"w+");
1752 
1753         std::map<AbstractVertex*,int> vertexmap;
1754         typedef std::map<AbstractVertex*,int>::iterator iteMapVert;
1755 
1756         ///add vertices
1757         fprintf(f,"%d,%d \n",AbsMesh()->fn,AbsMesh()->vn);
1758         int index=0;
1759         for (unsigned int i=0;i<AbsMesh()->vert.size();i++)
1760         {
1761             AbstractVertex* vert=&AbsMesh()->vert[i];
1762             if (!vert->IsD())
1763             {
1764                 vertexmap.insert(std::pair<AbstractVertex*,int>(vert,index));
1765                 CoordType pos=vert->P();
1766                 CoordType RPos=vert->RPos;
1767                 fprintf(f,"%f,%f,%f;\n",pos.X(),pos.Y(),pos.Z());
1768                 index++;
1769             }
1770         }
1771 
1772         ///add faces
1773         for (unsigned int i=0;i<AbsMesh()->face.size();i++)
1774         {
1775             AbstractFace* face=&AbsMesh()->face[i];
1776             if (!face->IsD())
1777             {
1778                 AbstractVertex* v0=face->V(0);
1779                 AbstractVertex* v1=face->V(1);
1780                 AbstractVertex* v2=face->V(2);
1781                 iteMapVert vertIte;
1782                 vertIte=vertexmap.find(v0);
1783                 assert(vertIte!=vertexmap.end());
1784                 int index0=(*vertIte).second;
1785                 vertIte=vertexmap.find(v1);
1786                 assert(vertIte!=vertexmap.end());
1787                 int index1=(*vertIte).second;
1788                 vertIte=vertexmap.find(v2);
1789                 assert(vertIte!=vertexmap.end());
1790                 int index2=(*vertIte).second;
1791                 assert((index0!=index1)&&(index1!=index2));
1792                 fprintf(f,"%d,%d,%d \n",index0,index1,index2);
1793             }
1794         }
1795         fclose(f);
1796     }
1797 
1798     template <class MeshType>
SetParamMesh(MeshType * _input_mesh,ParamMesh * _param_mesh)1799     bool SetParamMesh(MeshType	*_input_mesh,
1800                                         ParamMesh	 * _param_mesh)
1801     {
1802         param_mesh=_param_mesh;
1803         param_mesh->Clear();
1804         vcg::tri::Append<ParamMesh,MeshType>::Mesh(*param_mesh,*_input_mesh);
1805         return(Update(true));
1806     }
1807 
1808     template <class MeshType>
1809     bool LoadBaseDomain(const char *pathname,
1810                         MeshType	*_input_mesh,
1811                         ParamMesh	 * _param_mesh,
1812                         AbstractMesh *_absMesh,
1813             bool test=true)
1814 //						bool use_quality=true)
1815     {
1816         param_mesh=_param_mesh;
1817         param_mesh->Clear();
1818         /*vcg::tri::Allocator<MeshType>::CompactVertexVector(*_input_mesh);
1819         vcg::tri::Allocator<MeshType>::CompactFaceVector(*_input_mesh);*/
1820         vcg::tri::Append<ParamMesh,MeshType>::Mesh(*param_mesh,*_input_mesh);
1821         /*UpdateStructures<ParamMesh>(param_mesh);*/
1822 
1823         ///quality copy to index of texture
1824     for (size_t i=0;i<param_mesh->vert.size();i++)
1825         {
1826             int val0=(int)param_mesh->vert[i].Q();
1827             //int val1=param_mesh->vert[i].T().N();*/
1828             param_mesh->vert[i].T().N()=val0;
1829             assert(param_mesh->vert[i].T().N()>=0);
1830         }
1831         /*if (AbsMesh()!=NULL)
1832             delete(AbsMesh());*/
1833 
1834         //AbsMesh()=new AbstractMesh();
1835         AbsMesh()=_absMesh;
1836         AbsMesh()->Clear();
1837 
1838         FILE *f=NULL;
1839         f=fopen(pathname,"r");
1840         if (f==NULL)
1841             return false;
1842 
1843         int fileVn,fileFn;
1844         fscanf(f,"%d,%d \n",&fileVn,&fileFn);
1845 
1846         for (int i=0;i<fileVn;i++) {
1847           float _x,_y,_z;
1848           fscanf(f,"%f,%f,%f;\n",&_x,&_y,&_z);
1849           vcg::tri::Allocator<AbstractMesh>::AddVertex(*abstract_mesh,CoordType(_x,_y,_z));
1850         }
1851         for (int i=0;i<fileFn;i++) {
1852           int index0,index1,index2;
1853           fscanf(f,"%d,%d,%d \n",&index0,&index1,&index2);
1854           vcg::tri::Allocator<AbstractMesh>::AddFace(*abstract_mesh,index0,index1,index2);
1855         }
1856         UpdateTopologies<AbstractMesh>(AbsMesh());
1857         fclose(f);
1858 
1859         return (Update(test));
1860     }
1861 
1862     template <class MeshType>
CopyParametrization(MeshType * _param_mesh)1863     void CopyParametrization(MeshType	* _param_mesh)
1864     {
1865     for (size_t i=0;i<_param_mesh->vert.size();i++)
1866         {
1867             _param_mesh->vert[i].T().P()=ParaMesh()->vert[i].T().P();
1868             _param_mesh->vert[i].T().N()=ParaMesh()->vert[i].T().N();
1869             _param_mesh->vert[i].Q()=(typename MeshType::ScalarType)ParaMesh()->vert[i].T().N();
1870         }
1871     }
1872 
1873     template <class MeshType>
1874     int LoadMCP(AbstractMesh * _abstract_mesh,
1875               ParamMesh	 * _param_mesh,
1876                 char* filename,MeshType *coloredMesh=NULL)
1877     {
1878         abstract_mesh=_abstract_mesh;
1879         param_mesh=_param_mesh;
1880 
1881         FILE *f=NULL;
1882         f=fopen(filename,"r");
1883         if (f==NULL)
1884             return -1;
1885 
1886 
1887         ///add vertices
1888         abstract_mesh->Clear();
1889         fscanf(f,"%d,%d \n",&abstract_mesh->fn,&abstract_mesh->vn);
1890         abstract_mesh->vert.resize(abstract_mesh->vn);
1891         abstract_mesh->face.resize(abstract_mesh->fn);
1892 
1893         for (unsigned int i=0;i<abstract_mesh->vert.size();i++)
1894         {
1895             AbstractVertex* vert=&abstract_mesh->vert[i];
1896             CoordType pos;
1897             CoordType RPos;
1898             fscanf(f,"%f,%f,%f;%f,%f,%f \n",&pos.X(),&pos.Y(),&pos.Z(),&RPos.X(),&RPos.Y(),&RPos.Z());
1899             vert->P()=pos;
1900             //vert->RPos=RPos;
1901         }
1902 
1903 
1904 
1905         ///add faces
1906         for (unsigned int i=0;i<abstract_mesh->face.size();i++)
1907         {
1908             AbstractFace* face=&abstract_mesh->face[i];
1909             if (!face->IsD())
1910             {
1911                 int index0,index1,index2;
1912                 fscanf(f,"%d,%d,%d \n",&index0,&index1,&index2);
1913                 abstract_mesh->face[i].V(0)=&abstract_mesh->vert[index0];
1914                 abstract_mesh->face[i].V(1)=&abstract_mesh->vert[index1];
1915                 abstract_mesh->face[i].V(2)=&abstract_mesh->vert[index2];
1916             }
1917         }
1918 
1919         ///high resolution mesh
1920         fscanf(f,"%d,%d \n",&param_mesh->fn,&param_mesh->vn);
1921         param_mesh->vert.resize(param_mesh->vn);
1922         param_mesh->face.resize(param_mesh->fn);
1923 
1924         ///add vertices
1925         for (unsigned int i=0;i<param_mesh->vert.size();i++)
1926         {
1927             ParamVertex* vert=&param_mesh->vert[i];
1928             CoordType pos;
1929             CoordType bary;
1930             vcg::Color4b col;
1931             int index_face;
1932             int col0,col1,col2;
1933             fscanf(f,"%f,%f,%f;%f,%f,%f;%d,%d,%d;%d \n",
1934                   &pos.X(),&pos.Y(),&pos.Z(),
1935                   &bary.X(),&bary.Y(),&bary.Z(),
1936                   &col0,&col1,&col2,
1937                   &index_face);
1938             vert->P()=pos;
1939             //vert->RPos=pos;
1940             vert->T().P()=vcg::Point2<PScalarType>(bary.X(),bary.Y());
1941             vert->T().N()=index_face;
1942             if (coloredMesh!=NULL)
1943             {
1944                 vcg::Color4b col=coloredMesh->vert[i].C();
1945                 vert->C()=col;
1946             }
1947         }
1948 
1949         ///add faces
1950         for (unsigned int i=0;i<param_mesh->face.size();i++)
1951         {
1952             //BaseFace* face=&final_mesh.face[i];
1953 
1954             int index0,index1,index2;
1955             fscanf(f,"%d,%d,%d \n",&index0,&index1,&index2);
1956             param_mesh->face[i].V(0)=&param_mesh->vert[index0];
1957             param_mesh->face[i].V(1)=&param_mesh->vert[index1];
1958             param_mesh->face[i].V(2)=&param_mesh->vert[index2];
1959 
1960         }
1961         fclose(f);
1962 
1963         ///update structures
1964         vcg::tri::UpdateBounding<AbstractMesh>::Box(*abstract_mesh);
1965         vcg::tri::UpdateTopology<AbstractMesh>::FaceFace(*abstract_mesh);
1966         vcg::tri::UpdateTopology<AbstractMesh>::VertexFace(*abstract_mesh);
1967 
1968         vcg::tri::UpdateBounding<ParamMesh>::Box(*param_mesh);
1969         vcg::tri::UpdateTopology<ParamMesh>::FaceFace(*param_mesh);
1970         vcg::tri::UpdateTopology<ParamMesh>::VertexFace(*param_mesh);
1971 
1972 
1973         Update();
1974 
1975         return 0;
1976     }
1977 };
1978 
1979 
1980 #endif
1981