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