1 /****************************************************************************
2 * VCGLib                                                            o o     *
3 * Visual and Computer Graphics Library                            o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2004                                                \/)\/    *
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   History
25 
26 $Log: not supported by cvs2svn $
27 Revision 1.13  2008/02/15 14:38:32  ganovelli
28 added Cylinder(..). the filename platonic.h is lesser and lesser significant...
29 
30 Revision 1.12  2007/10/19 22:29:36  cignoni
31 Re-Wrote basic build function
32 
33 Revision 1.11  2007/02/01 06:38:27  cignoni
34 Added small comment to grid function
35 
36 Revision 1.10  2007/01/27 13:14:34  marfr960
37 Removed unuseful CoordType test
38 
39 Revision 1.9  2006/08/23 15:29:44  marfr960
40 *** empty log message ***
41 
42 Revision 1.8  2006/03/27 04:18:35  cignoni
43 Double->Scalar in dodecahedron
44 
45 Revision 1.7  2006/01/30 08:09:05  cignoni
46 Corrected Grid
47 
48 Revision 1.6  2006/01/22 17:10:15  cignoni
49 Added Grid function (to build range map meshes...)
50 
51 Revision 1.5  2005/07/11 13:16:34  cignoni
52 small gcc-related compiling issues (typenames,ending cr, initialization order)
53 
54 Revision 1.4  2005/07/01 11:17:06  cignoni
55 Added option of passing a base mesh to Sphere for spherifying it
56 
57 Revision 1.3  2005/06/17 00:49:29  cignoni
58 Added missing Sphere function
59 
60 Revision 1.2  2005/02/25 11:41:08  pietroni
61 Fixed bug in Square
62 
63 Revision 1.1  2005/01/19 15:43:15  fiorin
64 Moved from vcg/complex/trimesh to vcg/complex/algorithms/create
65 
66 Revision 1.10  2004/10/28 00:54:34  cignoni
67 Better Doxygen documentation
68 
69 Revision 1.9  2004/09/24 10:14:38  fiorin
70 Corrected bug in cone
71 
72 Revision 1.8  2004/09/22 15:12:38  fiorin
73 Corrected bug in hexahedron
74 
75 Revision 1.7  2004/07/09 15:34:29  tarini
76 Dodecahedron added! (and doxigened a little bit)
77 
78 Revision 1.6  2004/05/13 21:08:00  cignoni
79 Conformed C++ syntax to GCC requirements
80 
81 Revision 1.5  2004/03/18 15:29:07  cignoni
82 Completed Octahedron and Icosahedron
83 
84 Revision 1.2  2004/03/03 16:11:46  cignoni
85 First working version (tetrahedron!)
86 
87 
88 ****************************************************************************/
89 
90 #ifndef __VCGLIB_PLATONIC
91 #define __VCGLIB_PLATONIC
92 
93 #include<vcg/math/base.h>
94 #include<vcg/complex/allocate.h>
95 #include<vcg/complex/algorithms/refine.h>
96 #include<vcg/complex/algorithms/update/flag.h>
97 
98 namespace vcg {
99 namespace tri {
100 /** \addtogroup trimesh */
101 //@{
102     /**
103         A set of functions that builds meshes
104         that represent surfaces of platonic solids,
105 				and other simple shapes.
106 
107 				 The 1st parameter is the mesh that will
108 				be filled with the solid.
109 		*/
110 template <class TetraMeshType>
Tetrahedron(TetraMeshType & in)111 void Tetrahedron(TetraMeshType &in)
112 {
113  typedef TetraMeshType MeshType;
114  typedef typename TetraMeshType::CoordType CoordType;
115  typedef typename TetraMeshType::VertexPointer  VertexPointer;
116  typedef typename TetraMeshType::VertexIterator VertexIterator;
117  typedef typename TetraMeshType::FaceIterator   FaceIterator;
118 
119  in.Clear();
120  Allocator<TetraMeshType>::AddVertices(in,4);
121  Allocator<TetraMeshType>::AddFaces(in,4);
122 
123  VertexPointer ivp[4];
124  VertexIterator vi=in.vert.begin();
125  ivp[0]=&*vi;vi->P()=CoordType ( 1.0, 1.0, 1.0); ++vi;
126  ivp[1]=&*vi;vi->P()=CoordType (-1.0, 1.0,-1.0); ++vi;
127  ivp[2]=&*vi;vi->P()=CoordType (-1.0,-1.0, 1.0); ++vi;
128  ivp[3]=&*vi;vi->P()=CoordType ( 1.0,-1.0,-1.0);
129 
130  FaceIterator fi=in.face.begin();
131  fi->V(0)=ivp[0];  fi->V(1)=ivp[1]; fi->V(2)=ivp[2]; ++fi;
132  fi->V(0)=ivp[0];  fi->V(1)=ivp[2]; fi->V(2)=ivp[3]; ++fi;
133  fi->V(0)=ivp[0];  fi->V(1)=ivp[3]; fi->V(2)=ivp[1]; ++fi;
134  fi->V(0)=ivp[3];  fi->V(1)=ivp[2]; fi->V(2)=ivp[1];
135 }
136 
137 
138 /// builds a Dodecahedron,
139 /// (each pentagon is composed of 5 triangles)
140 template <class DodMeshType>
Dodecahedron(DodMeshType & in)141 void Dodecahedron(DodMeshType & in)
142 {
143  typedef DodMeshType MeshType;
144  typedef typename MeshType::CoordType CoordType;
145  typedef typename MeshType::VertexPointer  VertexPointer;
146  typedef typename MeshType::VertexIterator VertexIterator;
147  typedef typename MeshType::FaceIterator   FaceIterator;
148  typedef typename MeshType::ScalarType     ScalarType;
149  const int N_penta=12;
150  const int N_points=62;
151 
152  int penta[N_penta*3*3]=
153 	{20,11, 18,  18, 11,  8,  8, 11,  4,
154 		13,23,  4,  4, 23,  8,  8, 23, 16,
155     13, 4, 30, 30,  4, 28, 28, 4,  11,
156     16,34,  8,  8, 34, 18, 18, 34, 36,
157     11,20, 28, 28, 20, 45, 45, 20, 38,
158     13,30, 23, 23, 30, 41, 41, 30, 47,
159     16,23, 34, 34, 23, 50, 50, 23, 41,
160     20,18, 38, 38, 18, 52, 52, 18, 36,
161     30,28, 47, 47, 28, 56, 56, 28, 45,
162     50,60, 34, 34, 60, 36, 36, 60, 52,
163     45,38, 56, 56, 38, 60, 60, 38, 52,
164     50,41, 60, 60, 41, 56, 56, 41, 47 };
165    //A B   E                D       C
166   const ScalarType p=(1.0 + math::Sqrt(5.0)) / 2.0;
167   const ScalarType p2=p*p;
168   const ScalarType p3=p*p*p;
169 	ScalarType vv[N_points*3]=
170 	{
171    0, 0, 2*p2,     p2, 0, p3,      p, p2, p3,
172    0, p, p3,       -p, p2, p3,     -p2, 0, p3,
173    -p, -p2, p3,    0,   -p, p3,    p,  -p2, p3,
174    p3,  p, p2,     p2,  p2, p2,    0,   p3, p2,
175    -p2, p2, p2,    -p3, p, p2,     -p3, -p, p2,
176    -p2, -p2, p2,   0, -p3, p2,     p2, -p2, p2,
177    p3, -p, p2,     p3, 0, p,       p2, p3, p,
178    -p2, p3, p,     -p3, 0, p,      -p2, -p3, p,
179    p2, -p3, p,     2*p2, 0, 0,     p3, p2, 0,
180    p, p3, 0,       0, 2*p2, 0,     -p, p3, 0,
181    -p3, p2, 0,     -2*p2, 0, 0,    -p3, -p2, 0,
182    -p, -p3, 0,     0, -2*p2, 0,    p, -p3, 0,
183    p3, -p2, 0,     p3, 0, -p,      p2, p3, -p,
184    -p2, p3, -p,    -p3, 0, -p,     -p2, -p3, -p,
185    p2, -p3, -p,    p3, p, -p2,     p2, p2, -p2,
186    0, p3, -p2,     -p2, p2, -p2,   -p3, p, -p2,
187    -p3, -p, -p2,   -p2, -p2, -p2,  0, -p3, -p2,
188    p2, -p2, -p2,   p3, -p, -p2,    p2, 0, -p3,
189    p, p2, -p3,     0, p, -p3,      -p, p2, -p3,
190    -p2, 0, -p3,    -p, -p2, -p3,   0, -p, -p3,
191    p, -p2, -p3,    0, 0, -2*p2
192 	};
193 	in.Clear();
194 	//in.face.clear();
195   Allocator<DodMeshType>::AddVertices(in,20+12);
196   Allocator<DodMeshType>::AddFaces(in, 5*12); // five pentagons, each made by 5 tri
197 
198   int h,i,j,m=0;
199 
200 	bool used[N_points];
201 	for (i=0; i<N_points; i++) used[i]=false;
202 
203 	int reindex[20+12 *10];
204 	ScalarType xx,yy,zz, sx,sy,sz;
205 
206 	int order[5]={0,1,8,6,2};
207 	int added[12];
208 
209 	VertexIterator vi=in.vert.begin();
210 
211 	for (i=0; i<12; i++) {
212 		sx=sy=sz=0;
213 		for (int j=0; j<5; j++) {
214 			h= penta[ i*9 + order[j]  ]-1;
215 		  xx=vv[h*3];yy=vv[h*3+1];zz=vv[h*3+2]; sx+=xx; sy+=yy; sz+=zz;
216 			if (!used[h]) {
217                                 vi->P()=CoordType( xx, yy, zz ); vi++;
218 				used[h]=true;
219 				reindex[ h ] = m++;
220 			}
221 		}
222                 vi->P()=CoordType( sx/5.0, sy/5.0, sz/5.0 ); 	vi++;
223 		added[ i ] = m++;
224 	}
225 
226   std::vector<VertexPointer> index(in.vn);
227 
228 	for(j=0,vi=in.vert.begin();j<in.vn;++j,++vi)	index[j] = &(*vi);
229 
230   FaceIterator fi=in.face.begin();
231 
232 	for (i=0; i<12; i++) {
233 		for (j=0; j<5; j++){
234                   fi->V(0)=index[added[i] ];
235             fi->V(1)=index[reindex[penta[i*9 + order[j      ] ] -1 ] ];
236             fi->V(2)=index[reindex[penta[i*9 + order[(j+1)%5] ] -1 ] ];
237 	    if (in.HasPerFaceFlags()) {
238   	    // tag faux edges
239         fi->SetF(0);
240         fi->SetF(2);
241       }
242 		  fi++;
243 		}
244 	}
245 }
246 
247 template <class OctMeshType>
Octahedron(OctMeshType & in)248 void Octahedron(OctMeshType &in)
249 {
250  typedef OctMeshType MeshType;
251  typedef typename MeshType::CoordType CoordType;
252  typedef typename MeshType::VertexPointer  VertexPointer;
253  typedef typename MeshType::VertexIterator VertexIterator;
254  typedef typename MeshType::FaceIterator   FaceIterator;
255 
256  in.Clear();
257  Allocator<OctMeshType>::AddVertices(in,6);
258  Allocator<OctMeshType>::AddFaces(in,8);
259 
260  VertexPointer ivp[6];
261 
262  VertexIterator vi=in.vert.begin();
263  ivp[0]=&*vi;vi->P()=CoordType ( 1, 0, 0); ++vi;
264  ivp[1]=&*vi;vi->P()=CoordType ( 0, 1, 0); ++vi;
265  ivp[2]=&*vi;vi->P()=CoordType ( 0, 0, 1); ++vi;
266  ivp[3]=&*vi;vi->P()=CoordType (-1, 0, 0); ++vi;
267  ivp[4]=&*vi;vi->P()=CoordType ( 0,-1, 0); ++vi;
268  ivp[5]=&*vi;vi->P()=CoordType ( 0, 0,-1);
269 
270  FaceIterator fi=in.face.begin();
271  fi->V(0)=ivp[0];  fi->V(1)=ivp[1]; fi->V(2)=ivp[2]; ++fi;
272  fi->V(0)=ivp[0];  fi->V(1)=ivp[2]; fi->V(2)=ivp[4]; ++fi;
273  fi->V(0)=ivp[0];  fi->V(1)=ivp[4]; fi->V(2)=ivp[5]; ++fi;
274  fi->V(0)=ivp[0];  fi->V(1)=ivp[5]; fi->V(2)=ivp[1]; ++fi;
275  fi->V(0)=ivp[3];  fi->V(1)=ivp[1]; fi->V(2)=ivp[5]; ++fi;
276  fi->V(0)=ivp[3];  fi->V(1)=ivp[5]; fi->V(2)=ivp[4]; ++fi;
277  fi->V(0)=ivp[3];  fi->V(1)=ivp[4]; fi->V(2)=ivp[2]; ++fi;
278  fi->V(0)=ivp[3];  fi->V(1)=ivp[2]; fi->V(2)=ivp[1];
279 }
280 
281 template <class IcoMeshType>
Icosahedron(IcoMeshType & in)282 void Icosahedron(IcoMeshType &in)
283 {
284  typedef IcoMeshType MeshType;
285  typedef typename MeshType::ScalarType ScalarType;
286  typedef typename MeshType::CoordType CoordType;
287  typedef typename MeshType::VertexPointer  VertexPointer;
288  typedef typename MeshType::VertexIterator VertexIterator;
289  typedef typename MeshType::FaceIterator   FaceIterator;
290 
291   ScalarType L=ScalarType((math::Sqrt(5.0)+1.0)/2.0);
292 	CoordType vv[12]={
293 	CoordType ( 0, L, 1),
294 	CoordType ( 0, L,-1),
295 	CoordType ( 0,-L, 1),
296 	CoordType ( 0,-L,-1),
297 
298 	CoordType ( L, 1, 0),
299 	CoordType ( L,-1, 0),
300 	CoordType (-L, 1, 0),
301 	CoordType (-L,-1, 0),
302 
303 	CoordType ( 1, 0, L),
304 	CoordType (-1, 0, L),
305 	CoordType ( 1, 0,-L),
306 	CoordType (-1, 0,-L)
307 	};
308 
309 	int ff[20][3]={
310 		{1,0,4},{0,1,6},{2,3,5},{3,2,7},
311 		{4,5,10},{5,4,8},{6,7,9},{7,6,11},
312 		{8,9,2},{9,8,0},{10,11,1},{11,10,3},
313 		{0,8,4},{0,6,9},{1,4,10},{1,11,6},
314 		{2,5,8},{2,9,7},{3,10,5},{3,7,11}
315 	};
316 
317 
318   in.Clear();
319   Allocator<IcoMeshType>::AddVertices(in,12);
320   Allocator<IcoMeshType>::AddFaces(in,20);
321   VertexPointer ivp[12];
322 
323   VertexIterator vi;
324   int i;
325   for(i=0,vi=in.vert.begin();vi!=in.vert.end();++i,++vi){
326     vi->P()=vv[i];
327 	  ivp[i]=&*vi;
328   }
329 
330  FaceIterator fi;
331  for(i=0,fi=in.face.begin();fi!=in.face.end();++i,++fi){
332                 fi->V(0)=ivp[ff[i][0]];
333                 fi->V(1)=ivp[ff[i][1]];
334                 fi->V(2)=ivp[ff[i][2]];
335 	}
336 }
337 
338 template <class MeshType>
Hexahedron(MeshType & in)339 void Hexahedron(MeshType &in)
340 {
341  typedef typename MeshType::ScalarType ScalarType;
342  typedef typename MeshType::CoordType CoordType;
343  typedef typename MeshType::VertexPointer  VertexPointer;
344  typedef typename MeshType::VertexIterator VertexIterator;
345  typedef typename MeshType::FaceIterator   FaceIterator;
346 
347  in.Clear();
348  Allocator<MeshType>::AddVertices(in,8);
349  Allocator<MeshType>::AddFaces(in,12);
350 
351  VertexPointer ivp[8];
352 
353  VertexIterator vi=in.vert.begin();
354 
355  ivp[7]=&*vi;vi->P()=CoordType (-1,-1,-1); ++vi;
356  ivp[6]=&*vi;vi->P()=CoordType ( 1,-1,-1); ++vi;
357  ivp[5]=&*vi;vi->P()=CoordType (-1, 1,-1); ++vi;
358  ivp[4]=&*vi;vi->P()=CoordType ( 1, 1,-1); ++vi;
359  ivp[3]=&*vi;vi->P()=CoordType (-1,-1, 1); ++vi;
360  ivp[2]=&*vi;vi->P()=CoordType ( 1,-1, 1); ++vi;
361  ivp[1]=&*vi;vi->P()=CoordType (-1, 1, 1); ++vi;
362  ivp[0]=&*vi;vi->P()=CoordType ( 1, 1, 1);
363 
364  FaceIterator fi=in.face.begin();
365  fi->V(0)=ivp[0];  fi->V(1)=ivp[1]; fi->V(2)=ivp[2]; ++fi;
366  fi->V(0)=ivp[3];  fi->V(1)=ivp[2]; fi->V(2)=ivp[1]; ++fi;
367  fi->V(0)=ivp[0];  fi->V(1)=ivp[2]; fi->V(2)=ivp[4]; ++fi;
368  fi->V(0)=ivp[6];  fi->V(1)=ivp[4]; fi->V(2)=ivp[2]; ++fi;
369  fi->V(0)=ivp[0];  fi->V(1)=ivp[4]; fi->V(2)=ivp[1]; ++fi;
370  fi->V(0)=ivp[5];  fi->V(1)=ivp[1]; fi->V(2)=ivp[4]; ++fi;
371  fi->V(0)=ivp[7];  fi->V(1)=ivp[5]; fi->V(2)=ivp[6]; ++fi;
372  fi->V(0)=ivp[4];  fi->V(1)=ivp[6]; fi->V(2)=ivp[5]; ++fi;
373  fi->V(0)=ivp[7];  fi->V(1)=ivp[6]; fi->V(2)=ivp[3]; ++fi;
374  fi->V(0)=ivp[2];  fi->V(1)=ivp[3]; fi->V(2)=ivp[6]; ++fi;
375  fi->V(0)=ivp[7];  fi->V(1)=ivp[3]; fi->V(2)=ivp[5]; ++fi;
376  fi->V(0)=ivp[1];  fi->V(1)=ivp[5]; fi->V(2)=ivp[3];
377 
378   if (in.HasPerFaceFlags()) {
379     FaceIterator fi=in.face.begin();
380     for (int k=0; k<12; k++) {
381       fi->SetF(1); fi++;
382     }
383   }
384 
385 }
386 
387 // Create an hexahedron with a vertex in the middle of every face
388 template <class MeshType>
HexahedronStar(MeshType & in)389 void HexahedronStar(MeshType &in)
390 {
391  typedef typename MeshType::ScalarType ScalarType;
392  typedef typename MeshType::CoordType CoordType;
393  typedef typename MeshType::VertexPointer  VertexPointer;
394  typedef typename MeshType::VertexIterator VertexIterator;
395  typedef typename MeshType::FaceIterator   FaceIterator;
396 
397  in.Clear();
398  Allocator<MeshType>::AddVertices(in,14);
399  Allocator<MeshType>::AddFaces(in,24);
400 
401  VertexPointer ivp[14];
402 
403  VertexIterator vi=in.vert.begin();
404 
405  ivp[13]=&*vi;vi->P()=CoordType ( 0, 0,-1); ++vi;
406  ivp[12]=&*vi;vi->P()=CoordType ( 0, 0, 1); ++vi;
407  ivp[11]=&*vi;vi->P()=CoordType (-1, 0, 0); ++vi;
408  ivp[10]=&*vi;vi->P()=CoordType ( 1, 0, 0); ++vi;
409  ivp[9] =&*vi;vi->P()=CoordType ( 0,-1, 0); ++vi;
410  ivp[8] =&*vi;vi->P()=CoordType ( 0, 1, 0); ++vi;
411  ivp[7] =&*vi;vi->P()=CoordType (-1,-1,-1); ++vi;
412  ivp[6] =&*vi;vi->P()=CoordType ( 1,-1,-1); ++vi;
413  ivp[5] =&*vi;vi->P()=CoordType (-1, 1,-1); ++vi;
414  ivp[4] =&*vi;vi->P()=CoordType ( 1, 1,-1); ++vi;
415  ivp[3] =&*vi;vi->P()=CoordType (-1,-1, 1); ++vi;
416  ivp[2] =&*vi;vi->P()=CoordType ( 1,-1, 1); ++vi;
417  ivp[1] =&*vi;vi->P()=CoordType (-1, 1, 1); ++vi;
418  ivp[0] =&*vi;vi->P()=CoordType ( 1, 1, 1);
419 
420  FaceIterator fi=in.face.begin();
421  fi->V(0)=ivp[8];  fi->V(1)=ivp[0]; fi->V(2)=ivp[4]; ++fi;
422  fi->V(0)=ivp[8];  fi->V(1)=ivp[4]; fi->V(2)=ivp[5]; ++fi;
423  fi->V(0)=ivp[8];  fi->V(1)=ivp[5]; fi->V(2)=ivp[1]; ++fi;
424  fi->V(0)=ivp[8];  fi->V(1)=ivp[1]; fi->V(2)=ivp[0]; ++fi;
425 
426  fi->V(0)=ivp[10];  fi->V(1)=ivp[0]; fi->V(2)=ivp[2]; ++fi;
427  fi->V(0)=ivp[10];  fi->V(1)=ivp[2]; fi->V(2)=ivp[6]; ++fi;
428  fi->V(0)=ivp[10];  fi->V(1)=ivp[6]; fi->V(2)=ivp[4]; ++fi;
429  fi->V(0)=ivp[10];  fi->V(1)=ivp[4]; fi->V(2)=ivp[0]; ++fi;
430 
431  fi->V(0)=ivp[12];  fi->V(1)=ivp[0]; fi->V(2)=ivp[1]; ++fi;
432  fi->V(0)=ivp[12];  fi->V(1)=ivp[1]; fi->V(2)=ivp[3]; ++fi;
433  fi->V(0)=ivp[12];  fi->V(1)=ivp[3]; fi->V(2)=ivp[2]; ++fi;
434  fi->V(0)=ivp[12];  fi->V(1)=ivp[2]; fi->V(2)=ivp[0]; ++fi;
435 
436  fi->V(0)=ivp[11];  fi->V(1)=ivp[1]; fi->V(2)=ivp[3]; ++fi;
437  fi->V(0)=ivp[11];  fi->V(1)=ivp[3]; fi->V(2)=ivp[7]; ++fi;
438  fi->V(0)=ivp[11];  fi->V(1)=ivp[7]; fi->V(2)=ivp[5]; ++fi;
439  fi->V(0)=ivp[11];  fi->V(1)=ivp[5]; fi->V(2)=ivp[1]; ++fi;
440 
441  fi->V(0)=ivp[13];  fi->V(1)=ivp[4]; fi->V(2)=ivp[5]; ++fi;
442  fi->V(0)=ivp[13];  fi->V(1)=ivp[5]; fi->V(2)=ivp[7]; ++fi;
443  fi->V(0)=ivp[13];  fi->V(1)=ivp[7]; fi->V(2)=ivp[6]; ++fi;
444  fi->V(0)=ivp[13];  fi->V(1)=ivp[6]; fi->V(2)=ivp[4]; ++fi;
445 
446  fi->V(0)=ivp[9];  fi->V(1)=ivp[2]; fi->V(2)=ivp[3]; ++fi;
447  fi->V(0)=ivp[9];  fi->V(1)=ivp[3]; fi->V(2)=ivp[7]; ++fi;
448  fi->V(0)=ivp[9];  fi->V(1)=ivp[7]; fi->V(2)=ivp[6]; ++fi;
449  fi->V(0)=ivp[9];  fi->V(1)=ivp[6]; fi->V(2)=ivp[2]; ++fi;
450 
451   if (in.HasPerFaceFlags()) {
452     FaceIterator fi=in.face.begin();
453     for (int k=0; k<24; k++) {
454       fi->SetF(1); fi++;
455     }
456   }
457 
458 }
459 
460 template <class MeshType>
Square(MeshType & in)461 void Square(MeshType &in)
462 {
463   typedef typename MeshType::ScalarType ScalarType;
464   typedef typename MeshType::CoordType CoordType;
465   typedef typename MeshType::VertexPointer  VertexPointer;
466   typedef typename MeshType::VertexIterator VertexIterator;
467   typedef typename MeshType::FaceIterator   FaceIterator;
468 
469   in.Clear();
470   Allocator<MeshType>::AddVertices(in,4);
471   Allocator<MeshType>::AddFaces(in,2);
472 
473   VertexPointer ivp[4];
474 
475   VertexIterator vi=in.vert.begin();
476   ivp[0]=&*vi;vi->P()=CoordType ( 1, 0, 0); ++vi;
477   ivp[1]=&*vi;vi->P()=CoordType ( 0, 1, 0); ++vi;
478   ivp[2]=&*vi;vi->P()=CoordType (-1, 0, 0); ++vi;
479   ivp[3]=&*vi;vi->P()=CoordType ( 0,-1, 0);
480 
481   FaceIterator fi=in.face.begin();
482   fi->V(0)=ivp[0];  fi->V(1)=ivp[1]; fi->V(2)=ivp[2]; ++fi;
483   fi->V(0)=ivp[2];  fi->V(1)=ivp[3]; fi->V(2)=ivp[0];
484 
485   if (in.HasPerFaceFlags()) {
486     FaceIterator fi=in.face.begin();
487     for (int k=0; k<2; k++) {
488       fi->SetF(2); fi++;
489     }
490   }
491 }
492 
493 // this function build a sphere starting from a eventually not empty mesh.
494 // If the mesh is not empty it is 'spherified' and used as base for the subdivision process.
495 // otherwise an icosahedron is used.
496 template <class MeshType>
497 void Sphere(MeshType &in, const int subdiv = 3 )
498 {
499  typedef typename MeshType::ScalarType ScalarType;
500  typedef typename MeshType::CoordType CoordType;
501  typedef typename MeshType::VertexPointer  VertexPointer;
502  typedef typename MeshType::VertexIterator VertexIterator;
503  typedef typename MeshType::FaceIterator   FaceIterator;
504 	if(in.vn==0 && in.fn==0) Icosahedron(in);
505 
506 	VertexIterator vi;
507 	for(vi = in.vert.begin(); vi!=in.vert.end();++vi)
508 		vi->P().Normalize();
509 
510 	tri::UpdateFlags<MeshType>::FaceBorderFromNone(in);
511 	tri::UpdateTopology<MeshType>::FaceFace(in);
512 
513 	size_t lastsize = 0;
514 	for(int i = 0 ; i < subdiv; ++i)
515 	{
516 		Refine< MeshType, MidPoint<MeshType> >(in, MidPoint<MeshType>(&in), 0);
517 
518 		for(vi = in.vert.begin() + lastsize; vi != in.vert.end(); ++vi)
519 			vi->P().Normalize();
520 
521 		lastsize = in.vert.size();
522 	}
523 }
524 
525 
526 	/// r1 = raggio 1, r2 = raggio2, h = altezza (asse y)
527 template <class MeshType>
Cone(MeshType & in,const typename MeshType::ScalarType r1,const typename MeshType::ScalarType r2,const typename MeshType::ScalarType h)528 void Cone( MeshType& in,
529 		  const typename MeshType::ScalarType r1,
530 		  const typename MeshType::ScalarType r2,
531 		  const typename MeshType::ScalarType h  )
532 {
533  typedef typename MeshType::ScalarType ScalarType;
534  typedef typename MeshType::CoordType CoordType;
535  typedef typename MeshType::VertexPointer  VertexPointer;
536  typedef typename MeshType::VertexIterator VertexIterator;
537  typedef typename MeshType::FaceIterator   FaceIterator;
538 
539  const int D = 24;
540 	int i,b1,b2;
541   in.Clear();
542   int VN,FN;
543 	if(r1==0 || r2==0) {
544 		VN=D+2;
545 		FN=D*2;
546 	}	else {
547 		VN=D*2+2;
548 		FN=D*4;
549 	}
550 
551   Allocator<MeshType>::AddVertices(in,VN);
552   Allocator<MeshType>::AddFaces(in,FN);
553 	VertexPointer  *ivp = new VertexPointer[VN];
554 
555   VertexIterator vi=in.vert.begin();
556   ivp[0]=&*vi;vi->P()=CoordType ( 0,-h/2,0 ); ++vi;
557   ivp[1]=&*vi;vi->P()=CoordType ( 0, h/2,0 ); ++vi;
558 
559 	b1 = b2 = 2;
560  int cnt=2;
561 	if(r1!=0)
562 	{
563 		for(i=0;i<D;++i)
564 		{
565 			double a = i*3.14159265358979323846*2/D;
566 			double s = sin(a);
567 			double c = cos(a);
568 			double x,y,z;
569 			x = r1*c;
570 			z = r1*s;
571 			y = -h/2;
572 
573       ivp[cnt]=&*vi; vi->P()= CoordType( x,y,z ); ++vi;++cnt;
574 		}
575 		b2 += D;
576 	}
577 
578 	if(r2!=0)
579 	{
580 		for(i=0;i<D;++i)
581 		{
582 			double a = i*3.14159265358979323846*2/D;
583 			double s = sin(a);
584 			double c = cos(a);
585 			double x,y,z;
586 			x = r2*c;
587 			z = r2*s;
588 			y =  h/2;
589 
590       ivp[cnt]=&*vi; vi->P()= CoordType( x,y,z ); ++vi;++cnt;
591   		}
592 	}
593 
594   FaceIterator fi=in.face.begin();
595 
596   if(r1!=0) for(i=0;i<D;++i,++fi)	{
597       fi->V(0)=ivp[0];
598       fi->V(1)=ivp[b1+i];
599       fi->V(2)=ivp[b1+(i+1)%D];
600 		}
601 
602 	if(r2!=0) for(i=0;i<D;++i,++fi) {
603       fi->V(0)=ivp[1];
604       fi->V(2)=ivp[b2+i];
605       fi->V(1)=ivp[b2+(i+1)%D];
606 		}
607 
608 	if(r1==0) for(i=0;i<D;++i,++fi)
609 		{
610       fi->V(0)=ivp[0];
611       fi->V(1)=ivp[b2+i];
612       fi->V(2)=ivp[b2+(i+1)%D];
613 			//in.face.push_back(*fi);
614 		}
615   if(r2==0)	for(i=0;i<D;++i,++fi){
616       fi->V(0)=ivp[1];
617       fi->V(2)=ivp[b1+i];
618       fi->V(1)=ivp[b1+(i+1)%D];
619 		}
620 
621 	if(r1!=0 && r2!=0)for(i=0;i<D;++i)
622 		{
623       fi->V(0)=ivp[b1+i];
624       fi->V(1)=ivp[b2+i];
625       fi->V(2)=ivp[b2+(i+1)%D];
626       ++fi;
627       fi->V(0)=ivp[b1+i];
628       fi->V(1)=ivp[b2+(i+1)%D];
629       fi->V(2)=ivp[b1+(i+1)%D];
630       ++fi;
631 		}
632 }
633 
634 
635 template <class MeshType >
Box(MeshType & in,const typename MeshType::BoxType & bb)636 void Box(MeshType &in, const typename MeshType::BoxType & bb )
637 {
638  typedef typename MeshType::ScalarType ScalarType;
639  typedef typename MeshType::CoordType CoordType;
640  typedef typename MeshType::VertexPointer  VertexPointer;
641  typedef typename MeshType::VertexIterator VertexIterator;
642  typedef typename MeshType::FaceIterator   FaceIterator;
643 
644  in.Clear();
645  Allocator<MeshType>::AddVertices(in,8);
646  Allocator<MeshType>::AddFaces(in,12);
647 
648  VertexPointer ivp[8];
649 
650  VertexIterator vi=in.vert.begin();
651  ivp[0]=&*vi;vi->P()=CoordType (bb.min[0],bb.min[1],bb.min[2]); ++vi;
652  ivp[1]=&*vi;vi->P()=CoordType (bb.max[0],bb.min[1],bb.min[2]); ++vi;
653  ivp[2]=&*vi;vi->P()=CoordType (bb.min[0],bb.max[1],bb.min[2]); ++vi;
654  ivp[3]=&*vi;vi->P()=CoordType (bb.max[0],bb.max[1],bb.min[2]); ++vi;
655  ivp[4]=&*vi;vi->P()=CoordType (bb.min[0],bb.min[1],bb.max[2]); ++vi;
656  ivp[5]=&*vi;vi->P()=CoordType (bb.max[0],bb.min[1],bb.max[2]); ++vi;
657  ivp[6]=&*vi;vi->P()=CoordType (bb.min[0],bb.max[1],bb.max[2]); ++vi;
658  ivp[7]=&*vi;vi->P()=CoordType (bb.max[0],bb.max[1],bb.max[2]);
659 
660  FaceIterator fi=in.face.begin();
661  fi->V(0)=ivp[0];  fi->V(1)=ivp[1]; fi->V(2)=ivp[2]; ++fi;
662  fi->V(0)=ivp[3];  fi->V(1)=ivp[2]; fi->V(2)=ivp[1]; ++fi;
663  fi->V(0)=ivp[0];  fi->V(1)=ivp[2]; fi->V(2)=ivp[4]; ++fi;
664  fi->V(0)=ivp[6];  fi->V(1)=ivp[4]; fi->V(2)=ivp[2]; ++fi;
665  fi->V(0)=ivp[0];  fi->V(1)=ivp[4]; fi->V(2)=ivp[1]; ++fi;
666  fi->V(0)=ivp[5];  fi->V(1)=ivp[1]; fi->V(2)=ivp[4]; ++fi;
667  fi->V(0)=ivp[7];  fi->V(1)=ivp[5]; fi->V(2)=ivp[6]; ++fi;
668  fi->V(0)=ivp[4];  fi->V(1)=ivp[6]; fi->V(2)=ivp[5]; ++fi;
669  fi->V(0)=ivp[7];  fi->V(1)=ivp[6]; fi->V(2)=ivp[3]; ++fi;
670  fi->V(0)=ivp[2];  fi->V(1)=ivp[3]; fi->V(2)=ivp[6]; ++fi;
671  fi->V(0)=ivp[7];  fi->V(1)=ivp[3]; fi->V(2)=ivp[5]; ++fi;
672  fi->V(0)=ivp[1];  fi->V(1)=ivp[5]; fi->V(2)=ivp[3];
673 
674  if (in.HasPerFaceFlags()) {
675     FaceIterator fi=in.face.begin();
676     for (int k=0; k<12; k++) {
677       fi->SetF(1); fi++;
678     }
679   }
680 
681 }
682 
683 
684 // this function build a mesh starting from a vector of generic coords (objects having a triple of float at their beginning)
685 // and a vector of faces (objects having a triple of ints at theri beginning).
686 
687 
688 template <class MeshType,class V, class F >
Build(MeshType & in,const V & v,const F & f)689 void Build( MeshType & in, const V & v, const F & f)
690 {
691  typedef typename MeshType::ScalarType ScalarType;
692  typedef typename MeshType::CoordType CoordType;
693  typedef typename MeshType::VertexPointer  VertexPointer;
694  typedef typename MeshType::VertexIterator VertexIterator;
695  typedef typename MeshType::FaceIterator   FaceIterator;
696 
697  Allocator<MeshType>::AddVertices(in,v.size());
698  Allocator<MeshType>::AddFaces(in,f.size());
699 
700 	typename V::const_iterator vi;
701 
702 	typename MeshType::VertexType tv;
703 
704 	for(int i=0;i<v.size();++i)
705 	{
706 		float *vv=(float *)(&v[i]);
707 		in.vert[i].P() = CoordType( vv[0],vv[1],vv[2]);
708 	}
709 
710   std::vector<VertexPointer> index(in.vn);
711 	VertexIterator j;
712 	int k;
713 	for(k=0,j=in.vert.begin();j!=in.vert.end();++j,++k)
714 		index[k] = &*j;
715 
716 	typename F::const_iterator fi;
717 
718 	typename MeshType::FaceType ft;
719 
720 	for(int i=0;i<f.size();++i)
721 	{
722 	int * ff=(int *)(&f[i]);
723 		assert( ff[0]>=0 );
724 		assert( ff[1]>=0 );
725 		assert( ff[2]>=0 );
726 		assert( ff[0]<in.vn );
727 		assert( ff[1]<in.vn );
728 		assert( ff[2]<in.vn );
729 		in.face[i].V(0) = &in.vert[ ff[0] ];
730 		in.face[i].V(1) = &in.vert[ ff[0] ];
731 		in.face[i].V(2) = &in.vert[ ff[0] ];
732 
733 	}
734 }
735 
736 // Build a regular grid mesh as a typical height field mesh
737 // 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)
738 // z is taken from the <data> array
739 // Once generated the vertex positions it uses the FaceGrid function to generate the faces;
740 
741 template <class MeshType>
Grid(MeshType & in,int w,int h,float wl,float hl,float * data)742 void Grid(MeshType & in, int w, int h, float wl, float hl, float *data)
743 {
744  typedef typename MeshType::CoordType CoordType;
745  typedef typename MeshType::VertexPointer  VertexPointer;
746  typedef typename MeshType::VertexIterator VertexIterator;
747  typedef typename MeshType::FaceIterator   FaceIterator;
748 
749   in.Clear();
750 	Allocator<MeshType>::AddVertices(in,w*h);
751 
752 
753   float wld=wl/float(w);
754   float hld=hl/float(h);
755 
756   for(int i=0;i<h;++i)
757     for(int j=0;j<w;++j)
758       in.vert[i*w+j].P()=CoordType ( j*wld, i*hld, data[i*w+j]);
759  FaceGrid(in,w,h);
760 }
761 
762 
763 // Build a regular grid mesh of faces as a typical height field mesh
764 // Vertexes are assumed to be already be allocated.
765 
766 template <class MeshType>
FaceGrid(MeshType & in,int w,int h)767 void FaceGrid(MeshType & in, int w, int h)
768 {
769 	assert(in.vn == (int)in.vert.size()); // require a compact vertex vector
770 	assert(in.vn >= w*h); // the number of vertices should match the number of expected grid vertices
771 
772 	Allocator<MeshType>::AddFaces(in,(w-1)*(h-1)*2);
773 
774 //   i+0,j+0 -- i+0,j+1
775 //      |   \     |
776 //      |    \    |
777 //      |     \   |
778 //      |      \  |
779 //   i+1,j+0 -- i+1,j+1
780 //
781   for(int i=0;i<h-1;++i)
782     for(int j=0;j<w-1;++j)
783     {
784       in.face[2*(i*(w-1)+j)+0].V(0) = &(in.vert[(i+1)*w+j+1]);
785       in.face[2*(i*(w-1)+j)+0].V(1) = &(in.vert[(i+0)*w+j+1]);
786       in.face[2*(i*(w-1)+j)+0].V(2) = &(in.vert[(i+0)*w+j+0]);
787 
788       in.face[2*(i*(w-1)+j)+1].V(0) = &(in.vert[(i+0)*w+j+0]);
789       in.face[2*(i*(w-1)+j)+1].V(1) = &(in.vert[(i+1)*w+j+0]);
790       in.face[2*(i*(w-1)+j)+1].V(2) = &(in.vert[(i+1)*w+j+1]);
791     }
792 
793   if (in.HasPerFaceFlags()) {
794     for (int k=0; k<(h-1)*(w-1)*2; k++) {
795       in.face[k].SetF(2);
796     }
797   }
798 
799 }
800 
801 
802 // Build a regular grid mesh of faces as a typical height field mesh
803 // Vertexes are assumed to be already be allocated, but not oll the grid vertexes are present.
804 // For this purpos a grid of indexes is also passed. negative indexes means that there is no vertex.
805 
806 template <class MeshType>
FaceGrid(MeshType & in,const std::vector<int> & grid,int w,int h)807 void FaceGrid(MeshType & in, const std::vector<int> &grid, int w, int h)
808 {
809 	assert(in.vn == (int)in.vert.size()); // require a compact vertex vector
810 	assert(in.vn <= w*h); // the number of vertices should match the number of expected grid vertices
811 
812 //	    V0       V1
813 //   i+0,j+0 -- i+0,j+1
814 //      |   \     |
815 //      |    \    |
816 //      |     \   |
817 //      |      \  |
818 //   i+1,j+0 -- i+1,j+1
819 //     V2        V3
820 
821 
822   for(int i=0;i<h-1;++i)
823     for(int j=0;j<w-1;++j)
824     {
825       int V0i= grid[(i+0)*w+j+0];
826 			int V1i= grid[(i+0)*w+j+1];
827 			int V2i= grid[(i+1)*w+j+0];
828 			int V3i= grid[(i+1)*w+j+1];
829 
830 			int ndone=0;
831 			bool quad = (V0i>=0 && V1i>=0 && V2i>=0 && V3i>=0 ) && in.HasPerFaceFlags();
832 
833 			if(V0i>=0 && V2i>=0 && V3i>=0 )
834 			{
835 				typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
836 				f->V(0)=&(in.vert[V3i]);
837 				f->V(1)=&(in.vert[V2i]);
838 				f->V(2)=&(in.vert[V0i]);
839 				if (quad) f->SetF(2);
840 				ndone++;
841 			}
842 			if(V0i>=0 && V1i>=0 && V3i>=0 )
843 			{
844 				typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
845 				f->V(0)=&(in.vert[V0i]);
846 				f->V(1)=&(in.vert[V1i]);
847 				f->V(2)=&(in.vert[V3i]);
848 				if (quad) f->SetF(2);
849 				ndone++;
850 			}
851 
852 			if (ndone==0) { // try diag the other way
853   		 if(V2i>=0 && V0i>=0 && V1i>=0 )
854 	  		{
855 				typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
856 				f->V(0)=&(in.vert[V2i]);
857 				f->V(1)=&(in.vert[V0i]);
858 				f->V(2)=&(in.vert[V1i]);
859 				ndone++;
860 			 }
861 			 if(V1i>=0 && V3i>=0 && V2i>=0 )
862 			 {
863 				typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
864 				f->V(0)=&(in.vert[V1i]);
865 				f->V(1)=&(in.vert[V3i]);
866 				f->V(2)=&(in.vert[V2i]);
867 				ndone++;
868 			 }
869       }
870 
871 
872     }
873 }
874 
875 template <class MeshType>
Cylinder(int slices,int stacks,MeshType & m)876 void Cylinder(int slices, int stacks, MeshType & m){
877 
878 	typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices*(stacks+1));
879 	for ( int i = 0; i < stacks+1; ++i)
880   	for ( int j = 0; j < slices; ++j)
881     {
882       	float x,y,h;
883 				x = cos(	2.0 * M_PI / slices * j);
884 				y = sin(	2.0 * M_PI / slices * j);
885 				h = 2 * i / (float)(stacks) - 1;
886 
887                                 vi->P() = typename MeshType::CoordType(x,h,y);
888 				++vi;
889 		}
890 
891 	typename MeshType::FaceIterator fi ;
892 	for ( int j = 0; j < stacks; ++j)
893 		for ( int i = 0; i < slices; ++i)
894     {
895        int a,b,c,d;
896        a =  (j+0)*slices + i;
897        b =  (j+1)*slices + i;
898        c =  (j+1)*slices + (i+1)%slices;
899        d =  (j+0)*slices + (i+1)%slices;
900 			 if(((i+j)%2) == 0){
901 				fi = vcg::tri::Allocator<MeshType>::AddFaces(m,1);
902                                 fi->V(0) = &m.vert[ a ];
903                                 fi->V(1) = &m.vert[ b ];
904                                 fi->V(2) = &m.vert[ c ];
905 
906 			 	fi = vcg::tri::Allocator<MeshType>::AddFaces(m,1);
907                                 fi->V(0) = &m.vert[ c ];
908                                 fi->V(1) = &m.vert[ d ];
909                                 fi->V(2) = &m.vert[ a ];
910 			 }
911 			 else{
912 				fi = vcg::tri::Allocator<MeshType>::AddFaces(m,1);
913                                 fi->V(0) = &m.vert[ b ];
914                                 fi->V(1) = &m.vert[ c ];
915                                 fi->V(2) = &m.vert[ d ];
916 
917 			 	fi = vcg::tri::Allocator<MeshType>::AddFaces(m,1);
918                                 fi->V(0) = &m.vert[ d ];
919                                 fi->V(1) = &m.vert[ a ];
920                                 fi->V(2) = &m.vert[ b ];
921 
922 			 }
923     }
924 
925    if (m.HasPerFaceFlags()) {
926      for (typename MeshType::FaceIterator fi=m.face.begin(); fi!=m.face.end(); fi++) {
927        fi->SetF(2);
928      }
929    }
930 
931 
932 }
933 
934 template <class MeshType>
GenerateCameraMesh(MeshType & in)935 void GenerateCameraMesh(MeshType &in){
936 	typedef typename MeshType::CoordType MV;
937 	MV vv[52]={
938 		MV(-0.000122145 , -0.2 ,0.35),
939 		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),
940 		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),
941 		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),
942 		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),
943 		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),
944 		MV(-0.203079 , -0.1 ,0.471362),	};
945 	int ff[88][3]={
946 		{0,2,3},
947 		{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},
948 		{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},
949 		{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},
950 		{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},
951 		{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},
952 		{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},
953 		{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},
954 		{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},
955 		{43,36,44},{51,44,45},{51,45,46},{51,46,47},{51,47,48},{51,49,50},{51,50,44},
956 	};
957 
958 	 in.Clear();
959 	 Allocator<MeshType>::AddVertices(in,52);
960 	 Allocator<MeshType>::AddFaces(in,88);
961 
962 	in.vn=52;in.fn=88;
963 	int i,j;
964 	for(i=0;i<in.vn;i++)
965 				in.vert[i].P()=vv[i];;
966 
967 	std::vector<typename MeshType::VertexPointer> index(in.vn);
968 
969 	typename MeshType::VertexIterator vi;
970 	for(j=0,vi=in.vert.begin();j<in.vn;++j,++vi)	index[j] = &*vi;
971 	for(j=0;j<in.fn;++j)
972 	{
973 		in.face[j].V(0)=index[ff[j][0]];
974 		in.face[j].V(1)=index[ff[j][1]];
975 		in.face[j].V(2)=index[ff[j][2]];
976 	}
977 }
978 
979 //@}
980 
981 } // End Namespace TriMesh
982 } // End Namespace vcg
983 #endif
984