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(¶m_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=¶mDomain->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=¶mDomain->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=¶mDomain->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=¶m_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=¶m_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",¶m_mesh->fn,¶m_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=¶m_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)=¶m_mesh->vert[index0];
1957 param_mesh->face[i].V(1)=¶m_mesh->vert[index1];
1958 param_mesh->face[i].V(2)=¶m_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