$darkmode
VCG Library
platonic.h
1 /****************************************************************************
2 * VCGLib o o *
3 * Visual and Computer Graphics Library o o *
4 * _ O _ *
5 * Copyright(C) 2004-2016 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23 
24 #ifndef __VCGLIB_PLATONIC
25 #define __VCGLIB_PLATONIC
26 
27 #include<vcg/math/base.h>
28 #include<vcg/complex/algorithms/refine.h>
29 #include<vcg/complex/algorithms/update/position.h>
30 #include<vcg/complex/algorithms/update/bounding.h>
31 #include<vcg/complex/algorithms/clean.h>
32 #include<vcg/complex/algorithms/polygon_support.h>
33 #include<vcg/complex/algorithms/smooth.h>
34 
35 
36 namespace vcg {
37 namespace tri {
48 template <class TetraMeshType>
49 void Tetrahedron(TetraMeshType &in)
50 {
51  typedef typename TetraMeshType::CoordType CoordType;
52  typedef typename TetraMeshType::VertexPointer VertexPointer;
53  typedef typename TetraMeshType::VertexIterator VertexIterator;
54  typedef typename TetraMeshType::FaceIterator FaceIterator;
55 
56  in.Clear();
59 
60  VertexPointer ivp[4];
61  VertexIterator vi=in.vert.begin();
62  ivp[0]=&*vi;(*vi).P()=CoordType ( 1.0, 1.0, 1.0); ++vi;
63  ivp[1]=&*vi;(*vi).P()=CoordType (-1.0, 1.0,-1.0); ++vi;
64  ivp[2]=&*vi;(*vi).P()=CoordType (-1.0,-1.0, 1.0); ++vi;
65  ivp[3]=&*vi;(*vi).P()=CoordType ( 1.0,-1.0,-1.0);
66 
67  FaceIterator fi=in.face.begin();
68  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
69  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[3]; ++fi;
70  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[1]; ++fi;
71  (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1];
72 }
73 
74 
77 template <class DodMeshType>
78 void Dodecahedron(DodMeshType & in)
79 {
80  typedef DodMeshType MeshType;
81  typedef typename MeshType::CoordType CoordType;
82  typedef typename MeshType::VertexPointer VertexPointer;
83  typedef typename MeshType::VertexIterator VertexIterator;
84  typedef typename MeshType::FaceIterator FaceIterator;
85  typedef typename MeshType::ScalarType ScalarType;
86  const int N_penta=12;
87  const int N_points=62;
88 
89  int penta[N_penta*3*3]=
90  {20,11, 18, 18, 11, 8, 8, 11, 4,
91  13,23, 4, 4, 23, 8, 8, 23, 16,
92  13, 4, 30, 30, 4, 28, 28, 4, 11,
93  16,34, 8, 8, 34, 18, 18, 34, 36,
94  11,20, 28, 28, 20, 45, 45, 20, 38,
95  13,30, 23, 23, 30, 41, 41, 30, 47,
96  16,23, 34, 34, 23, 50, 50, 23, 41,
97  20,18, 38, 38, 18, 52, 52, 18, 36,
98  30,28, 47, 47, 28, 56, 56, 28, 45,
99  50,60, 34, 34, 60, 36, 36, 60, 52,
100  45,38, 56, 56, 38, 60, 60, 38, 52,
101  50,41, 60, 60, 41, 56, 56, 41, 47 };
102  //A B E D C
103  const ScalarType p=(1.0 + math::Sqrt(5.0)) / 2.0;
104  const ScalarType p2=p*p;
105  const ScalarType p3=p*p*p;
106  ScalarType vv[N_points*3]=
107  {
108  0, 0, 2*p2, p2, 0, p3, p, p2, p3,
109  0, p, p3, -p, p2, p3, -p2, 0, p3,
110  -p, -p2, p3, 0, -p, p3, p, -p2, p3,
111  p3, p, p2, p2, p2, p2, 0, p3, p2,
112  -p2, p2, p2, -p3, p, p2, -p3, -p, p2,
113  -p2, -p2, p2, 0, -p3, p2, p2, -p2, p2,
114  p3, -p, p2, p3, 0, p, p2, p3, p,
115  -p2, p3, p, -p3, 0, p, -p2, -p3, p,
116  p2, -p3, p, 2*p2, 0, 0, p3, p2, 0,
117  p, p3, 0, 0, 2*p2, 0, -p, p3, 0,
118  -p3, p2, 0, -2*p2, 0, 0, -p3, -p2, 0,
119  -p, -p3, 0, 0, -2*p2, 0, p, -p3, 0,
120  p3, -p2, 0, p3, 0, -p, p2, p3, -p,
121  -p2, p3, -p, -p3, 0, -p, -p2, -p3, -p,
122  p2, -p3, -p, p3, p, -p2, p2, p2, -p2,
123  0, p3, -p2, -p2, p2, -p2, -p3, p, -p2,
124  -p3, -p, -p2, -p2, -p2, -p2, 0, -p3, -p2,
125  p2, -p2, -p2, p3, -p, -p2, p2, 0, -p3,
126  p, p2, -p3, 0, p, -p3, -p, p2, -p3,
127  -p2, 0, -p3, -p, -p2, -p3, 0, -p, -p3,
128  p, -p2, -p3, 0, 0, -2*p2
129  };
130  in.Clear();
131  //in.face.clear();
133  Allocator<DodMeshType>::AddFaces(in, 5*12); // five pentagons, each made by 5 tri
134 
135  int h,i,j,m=0;
136 
137  bool used[N_points];
138  for (i=0; i<N_points; i++) used[i]=false;
139 
140  int reindex[20+12 *10];
141  ScalarType xx,yy,zz, sx,sy,sz;
142 
143  int order[5]={0,1,8,6,2};
144  int added[12];
145 
146  VertexIterator vi=in.vert.begin();
147 
148  for (i=0; i<12; i++) {
149  sx=sy=sz=0;
150  for (int j=0; j<5; j++) {
151  h= penta[ i*9 + order[j] ]-1;
152  xx=vv[h*3];yy=vv[h*3+1];zz=vv[h*3+2]; sx+=xx; sy+=yy; sz+=zz;
153  if (!used[h]) {
154  (*vi).P()=CoordType( xx, yy, zz ); vi++;
155  used[h]=true;
156  reindex[ h ] = m++;
157  }
158  }
159  (*vi).P()=CoordType( sx/5.0, sy/5.0, sz/5.0 ); vi++;
160  added[ i ] = m++;
161  }
162 
163  std::vector<VertexPointer> index(in.vn);
164 
165  for(j=0,vi=in.vert.begin();j<in.vn;++j,++vi) index[j] = &(*vi);
166 
167  FaceIterator fi=in.face.begin();
168 
169  for (i=0; i<12; i++) {
170  for (j=0; j<5; j++){
171  (*fi).V(0)=index[added[i] ];
172  (*fi).V(1)=index[reindex[penta[i*9 + order[j ] ] -1 ] ];
173  (*fi).V(2)=index[reindex[penta[i*9 + order[(j+1)%5] ] -1 ] ];
174  if (HasPerFaceFlags(in)) {
175  // tag faux edges
176  (*fi).SetF(0);
177  (*fi).SetF(2);
178  }
179  fi++;
180  }
181  }
182 }
183 
184 template <class OctMeshType>
185 void Octahedron(OctMeshType &in)
186 {
187  typedef OctMeshType MeshType;
188  typedef typename MeshType::CoordType CoordType;
189  typedef typename MeshType::VertexPointer VertexPointer;
190  typedef typename MeshType::VertexIterator VertexIterator;
191  typedef typename MeshType::FaceIterator FaceIterator;
192 
193  in.Clear();
196 
197  VertexPointer ivp[6];
198 
199  VertexIterator vi=in.vert.begin();
200  ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 0, 0); ++vi;
201  ivp[1]=&*vi;(*vi).P()=CoordType ( 0, 1, 0); ++vi;
202  ivp[2]=&*vi;(*vi).P()=CoordType ( 0, 0, 1); ++vi;
203  ivp[3]=&*vi;(*vi).P()=CoordType (-1, 0, 0); ++vi;
204  ivp[4]=&*vi;(*vi).P()=CoordType ( 0,-1, 0); ++vi;
205  ivp[5]=&*vi;(*vi).P()=CoordType ( 0, 0,-1);
206 
207  FaceIterator fi=in.face.begin();
208  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
209  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi;
210  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[5]; ++fi;
211  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[1]; ++fi;
212  (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[5]; ++fi;
213  (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[4]; ++fi;
214  (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi;
215  (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1];
216 }
217 
218 template <class IcoMeshType>
219 void Icosahedron(IcoMeshType &in)
220 {
221  typedef IcoMeshType MeshType;
222  typedef typename MeshType::ScalarType ScalarType;
223  typedef typename MeshType::CoordType CoordType;
224  typedef typename MeshType::VertexPointer VertexPointer;
225  typedef typename MeshType::VertexIterator VertexIterator;
226  typedef typename MeshType::FaceIterator FaceIterator;
227 
228  ScalarType L=ScalarType((math::Sqrt(5.0)+1.0)/2.0);
229  CoordType vv[12]={
230  CoordType ( 0, L, 1),
231  CoordType ( 0, L,-1),
232  CoordType ( 0,-L, 1),
233  CoordType ( 0,-L,-1),
234 
235  CoordType ( L, 1, 0),
236  CoordType ( L,-1, 0),
237  CoordType (-L, 1, 0),
238  CoordType (-L,-1, 0),
239 
240  CoordType ( 1, 0, L),
241  CoordType (-1, 0, L),
242  CoordType ( 1, 0,-L),
243  CoordType (-1, 0,-L)
244  };
245 
246  int ff[20][3]={
247  {1,0,4},{0,1,6},{2,3,5},{3,2,7},
248  {4,5,10},{5,4,8},{6,7,9},{7,6,11},
249  {8,9,2},{9,8,0},{10,11,1},{11,10,3},
250  {0,8,4},{0,6,9},{1,4,10},{1,11,6},
251  {2,5,8},{2,9,7},{3,10,5},{3,7,11}
252  };
253 
254 
255  in.Clear();
258  VertexPointer ivp[12];
259 
260  VertexIterator vi;
261  int i;
262  for(i=0,vi=in.vert.begin();vi!=in.vert.end();++i,++vi){
263  (*vi).P()=vv[i];
264  ivp[i]=&*vi;
265  }
266 
267  FaceIterator fi;
268  for(i=0,fi=in.face.begin();fi!=in.face.end();++i,++fi){
269  (*fi).V(0)=ivp[ff[i][0]];
270  (*fi).V(1)=ivp[ff[i][1]];
271  (*fi).V(2)=ivp[ff[i][2]];
272  }
273 }
274 
275 template <class MeshType>
276 void Hexahedron(MeshType &in)
277 {
278  typedef typename MeshType::CoordType CoordType;
279  typedef typename MeshType::VertexPointer VertexPointer;
280  typedef typename MeshType::VertexIterator VertexIterator;
281  typedef typename MeshType::FaceIterator FaceIterator;
282 
283  in.Clear();
286 
287  VertexPointer ivp[8];
288 
289  VertexIterator vi=in.vert.begin();
290 
291  ivp[7]=&*vi;(*vi).P()=CoordType (-1,-1,-1); ++vi;
292  ivp[6]=&*vi;(*vi).P()=CoordType ( 1,-1,-1); ++vi;
293  ivp[5]=&*vi;(*vi).P()=CoordType (-1, 1,-1); ++vi;
294  ivp[4]=&*vi;(*vi).P()=CoordType ( 1, 1,-1); ++vi;
295  ivp[3]=&*vi;(*vi).P()=CoordType (-1,-1, 1); ++vi;
296  ivp[2]=&*vi;(*vi).P()=CoordType ( 1,-1, 1); ++vi;
297  ivp[1]=&*vi;(*vi).P()=CoordType (-1, 1, 1); ++vi;
298  ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 1, 1);
299 
300  FaceIterator fi=in.face.begin();
301  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
302  (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1]; ++fi;
303  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi;
304  (*fi).V(0)=ivp[6]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi;
305  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[1]; ++fi;
306  (*fi).V(0)=ivp[5]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[4]; ++fi;
307  (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[6]; ++fi;
308  (*fi).V(0)=ivp[4]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[5]; ++fi;
309  (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[3]; ++fi;
310  (*fi).V(0)=ivp[2]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[6]; ++fi;
311  (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[5]; ++fi;
312  (*fi).V(0)=ivp[1]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[3];
313 
314  if (HasPerFaceFlags(in)) {
315  FaceIterator fi=in.face.begin();
316  for (int k=0; k<12; k++) {
317  (*fi).SetF(1); fi++;
318  }
319  }
320 
321 }
322 
323 template <class MeshType>
324 void Square(MeshType &in)
325 {
326  typedef typename MeshType::CoordType CoordType;
327  typedef typename MeshType::VertexPointer VertexPointer;
328  typedef typename MeshType::VertexIterator VertexIterator;
329  typedef typename MeshType::FaceIterator FaceIterator;
330 
331  in.Clear();
334 
335  VertexPointer ivp[4];
336 
337  VertexIterator vi=in.vert.begin();
338  ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 0, 0); ++vi;
339  ivp[1]=&*vi;(*vi).P()=CoordType ( 0, 1, 0); ++vi;
340  ivp[2]=&*vi;(*vi).P()=CoordType (-1, 0, 0); ++vi;
341  ivp[3]=&*vi;(*vi).P()=CoordType ( 0,-1, 0);
342 
343  FaceIterator fi=in.face.begin();
344  (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
345  (*fi).V(0)=ivp[2]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[0];
346 
347  if (HasPerFaceFlags(in)) {
348  FaceIterator fi=in.face.begin();
349  for (int k=0; k<2; k++) {
350  (*fi).SetF(2); fi++;
351  }
352  }
353 }
354 
355 template <class MeshType>
356 void SphericalCap(MeshType &in, float angleRad, const int subdiv = 3 )
357 {
358  typedef typename MeshType::CoordType CoordType;
359  typedef typename MeshType::VertexIterator VertexIterator;
360  in.Clear();
361  tri::Allocator<MeshType>::AddVertex(in,CoordType(0,0,0));
362  for(int i=0;i<6;++i)
363  tri::Allocator<MeshType>::AddVertex(in,CoordType(cos(math::ToRad(i*60.0)),sin(math::ToRad(i*60.0)),0));
364 
365  for(int i=0;i<6;++i)
366  tri::Allocator<MeshType>::AddFace(in,&(in.vert[0]),&(in.vert[1+i]),&(in.vert[1+(i+1)%6]));
367 
369  for(int i=0;i<subdiv;++i)
370  {
371  tri::Refine(in, MidPoint<MeshType>(&in));
372 
375 
376  for(int i=0;i<in.vn;++i)
377  if(in.vert[i].IsB())
378  in.vert[i].P().Normalize();
379 
382  tri::Smooth<MeshType>::VertexCoordLaplacian(in,10,true);
383  }
384 
385  float angleHalfRad = angleRad /2.0f;
386  float width = sin(angleHalfRad);
387  tri::UpdatePosition<MeshType>::Scale(in,width);
388  tri::Allocator<MeshType>::CompactEveryVector(in);
389  for(VertexIterator vi=in.vert.begin(); vi!=in.vert.end();++vi)
390  {
391  float cosVi = vi->P().Norm();
392  float angVi = asin (cosVi);
393  vi->P()[2] = cos(angVi) - cos(angleHalfRad);
394  }
395 }
396 
397 // this function build a sphere starting from a eventually not empty mesh.
398 // If the mesh is not empty it is 'spherified' and used as base for the subdivision process.
399 // otherwise an icosahedron is used.
400 template <class MeshType>
401 void Sphere(MeshType &in, const int subdiv = 3 )
402 {
403  typedef typename MeshType::CoordType CoordType;
404  typedef typename MeshType::VertexIterator VertexIterator;
405  typedef typename MeshType::FaceIterator FaceIterator;
406  if(in.vn==0 && in.fn==0) Icosahedron(in);
407 
408  for(VertexIterator vi = in.vert.begin(); vi!=in.vert.end();++vi)
409  vi->P().Normalize();
410 
411  for(int i = 0 ; i < subdiv; ++i)
412  {
413  MeshType newM;
414  for(FaceIterator fi=in.face.begin();fi!=in.face.end();++fi)
415  {
416  CoordType me01 = (fi->P(0)+fi->P(1))/2.0;
417  CoordType me12 = (fi->P(1)+fi->P(2))/2.0;
418  CoordType me20 = (fi->P(2)+fi->P(0))/2.0;
419  tri::Allocator<MeshType>::AddFace(newM,me01,me12,me20);
420  tri::Allocator<MeshType>::AddFace(newM,fi->P(0),me01,me20);
421  tri::Allocator<MeshType>::AddFace(newM,fi->P(1),me12,me01);
422  tri::Allocator<MeshType>::AddFace(newM,fi->P(2),me20,me12);
423  }
426 
427  for(VertexIterator vi = in.vert.begin(); vi != in.vert.end(); ++vi)
428  vi->P().Normalize();
429  }
430 }
431 
432 template <class MeshType>
433 void Sphere(MeshType & m, const typename MeshType::CoordType & position, typename MeshType::ScalarType radius = 0, const int subdiv = 3)
434 {
435  m.Clear();
436  tri::Sphere(m, subdiv);
437  tri::UpdatePosition<MeshType>::Scale(m,radius);
438  tri::UpdatePosition<MeshType>::Translate(m, position);
439 }
440 
442 template <class MeshType>
443 void Cone( MeshType& in,
444  const typename MeshType::ScalarType r1,
445  const typename MeshType::ScalarType r2,
446  const typename MeshType::ScalarType h,
447  const int SubDiv = 36 )
448 {
449  typedef typename MeshType::CoordType CoordType;
450  typedef typename MeshType::VertexPointer VertexPointer;
451  typedef typename MeshType::VertexIterator VertexIterator;
452  typedef typename MeshType::FaceIterator FaceIterator;
453 
454  int i,b1,b2;
455  in.Clear();
456  int VN,FN;
457  if(r1==0 || r2==0) {
458  VN=SubDiv+2;
459  FN=SubDiv*2;
460  } else {
461  VN=SubDiv*2+2;
462  FN=SubDiv*4;
463  }
464 
467  VertexPointer *ivp = new VertexPointer[VN];
468 
469  VertexIterator vi=in.vert.begin();
470  ivp[0]=&*vi;(*vi).P()=CoordType ( 0,-h/2.0,0 ); ++vi;
471  ivp[1]=&*vi;(*vi).P()=CoordType ( 0, h/2.0,0 ); ++vi;
472 
473  b1 = b2 = 2;
474  int cnt=2;
475  if(r1!=0)
476  {
477  for(i=0;i<SubDiv;++i)
478  {
479  double a = math::ToRad(i*360.0/SubDiv);
480  ivp[cnt]=&*vi; (*vi).P()= CoordType(r1*cos(a), -h/2.0, r1*sin(a)); ++vi;++cnt;
481  }
482  b2 += SubDiv;
483  }
484 
485  if(r2!=0)
486  {
487  for(i=0;i<SubDiv;++i)
488  {
489  double a = math::ToRad(i*360.0/SubDiv);
490  ivp[cnt]=&*vi; (*vi).P()= CoordType( r2*cos(a), h/2.0, r2*sin(a)); ++vi;++cnt;
491  }
492  }
493 
494  FaceIterator fi=in.face.begin();
495 
496  if(r1!=0) for(i=0;i<SubDiv;++i,++fi) {
497  (*fi).V(0)=ivp[0];
498  (*fi).V(1)=ivp[b1+i];
499  (*fi).V(2)=ivp[b1+(i+1)%SubDiv];
500  }
501 
502  if(r2!=0) for(i=0;i<SubDiv;++i,++fi) {
503  (*fi).V(0)=ivp[1];
504  (*fi).V(2)=ivp[b2+i];
505  (*fi).V(1)=ivp[b2+(i+1)%SubDiv];
506  }
507 
508  if(r1==0) for(i=0;i<SubDiv;++i,++fi)
509  {
510  (*fi).V(0)=ivp[0];
511  (*fi).V(1)=ivp[b2+i];
512  (*fi).V(2)=ivp[b2+(i+1)%SubDiv];
513  }
514  if(r2==0) for(i=0;i<SubDiv;++i,++fi){
515  (*fi).V(0)=ivp[1];
516  (*fi).V(2)=ivp[b1+i];
517  (*fi).V(1)=ivp[b1+(i+1)%SubDiv];
518  }
519 
520  if(r1!=0 && r2!=0)for(i=0;i<SubDiv;++i)
521  {
522  (*fi).V(0)=ivp[b1+i];
523  (*fi).V(1)=ivp[b2+i];
524  (*fi).V(2)=ivp[b2+(i+1)%SubDiv];
525  ++fi;
526  (*fi).V(0)=ivp[b1+i];
527  (*fi).V(1)=ivp[b2+(i+1)%SubDiv];
528  (*fi).V(2)=ivp[b1+(i+1)%SubDiv];
529  ++fi;
530  }
531 }
532 
533 template <class MeshType>
534 void OrientedCone(MeshType & m,
535  const typename MeshType::CoordType origin,
536  const typename MeshType::CoordType end,
537  const typename MeshType::ScalarType r1,
538  const typename MeshType::ScalarType r2,
539  const int SubDiv = 36 )
540 {
541  typedef typename MeshType::ScalarType ScalarType;
542  typedef typename MeshType::CoordType CoordType;
543  typedef Matrix44<typename MeshType::ScalarType> Matrix44x;
544  Cone(m,r1,r2,Distance(origin,end),SubDiv);
545 
546  tri::UpdatePosition<MeshType>::Translate(m,CoordType(0,Distance(origin,end)/2,0));
547 
548  CoordType norm = end-origin;
549  ScalarType angleRad = Angle(CoordType(0,1,0),norm);
550  const ScalarType Delta= 0.000000001;
551  Matrix44x rotM;
552  if (fabs(angleRad)<Delta)
553  rotM.SetIdentity();
554  else
555  if (fabs(angleRad-M_PI)<Delta)
556  {
557  CoordType axis = CoordType(0,0,1)^norm;
558  rotM.SetRotateRad(angleRad,axis);
559  }
560  else
561  {
562  CoordType axis = CoordType(0,1,0)^norm;
563  rotM.SetRotateRad(angleRad,axis);
564  }
566  tri::UpdatePosition<MeshType>::Translate(m,origin);
567 }
568 
569 
570 template <class MeshType >
571 void Box(MeshType &in, const typename MeshType::BoxType & bb )
572 {
573  typedef typename MeshType::CoordType CoordType;
574  typedef typename MeshType::VertexPointer VertexPointer;
575  typedef typename MeshType::VertexIterator VertexIterator;
576  typedef typename MeshType::FaceIterator FaceIterator;
577 
578  in.Clear();
580  VertexPointer ivp[8];
581 
582  VertexIterator vi=in.vert.begin();
583  ivp[0]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.min[2]); ++vi;
584  ivp[1]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.min[2]); ++vi;
585  ivp[2]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.min[2]); ++vi;
586  ivp[3]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.min[2]); ++vi;
587  ivp[4]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.max[2]); ++vi;
588  ivp[5]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.max[2]); ++vi;
589  ivp[6]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.max[2]); ++vi;
590  ivp[7]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.max[2]);
591 
592  Allocator<MeshType>::AddFace(in,ivp[2],ivp[1],ivp[0]);
593  Allocator<MeshType>::AddFace(in,ivp[1],ivp[2],ivp[3]);
594  Allocator<MeshType>::AddFace(in,ivp[4],ivp[2],ivp[0]);
595  Allocator<MeshType>::AddFace(in,ivp[2],ivp[4],ivp[6]);
596  Allocator<MeshType>::AddFace(in,ivp[1],ivp[4],ivp[0]);
597  Allocator<MeshType>::AddFace(in,ivp[4],ivp[1],ivp[5]);
598  Allocator<MeshType>::AddFace(in,ivp[6],ivp[5],ivp[7]);
599  Allocator<MeshType>::AddFace(in,ivp[5],ivp[6],ivp[4]);
600  Allocator<MeshType>::AddFace(in,ivp[3],ivp[6],ivp[7]);
601  Allocator<MeshType>::AddFace(in,ivp[6],ivp[3],ivp[2]);
602  Allocator<MeshType>::AddFace(in,ivp[5],ivp[3],ivp[7]);
603  Allocator<MeshType>::AddFace(in,ivp[3],ivp[5],ivp[1]);
604 
605  if (HasPerFaceFlags(in)) {
606  FaceIterator fi=in.face.begin();
607  for (int k=0; k<12; k++) {
608  (*fi).SetF(0); fi++;
609  }
610  }
611 
612 }
613 
614 // Torus
615 template <class MeshType>
616 void Torus(MeshType &m, float hRingRadius, float vRingRadius, int hRingDiv=24, int vRingDiv=12 )
617 {
618  typedef typename MeshType::CoordType CoordType;
619  typedef typename MeshType::ScalarType ScalarType;
620  typedef Matrix44<ScalarType> Matrix44x;
621  m.Clear();
622  ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
623  ScalarType angleStepH = (2.0f*M_PI)/hRingDiv;
624 
625  Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
626  for(int i=0;i<hRingDiv+1;++i)
627  {
628  Matrix44x RotM; RotM.SetRotateRad(float(i%hRingDiv)*angleStepH,CoordType(0,0,1));
629  for(int j=0;j<vRingDiv+1;++j)
630  {
631  CoordType p;
632  p[0]= vRingRadius*cos(float(j%vRingDiv)*angleStepV) + hRingRadius;
633  p[1] = 0;
634  p[2]= vRingRadius*sin(float(j%vRingDiv)*angleStepV);
635 
636  m.vert[i*(vRingDiv+1)+j].P() = RotM*p;
637  }
638  }
639  FaceGrid(m,vRingDiv+1,hRingDiv+1);
641  tri::Allocator<MeshType>::CompactEveryVector(m);
642 
643 }
644 
647 template <class ScalarType>
648 static ScalarType _SQfnC(ScalarType a, ScalarType b){
649  return math::Sgn(cos(a))*pow(fabs(cos(a)),b);
650 }
651 template <class ScalarType>
652 static ScalarType _SQfnS(ScalarType a, ScalarType b){
653  return math::Sgn(sin(a))*pow(fabs(sin(a)),b);
654 }
655 
656 
664 template <class MeshType>
665 void SuperToroid(MeshType &m, float hRingRadius, float vRingRadius, float vSquareness, float hSquareness, int hRingDiv=24, int vRingDiv=12 )
666 {
667  typedef typename MeshType::CoordType CoordType;
668  typedef typename MeshType::ScalarType ScalarType;
669  m.Clear();
670  ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
671  ScalarType angleStepH = (2.0f*M_PI)/hRingDiv;
672 
673  ScalarType u,v;
674  int count;
675  Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
676  for(int i=0;i<hRingDiv+1;++i)
677  {
678  u=float(i%hRingDiv)*angleStepH;
679  count=0;
680  for(int j=vRingDiv;j>=0;--j)
681  {
682  CoordType p;
683  v=float(j%vRingDiv)*angleStepV;
684  p[0]= (hRingRadius+vRingRadius*_SQfnC(u,vSquareness))*_SQfnC(v,hSquareness);;
685  p[1]= (hRingRadius+vRingRadius*_SQfnC(u,vSquareness))*_SQfnS(v,hSquareness);
686  p[2] = vRingRadius*_SQfnS(u,vSquareness);
687  m.vert[i*(vRingDiv+1)+count].P() = p;
688  count++;
689  }
690  }
691  FaceGrid(m,vRingDiv+1,hRingDiv+1);
694 
695 }
701 template <class MeshType>
702 void SuperEllipsoid(MeshType &m, float rFeature, float sFeature, float tFeature, int hRingDiv=24, int vRingDiv=12 )
703 {
704  typedef typename MeshType::CoordType CoordType;
705  typedef typename MeshType::ScalarType ScalarType;
706  m.Clear();
707  ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
708  ScalarType angleStepH = (1.0f*M_PI)/hRingDiv;
709  float u;
710  float v;
711  Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
712  for(int i=0;i<hRingDiv+1;++i)
713  {
714  //u=ScalarType(i%hRingDiv)*angleStepH + angleStepH/2.0;
715  u=i*angleStepH;
716  for(int j=0;j<vRingDiv+1;++j)
717  {
718  CoordType p;
719  v=ScalarType(j%vRingDiv)*angleStepV;
720  p[0] = _SQfnC(v,2/rFeature)*_SQfnC(u,2/rFeature);
721  p[1] = _SQfnC(v,2/sFeature)*_SQfnS(u,2/sFeature);
722  p[2] = _SQfnS(v,2/tFeature);
723  m.vert[i*(vRingDiv+1)+j].P() = p;
724  }
725  }
726  FaceGrid(m,vRingDiv+1,hRingDiv+1);
727  tri::Clean<MeshType>::MergeCloseVertex(m,ScalarType(angleStepV*angleStepV*0.001));
729  bool oriented, orientable;
731  tri::Clean<MeshType>::OrientCoherentlyMesh(m,oriented,orientable);
733 }
734 
740 template <class MeshType, class InCoordType, class InFaceIndexType >
741 void BuildMeshFromCoordVectorIndexVector(MeshType & in, const std::vector<InCoordType> & v, const std::vector<InFaceIndexType> & f)
742 {
743  typedef typename MeshType::CoordType CoordType;
744 
745  in.Clear();
747  Allocator<MeshType>::AddFaces(in,f.size());
748 
749  for(size_t i=0;i<v.size();++i)
750  {
751  const InCoordType &vv = v[i];
752  in.vert[i].P() = CoordType( vv[0],vv[1],vv[2]);
753  }
754 
755  for(size_t i=0;i<f.size();++i)
756  {
757  const InFaceIndexType &ff= f[i];
758  assert( ff[0]>=0 && ff[0]<in.vn);
759  assert( ff[1]>=0 && ff[1]<in.vn);
760  assert( ff[2]>=0 && ff[2]<in.vn);
761  in.face[i].V(0) = &in.vert[ ff[0] ];
762  in.face[i].V(1) = &in.vert[ ff[1] ];
763  in.face[i].V(2) = &in.vert[ ff[2] ];
764  }
765 
767 }
768 
769 
770 template <class MeshType,class V>
771 void BuildMeshFromCoordVector( MeshType & in, const V & v)
772 {
773  std::vector<Point3i> dummyfaceVec;
774  BuildMeshFromCoordVectorIndexVector(in,v,dummyfaceVec);
775 }
776 
777 
778 template <class TriMeshType,class EdgeMeshType >
779 void BuildFromFaceEdgeSel(TriMeshType &in, EdgeMeshType &out)
780 {
781  tri::RequireCompactness(in);
782  std::vector<typename tri::UpdateTopology<TriMeshType>::PEdge> edgevec;
783  tri::UpdateTopology<TriMeshType>::FillSelectedFaceEdgeVector(in, edgevec);
784  out.Clear();
785  for(size_t i=0;i<in.vert.size();++i)
786  tri::Allocator<EdgeMeshType>::AddVertex(out, in.vert[i].P());
787  tri::UpdateFlags<EdgeMeshType>::VertexClearV(out);
788 
789  for(size_t i=0;i<edgevec.size();++i)
790  {
791  int i0 = tri::Index(in,edgevec[i].v[0]);
792  int i1 = tri::Index(in,edgevec[i].v[1]);
793  out.vert[i0].SetV();
794  out.vert[i1].SetV();
795  tri::Allocator<EdgeMeshType>::AddEdge(out,&out.vert[i0],&out.vert[i1]);
796  if(in.vert[i0].IsS()) out.vert[i0].SetS();
797  if(in.vert[i1].IsS()) out.vert[i1].SetS();
798  }
799 
800  for(size_t i=0;i<out.vert.size();++i)
801  if(!out.vert[i].IsV()) tri::Allocator<EdgeMeshType>::DeleteVertex(out,out.vert[i]);
802 
803  tri::Allocator<EdgeMeshType>::CompactEveryVector(out);
804 }
805 
806 // Build a regular grid mesh as a typical height field mesh
807 // x y are the position on the grid scaled by wl and hl (at the end x is in the range 0..wl and y is in 0..hl)
808 // z is taken from the <data> array
809 // Once generated the vertex positions it uses the FaceGrid function to generate the faces;
810 
811 template <class MeshType>
812 void Grid(MeshType & in, int w, int h, float wl, float hl, float *data=0)
813 {
814  typedef typename MeshType::CoordType CoordType;
815 
816  in.Clear();
818 
819  float wld=wl/float(w-1);
820  float hld=hl/float(h-1);
821  float zVal=0;
822  for(int i=0;i<h;++i)
823  for(int j=0;j<w;++j)
824  {
825  if(data) zVal=data[i*w+j];
826  in.vert[i*w+j].P()=CoordType ( j*wld, i*hld, zVal) ;
827  }
828  FaceGrid(in,w,h);
829 }
830 
831 
832 // Build a regular grid mesh of faces as a typical height field mesh
833 // Vertexes are assumed to be already be allocated.
834 
835 template <class MeshType>
836 void FaceGrid(MeshType & in, int w, int h)
837 {
838  assert(in.vn == (int)in.vert.size()); // require a compact vertex vector
839  assert(in.vn >= w*h); // the number of vertices should match the number of expected grid vertices
840 
841  Allocator<MeshType>::AddFaces(in,(w-1)*(h-1)*2);
842 
843 // i+0,j+0 -- i+0,j+1
844 // | \ |
845 // | \ |
846 // | \ |
847 // | \ |
848 // i+1,j+0 -- i+1,j+1
849 //
850  for(int i=0;i<h-1;++i)
851  for(int j=0;j<w-1;++j)
852  {
853  in.face[2*(i*(w-1)+j)+0].V(0) = &(in.vert[(i+1)*w+j+1]);
854  in.face[2*(i*(w-1)+j)+0].V(1) = &(in.vert[(i+0)*w+j+1]);
855  in.face[2*(i*(w-1)+j)+0].V(2) = &(in.vert[(i+0)*w+j+0]);
856 
857  in.face[2*(i*(w-1)+j)+1].V(0) = &(in.vert[(i+0)*w+j+0]);
858  in.face[2*(i*(w-1)+j)+1].V(1) = &(in.vert[(i+1)*w+j+0]);
859  in.face[2*(i*(w-1)+j)+1].V(2) = &(in.vert[(i+1)*w+j+1]);
860  }
861 
862  if (HasPerFaceFlags(in)) {
863  for (int k=0; k<(h-1)*(w-1)*2; k++) {
864  in.face[k].SetF(2);
865  }
866  }
867 
868 }
869 
870 
871 // Build a regular grid mesh of faces as the resulto of a sparsely regularly sampled height field.
872 // Vertexes are assumed to be already be allocated, but not all the grid vertexes are present.
873 // For this purpose vector with a grid of indexes is also passed.
874 // Negative indexes in this vector means that there is no vertex.
875 
876 template <class MeshType>
877 void SparseFaceGrid(MeshType & in, const std::vector<int> &grid, int w, int h)
878 {
879  tri::RequireCompactness(in);
880  assert(in.vn <= w*h); // the number of vertices should match the number of expected grid vertices
881 
882 // V0 V1
883 // i+0,j+0 -- i+0,j+1
884 // | \ |
885 // | \ |
886 // | \ |
887 // | \ |
888 // i+1,j+0 -- i+1,j+1
889 // V2 V3
890 
891 
892  for(int i=0;i<h-1;++i)
893  for(int j=0;j<w-1;++j)
894  {
895  int V0i= grid[(i+0)*w+j+0];
896  int V1i= grid[(i+0)*w+j+1];
897  int V2i= grid[(i+1)*w+j+0];
898  int V3i= grid[(i+1)*w+j+1];
899 
900  int ndone=0;
901  bool quad = (V0i>=0 && V1i>=0 && V2i>=0 && V3i>=0 ) && tri::HasPerFaceFlags(in);
902 
903  if(V0i>=0 && V2i>=0 && V3i>=0 )
904  {
905  typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
906  f->V(0)=&(in.vert[V3i]);
907  f->V(1)=&(in.vert[V2i]);
908  f->V(2)=&(in.vert[V0i]);
909  if (quad) f->SetF(2);
910  ndone++;
911  }
912  if(V0i>=0 && V1i>=0 && V3i>=0 )
913  {
914  typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
915  f->V(0)=&(in.vert[V0i]);
916  f->V(1)=&(in.vert[V1i]);
917  f->V(2)=&(in.vert[V3i]);
918  if (quad) f->SetF(2);
919  ndone++;
920  }
921 
922  if (ndone==0) { // try diag the other way
923  if(V2i>=0 && V0i>=0 && V1i>=0 )
924  {
925  typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
926  f->V(0)=&(in.vert[V2i]);
927  f->V(1)=&(in.vert[V0i]);
928  f->V(2)=&(in.vert[V1i]);
929  ndone++;
930  }
931  if(V1i>=0 && V3i>=0 && V2i>=0 )
932  {
933  typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
934  f->V(0)=&(in.vert[V1i]);
935  f->V(1)=&(in.vert[V3i]);
936  f->V(2)=&(in.vert[V2i]);
937  ndone++;
938  }
939  }
940  }
941 }
942 template <class MeshType>
943 void Annulus(MeshType & m, float externalRadius, float internalRadius, int slices)
944 {
945  m.Clear();
946  typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices*2);
947 
948  for ( int j = 0; j < slices; ++j)
949  {
950  float x = cos( 2.0 * M_PI / slices * j);
951  float y = sin( 2.0 * M_PI / slices * j);
952 
953  (*vi).P() = typename MeshType::CoordType(x,y,0)*internalRadius;
954  ++vi;
955  (*vi).P() = typename MeshType::CoordType(x,y,0)*externalRadius;
956  ++vi;
957  }
958  typename MeshType::FaceIterator fi ;
959  for ( int j = 0; j < slices; ++j)
960  {
962  (*fi).V(0) = &m.vert[ ((j+0)*2+0)%(slices*2) ];
963  (*fi).V(1) = &m.vert[ ((j+1)*2+1)%(slices*2) ];
964  (*fi).V(2) = &m.vert[ ((j+0)*2+1)%(slices*2) ];
965 
967  (*fi).V(0) = &m.vert[ ((j+1)*2+0)%(slices*2) ];
968  (*fi).V(1) = &m.vert[ ((j+1)*2+1)%(slices*2) ];
969  (*fi).V(2) = &m.vert[ ((j+0)*2+0)%(slices*2) ];
970  }
971 }
972 
973 template <class MeshType>
974 void OrientedAnnulus(MeshType & m, Point3f center, Point3f norm, float externalRadius, float internalRadius, int slices)
975 {
976  Annulus(m,externalRadius,internalRadius, slices);
977  float angleRad = Angle(Point3f(0,0,1),norm);
978  Point3f axis = Point3f(0,0,1)^norm;
979 
980  Matrix44f rotM;
981  rotM.SetRotateRad(angleRad,axis);
983  tri::UpdatePosition<MeshType>::Translate(m,center);
984 }
985 
986 
987 template <class MeshType>
988 void Disk(MeshType & m, int slices)
989 {
990  m.Clear();
991  typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices+1);
992  (*vi).P() = typename MeshType::CoordType(0,0,0);
993  ++vi;
994 
995  for ( int j = 0; j < slices; ++j)
996  {
997  float x = cos( 2.0 * M_PI / slices * j);
998  float y = sin( 2.0 * M_PI / slices * j);
999 
1000  (*vi).P() = typename MeshType::CoordType(x,y,0);
1001  ++vi;
1002  }
1003  typename MeshType::FaceIterator fi ;
1004  for ( int j = 0; j < slices; ++j)
1005  {
1006  int a = 1+(j+0)%slices;
1007  int b = 1+(j+1)%slices;
1009  (*fi).V(0) = &m.vert[ 0 ];
1010  (*fi).V(1) = &m.vert[ a ];
1011  (*fi).V(2) = &m.vert[ b ];
1012  }
1013 }
1014 
1015 template <class MeshType>
1016 void OrientedDisk(MeshType &m, int slices, typename MeshType::CoordType center, typename MeshType::CoordType norm, float radius)
1017 {
1018  typedef typename MeshType::ScalarType ScalarType;
1019  typedef typename MeshType::CoordType CoordType;
1020 
1021  Disk(m,slices);
1022  tri::UpdatePosition<MeshType>::Scale(m,radius);
1023  ScalarType angleRad = Angle(CoordType(0,0,1),norm);
1024  CoordType axis = CoordType(0,0,1)^norm;
1025 
1026  Matrix44<ScalarType> rotM;
1027  rotM.SetRotateRad(angleRad,axis);
1029  tri::UpdatePosition<MeshType>::Translate(m,center);
1030 }
1031 
1032 template <class MeshType>
1033 void OrientedEllipticPrism(MeshType & m, const typename MeshType::CoordType origin, const typename MeshType::CoordType end, float radius, float xScale, float yScale,bool capped, int slices=32, int stacks=4 )
1034 {
1035  typedef typename MeshType::ScalarType ScalarType;
1036  typedef typename MeshType::CoordType CoordType;
1037  typedef Matrix44<typename MeshType::ScalarType> Matrix44x;
1038  Cylinder(slices,stacks,m,capped);
1039  tri::UpdatePosition<MeshType>::Translate(m,CoordType(0,1,0));
1040  tri::UpdatePosition<MeshType>::Scale(m,CoordType(1,0.5f,1));
1041  tri::UpdatePosition<MeshType>::Scale(m,CoordType(xScale,1.0f,yScale));
1042 
1043  float height = Distance(origin,end);
1044  tri::UpdatePosition<MeshType>::Scale(m,CoordType(radius,height,radius));
1045  CoordType norm = end-origin;
1046  ScalarType angleRad = Angle(CoordType(0,1,0),norm);
1047  const ScalarType Delta= 0.000000001;
1048  Matrix44x rotM;
1049  if (fabs(angleRad)<Delta)
1050  rotM.SetIdentity();
1051  else
1052  if (fabs(angleRad-M_PI)<Delta)
1053  {
1054  CoordType axis = CoordType(0,0,1)^norm;
1055  rotM.SetRotateRad(angleRad,axis);
1056  }
1057  else
1058  {
1059  CoordType axis = CoordType(0,1,0)^norm;
1060  rotM.SetRotateRad(angleRad,axis);
1061  }
1063  tri::UpdatePosition<MeshType>::Translate(m,origin);
1064 
1065 }
1066 
1067 template <class MeshType>
1068 void OrientedCylinder(MeshType & m, const typename MeshType::CoordType origin, const typename MeshType::CoordType end, float radius, bool capped, int slices=32, int stacks=4 )
1069 {
1070  OrientedEllipticPrism(m,origin,end,radius,1.0f,1.0f,capped,slices,stacks);
1071 }
1072 
1073 
1074 template <class MeshType>
1075 void Cylinder(int slices, int stacks, MeshType & m, bool capped=false)
1076 {
1077  m.Clear();
1078  typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices*(stacks+1));
1079  for ( int i = 0; i < stacks+1; ++i)
1080  for ( int j = 0; j < slices; ++j)
1081  {
1082  float x,y,h;
1083  x = cos( 2.0 * M_PI / slices * j);
1084  y = sin( 2.0 * M_PI / slices * j);
1085  h = 2 * i / (float)(stacks) - 1;
1086 
1087  (*vi).P() = typename MeshType::CoordType(x,h,y);
1088  ++vi;
1089  }
1090 
1091  for ( int j = 0; j < stacks; ++j)
1092  for ( int i = 0; i < slices; ++i)
1093  {
1094  int a,b,c,d;
1095  a = (j+0)*slices + i;
1096  b = (j+1)*slices + i;
1097  c = (j+1)*slices + (i+1)%slices;
1098  d = (j+0)*slices + (i+1)%slices;
1099  if(((i+j)%2) == 0){
1100  vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ a ], &m.vert[ b ], &m.vert[ c ]);
1101  vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ c ], &m.vert[ d ], &m.vert[ a ]);
1102  }
1103  else{
1104  vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ b ], &m.vert[ c ], &m.vert[ d ]);
1105  vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ d ], &m.vert[ a ], &m.vert[ b ]);
1106  }
1107  }
1108 
1109  if(capped)
1110  {
1111  tri::Allocator<MeshType>::AddVertex(m,typename MeshType::CoordType(0,-1,0));
1112  tri::Allocator<MeshType>::AddVertex(m,typename MeshType::CoordType(0, 1,0));
1113  int base = 0;
1114  for ( int i = 0; i < slices; ++i)
1115  vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ m.vn-2 ], &m.vert[ base+i ], &m.vert[ base+(i+1)%slices ]);
1116  base = (stacks)*slices;
1117  for ( int i = 0; i < slices; ++i)
1118  vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ m.vn-1 ], &m.vert[ base+(i+1)%slices ], &m.vert[ base+i ]);
1119  }
1120  if (HasPerFaceFlags(m)) {
1121  for (typename MeshType::FaceIterator fi=m.face.begin(); fi!=m.face.end(); fi++) {
1122  (*fi).SetF(2);
1123  }
1124  }
1125 }
1126 
1127 
1128 
1129 class _SphFace;
1130 class _SphVertex;
1131 struct _SphUsedTypes : public UsedTypes< Use<_SphVertex> ::AsVertexType,
1132  Use<_SphFace> ::AsFaceType>{};
1133 
1134 class _SphVertex : public Vertex<_SphUsedTypes, vertex::Coord3f, vertex::Normal3f, vertex::BitFlags >{};
1135 class _SphFace : public Face< _SphUsedTypes, face::VertexRef, face::Normal3f, face::BitFlags, face::FFAdj > {};
1136 class _SphMesh : public tri::TriMesh< std::vector<_SphVertex>, std::vector<_SphFace> > {};
1137 
1138 
1139 template <class MeshType>
1140 void BuildPrismFaceShell(MeshType &mIn, MeshType &mOut, float height=0, float inset=0, bool smoothFlag=false )
1141 {
1142  typedef typename MeshType::VertexPointer VertexPointer;
1143  typedef typename MeshType::FacePointer FacePointer;
1144  typedef typename MeshType::CoordType CoordType;
1145  if(height==0) height = mIn.bbox.Diag()/100.0f;
1146  if(inset==0) inset = mIn.bbox.Diag()/200.0f;
1150 
1151  for(size_t i=0;i<mIn.face.size();++i) if(!mIn.face[i].IsV())
1152  {
1153  MeshType faceM;
1154  std::vector<VertexPointer> vertVec;
1155  std::vector<FacePointer> faceVec;
1156  tri::PolygonSupport<MeshType,MeshType>::ExtractPolygon(&(mIn.face[i]),vertVec,faceVec);
1157  size_t vn = vertVec.size();
1158 
1159  CoordType nf(0,0,0);
1160  for(size_t j=0;j<faceVec.size();++j)
1161  nf+=vcg::NormalizedTriangleNormal(*faceVec[j]) * DoubleArea(*faceVec[j]);
1162  nf.Normalize();
1163  nf = nf*height/2.0f;
1164 
1165  CoordType bary(0,0,0);
1166  for(size_t j=0;j<faceVec.size();++j)
1167  bary+= Barycenter(*faceVec[j]);
1168  bary/=float(faceVec.size());
1169 
1170  // Add vertices (alternated top and bottom)
1171  tri::Allocator<MeshType>::AddVertex(faceM, bary+nf);
1172  tri::Allocator<MeshType>::AddVertex(faceM, bary-nf);
1173  for(size_t j=0;j<vn;++j){
1174  CoordType delta = (vertVec[j]->P() - bary);
1175  delta.Normalize();
1176  delta = delta*inset;
1177  tri::Allocator<MeshType>::AddVertex(faceM, vertVec[j]->P()-delta+nf);
1178  tri::Allocator<MeshType>::AddVertex(faceM, vertVec[j]->P()-delta-nf);
1179  }
1180 
1181  // Build top and bottom faces
1182  for(size_t j=0;j<vn;++j)
1183  tri::Allocator<MeshType>::AddFace(faceM, 0, 2+(j+0)*2, 2+((j+1)%vn)*2 );
1184  for(size_t j=0;j<vn;++j)
1185  tri::Allocator<MeshType>::AddFace(faceM, 1, 3+((j+1)%vn)*2, 3+(j+0)*2 );
1186 
1187  // Build side strip
1188  for(size_t j=0;j<vn;++j){
1189  size_t j0=j;
1190  size_t j1=(j+1)%vn;
1191  tri::Allocator<MeshType>::AddFace(faceM, 2+ j0*2 + 0 , 2+ j0*2+1, 2+j1*2+0);
1192  tri::Allocator<MeshType>::AddFace(faceM, 2+ j0*2 + 1 , 2+ j1*2+1, 2+j1*2+0);
1193  }
1194 
1195  for(size_t j=0;j<2*vn;++j)
1196  faceM.face[j].SetS();
1197 
1198  if(smoothFlag)
1199  {
1202  tri::Refine(faceM, MidPoint<MeshType>(&faceM),0,true);
1203  tri::Refine(faceM, MidPoint<MeshType>(&faceM),0,true);
1205  tri::Smooth<MeshType>::VertexCoordLaplacian(faceM,2,true,true);
1206  }
1207 
1209 
1210  } // end main loop for each face;
1211 }
1212 
1213 
1214 template <class MeshType>
1215 void BuildCylinderEdgeShell(MeshType &mIn, MeshType &mOut, float radius=0, int slices=16, int stacks=1 )
1216 {
1217  if(radius==0) radius = mIn.bbox.Diag()/100.0f;
1218  if (mIn.edge.size() > 0)
1219  {
1220  for (size_t i = 0; i < mIn.edge.size(); ++i) {
1221  MeshType mCyl;
1222  tri::OrientedCylinder(
1223  mCyl, mIn.edge[i].V(0)->P(), mIn.edge[i].V(1)->P(), radius, true, slices, stacks);
1225  }
1226  }
1227  else
1228  {
1229  typedef typename tri::UpdateTopology<MeshType>::PEdge PEdge;
1230  std::vector<PEdge> edgeVec;
1231  tri::UpdateTopology<MeshType>::FillUniqueEdgeVector(mIn, edgeVec, false);
1232  for (size_t i = 0; i < edgeVec.size(); ++i) {
1233  MeshType mCyl;
1234  tri::OrientedCylinder(
1235  mCyl, edgeVec[i].v[0]->P(), edgeVec[i].v[1]->P(), radius, true, slices, stacks);
1237  }
1238  }
1239 }
1240 
1241 template <class MeshType>
1242 void BuildSphereVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, int recDiv=2 )
1243 {
1244  if(radius==0) radius = mIn.bbox.Diag()/100.0f;
1245  for(size_t i=0;i<mIn.vert.size();++i)
1246  {
1247  MeshType mSph;
1248  tri::Sphere(mSph,recDiv);
1249  tri::UpdatePosition<MeshType>::Scale(mSph,radius);
1250  tri::UpdatePosition<MeshType>::Translate(mSph,mIn.vert[i].P());
1252  }
1253 }
1254 
1255 template <class MeshType>
1256 void BuildCylinderVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, float height=0, int slices=16, int stacks=1 )
1257 {
1258  typedef typename MeshType::CoordType CoordType;
1259  if(radius==0) radius = mIn.bbox.Diag()/100.0f;
1260  if(height==0) height = mIn.bbox.Diag()/200.0f;
1261  for(size_t i=0;i<mIn.vert.size();++i)
1262  {
1263  CoordType p = mIn.vert[i].P();
1264  CoordType n = mIn.vert[i].N().Normalize();
1265 
1266  MeshType mCyl;
1267  tri::OrientedCylinder(mCyl,p-n*height,p+n*height,radius,true,slices,stacks);
1269  }
1270 }
1271 
1272 
1273 template <class MeshType>
1274 void GenerateCameraMesh(MeshType &in){
1275  typedef typename MeshType::CoordType MV;
1276  MV vv[52]={
1277  MV(-0.000122145 , -0.2 ,0.35),
1278  MV(0.000122145 , -0.2 ,-0.35),MV(-0.000122145 , 0.2 ,0.35),MV(0.000122145 , 0.2 ,-0.35),MV(0.999878 , -0.2 ,0.350349),MV(1.00012 , -0.2 ,-0.349651),MV(0.999878 , 0.2 ,0.350349),MV(1.00012 , 0.2 ,-0.349651),MV(1.28255 , 0.1 ,0.754205),MV(1.16539 , 0.1 ,1.03705),MV(0.88255 , 0.1 ,1.15421),
1279  MV(0.599707 , 0.1 ,1.03705),MV(0.48255 , 0.1 ,0.754205),MV(0.599707 , 0.1 ,0.471362),MV(0.88255 , 0.1 ,0.354205),MV(1.16539 , 0.1 ,0.471362),MV(1.28255 , -0.1 ,0.754205),MV(1.16539 , -0.1 ,1.03705),MV(0.88255 , -0.1 ,1.15421),MV(0.599707 , -0.1 ,1.03705),MV(0.48255 , -0.1 ,0.754205),
1280  MV(0.599707 , -0.1 ,0.471362),MV(1.16539 , -0.1 ,0.471362),MV(0.88255 , -0.1 ,0.354205),MV(3.49164e-005 , 0 ,-0.1),MV(1.74582e-005 , -0.0866025 ,-0.05),MV(-1.74582e-005 , -0.0866025 ,0.05),MV(-3.49164e-005 , 8.74228e-009 ,0.1),MV(-1.74582e-005 , 0.0866025 ,0.05),MV(1.74582e-005 , 0.0866025 ,-0.05),MV(-0.399913 , 1.99408e-022 ,-0.25014),
1281  MV(-0.399956 , -0.216506 ,-0.12514),MV(-0.400044 , -0.216506 ,0.12486),MV(-0.400087 , 2.18557e-008 ,0.24986),MV(-0.400044 , 0.216506 ,0.12486),MV(-0.399956 , 0.216506 ,-0.12514),MV(0.479764 , 0.1 ,0.754205),MV(0.362606 , 0.1 ,1.03705),MV(0.0797637 , 0.1 ,1.15421),MV(-0.203079 , 0.1 ,1.03705),MV(-0.320236 , 0.1 ,0.754205),
1282  MV(-0.203079 , 0.1 ,0.471362),MV(0.0797637 , 0.1 ,0.354205),MV(0.362606 , 0.1 ,0.471362),MV(0.479764 , -0.1 ,0.754205),MV(0.362606 , -0.1 ,1.03705),MV(0.0797637 , -0.1 ,1.15421),MV(-0.203079 , -0.1 ,1.03705),MV(-0.320236 , -0.1 ,0.754205),MV(0.0797637 , -0.1 ,0.354205),MV(0.362606 , -0.1 ,0.471362),
1283  MV(-0.203079 , -0.1 ,0.471362), };
1284  int ff[88][3]={
1285  {0,2,3},
1286  {3,1,0},{4,5,7},{7,6,4},{0,1,5},{5,4,0},{1,3,7},{7,5,1},{3,2,6},{6,7,3},{2,0,4},
1287  {4,6,2},{10,9,8},{10,12,11},{10,13,12},{10,14,13},{10,15,14},{10,8,15},{8,17,16},{8,9,17},{9,18,17},
1288  {9,10,18},{10,19,18},{10,11,19},{11,20,19},{11,12,20},{12,21,20},{12,13,21},{13,23,21},{13,14,23},{14,22,23},
1289  {14,15,22},{15,16,22},{15,8,16},{23,16,17},{23,17,18},{23,18,19},{23,19,20},{23,20,21},{23,22,16},{25,27,26},
1290  {25,28,27},{25,29,28},{25,24,29},{24,31,30},{24,25,31},{25,32,31},{25,26,32},{26,33,32},{26,27,33},{27,34,33},
1291  {27,28,34},{28,35,34},{28,29,35},{29,30,35},{29,24,30},{35,30,31},{35,31,32},{35,32,33},{35,33,34},{42,37,36},
1292  {42,38,37},{42,39,38},{42,40,39},{42,41,40},{42,36,43},{36,45,44},{36,37,45},{37,46,45},{37,38,46},{38,47,46},
1293  {38,39,47},{39,48,47},{39,40,48},{40,51,48},{40,41,51},{41,49,51},{41,42,49},{42,50,49},{42,43,50},{43,44,50},
1294  {43,36,44},{51,44,45},{51,45,46},{51,46,47},{51,47,48},{51,49,50},{51,50,44},
1295  };
1296 
1297  in.Clear();
1300 
1301  in.vn=52;in.fn=88;
1302  int i,j;
1303  for(i=0;i<in.vn;i++)
1304  in.vert[i].P()=vv[i];;
1305 
1306  std::vector<typename MeshType::VertexPointer> index(in.vn);
1307 
1308  typename MeshType::VertexIterator vi;
1309  for(j=0,vi=in.vert.begin();j<in.vn;++j,++vi) index[j] = &*vi;
1310  for(j=0;j<in.fn;++j)
1311  {
1312  in.face[j].V(0)=index[ff[j][0]];
1313  in.face[j].V(1)=index[ff[j][1]];
1314  in.face[j].V(2)=index[ff[j][2]];
1315  }
1316 }
1317 
1318 template <class MeshType>
1319 void OrientedRect(MeshType &square, float width, float height, Point3f c, Point3f dir=Point3f(0,0,0), float angleDeg=0,Point3f preRotTra = Point3f(0,0,0))
1320 {
1321  float zeros[4]={0,0,0,0};
1322  square.Clear();
1323  Matrix44f rotM;
1324  tri::Grid(square,2,2,width,height,zeros);
1325  tri::UpdatePosition<MeshType>::Translate(square,Point3f(-width/2.0f,-height/2.0f,0.0f));
1326  if(angleDeg!=0){
1327  tri::UpdatePosition<MeshType>::Translate(square,preRotTra);
1328  rotM.SetRotateDeg(angleDeg,dir);
1330  }
1331  tri::UpdatePosition<MeshType>::Translate(square,c);
1333 }
1334 
1335 template <class MeshType>
1336 void OrientedSquare(MeshType &square, float width, Point3f c, Point3f dir=Point3f(0,0,0), float angleDeg=0,Point3f preRotTra = Point3f(0,0,0))
1337 {
1338  OrientedRect(square,width,width,c,dir,angleDeg,preRotTra);
1339 }
1340 
1341 
1342 
1344 
1345 } // End Namespace TriMesh
1346 } // End Namespace vcg
1347 #endif
Class to safely add and delete elements in a mesh.
Definition: allocate.h:97
static VertexIterator AddVertex(MeshType &m, const CoordType &p)
Wrapper to AddVertices() to add a single vertex with given coords.
Definition: allocate.h:295
static void DeleteVertex(MeshType &m, VertexType &v)
Definition: allocate.h:935
static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater< VertexPointer > &pu)
Add n vertices to the mesh. Function to add n vertices to the mesh. The elements are added always to ...
Definition: allocate.h:189
static FaceIterator AddFaces(MeshType &m, size_t n)
Function to add n faces to the mesh. First wrapper, with no parameters.
Definition: allocate.h:615
static EdgeIterator AddEdge(MeshType &m, VertexPointer v0, VertexPointer v1)
Definition: allocate.h:387
static FaceIterator AddFace(MeshType &m, VertexPointer v0, VertexPointer v1, VertexPointer v2)
Definition: allocate.h:539
static void MeshCopy(MeshLeft &ml, ConstMeshRight &mr, bool selected=false, const bool adjFlag=false)
Copy the second mesh over the first one. The first mesh is destroyed. If requested only the selected ...
Definition: append.h:601
static void Mesh(MeshLeft &ml, ConstMeshRight &mr, const bool selected=false, const bool adjFlag=false)
Append the second mesh to the first one.
Definition: append.h:253
Class of static functions to clean//restore meshs.
Definition: clean.h:165
static int RemoveDuplicateVertex(MeshType &m, bool RemoveDegenerateFlag=true)
Definition: clean.h:206
static int MergeCloseVertex(MeshType &m, const ScalarType radius)
Definition: clean.h:1873
static void Box(ComputeMeshType &m)
Calculates the bounding box of the given mesh m.
Definition: bounding.h:45
Management, updating and computation of per-vertex and per-face flags (like border flags).
Definition: flag.h:44
static void VertexBorderFromFaceBorder(MeshType &m)
Compute the PerVertex Border flag deriving it from the border flag of faces.
Definition: flag.h:428
static void FaceBorderFromFF(MeshType &m)
Compute the border flags for the faces using the Face-Face Topology.
Definition: flag.h:170
static void PerVertexNormalizedPerFace(ComputeMeshType &m)
Equivalent to PerVertexNormalized() and PerFace().
Definition: normal.h:296
This class is used to update vertex position according to a transformation matrix.
Definition: position.h:47
static void Matrix(ComputeMeshType &m, const Matrix44< ScalarType > &M, bool update_also_normals=true)
Multiply.
Definition: position.h:60
static size_t VertexInvert(MeshType &m)
This function inverts the selection flag for all the vertices.
Definition: selection.h:352
static void Clear(MeshType &m)
This function clears the selection flag for all the elements of a mesh (vertices, edges,...
Definition: selection.h:271
static size_t VertexFromFaceStrict(MeshType &m, bool preserveSelection=false)
Select ONLY the vertices that are touched ONLY by selected faces.
Definition: selection.h:416
static size_t VertexFromBorderFlag(MeshType &m, bool preserveSelection=false)
This function select the vertices with the border flag set.
Definition: selection.h:493
static void FaceFace(MeshType &m)
Update the Face-Face topological relation by allowing to retrieve for each face what other faces shar...
Definition: topology.h:395
Definition: platonic.h:1135
Definition: platonic.h:1136
Definition: platonic.h:1134
void BuildMeshFromCoordVectorIndexVector(MeshType &in, const std::vector< InCoordType > &v, const std::vector< InFaceIndexType > &f)
Definition: platonic.h:741
void Cone(MeshType &in, const typename MeshType::ScalarType r1, const typename MeshType::ScalarType r2, const typename MeshType::ScalarType h, const int SubDiv=36)
r1 = raggio 1, r2 = raggio2, h = altezza (asse y)
Definition: platonic.h:443
void Dodecahedron(DodMeshType &in)
Definition: platonic.h:78
void SuperEllipsoid(MeshType &m, float rFeature, float sFeature, float tFeature, int hRingDiv=24, int vRingDiv=12)
Definition: platonic.h:702
void SuperToroid(MeshType &m, float hRingRadius, float vRingRadius, float vSquareness, float hSquareness, int hRingDiv=24, int vRingDiv=12)
Definition: platonic.h:665
void Tetrahedron(TetraMeshType &in)
Definition: platonic.h:49
Definition: namespaces.dox:6
Definition: platonic.h:1132