VCG Library
Loading...
Searching...
No Matches
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
36namespace vcg {
37namespace tri {
53template <class TetraMeshType>
54void Tetrahedron(TetraMeshType &in)
55{
56 typedef typename TetraMeshType::CoordType CoordType;
57 typedef typename TetraMeshType::VertexPointer VertexPointer;
58 typedef typename TetraMeshType::VertexIterator VertexIterator;
59 typedef typename TetraMeshType::FaceIterator FaceIterator;
60
61 in.Clear();
64
65 VertexPointer ivp[4];
66 VertexIterator vi=in.vert.begin();
67 ivp[0]=&*vi;(*vi).P()=CoordType ( 1.0, 1.0, 1.0); ++vi;
68 ivp[1]=&*vi;(*vi).P()=CoordType (-1.0, 1.0,-1.0); ++vi;
69 ivp[2]=&*vi;(*vi).P()=CoordType (-1.0,-1.0, 1.0); ++vi;
70 ivp[3]=&*vi;(*vi).P()=CoordType ( 1.0,-1.0,-1.0);
71
72 FaceIterator fi=in.face.begin();
73 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
74 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[3]; ++fi;
75 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[1]; ++fi;
76 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1];
77}
78
86template <class DodMeshType>
87void Dodecahedron(DodMeshType & in)
88{
89 typedef typename DodMeshType::CoordType CoordType;
90
91 const double phi = (1 + std::sqrt(5)) / 2; // Golden ratio
92 const double a = 1 / std::sqrt(3);
93 const double b = a / phi;
94 const double c = a * phi;
95
96 std::vector<std::array<double, 3>> vertices = {
97 {a, a, a}, {a, a, -a}, {a, -a, a}, {a, -a, -a},
98 {-a, a, a}, {-a, a, -a}, {-a, -a, a}, {-a, -a, -a},
99 {0, b, c}, {0, b, -c}, {0, -b, c}, {0, -b, -c},
100 {b, c, 0}, {b, -c, 0}, {-b, c, 0}, {-b, -c, 0},
101 {c, 0, b}, {c, 0, -b}, {-c, 0, b}, {-c, 0, -b}
102 };
103 for(size_t i = 0; i < vertices.size(); i++) {
104 Allocator<DodMeshType>::AddVertex(in, CoordType(vertices[i][0], vertices[i][1], vertices[i][2]));
105 }
106
107 std::vector<std::array<int, 5>> faces = {
108 {0, 8, 10, 2, 16},
109 {0, 16, 17, 1, 12},
110 {0, 12, 14, 4, 8},
111 {5, 14, 12, 1, 9},
112 {5, 19, 18, 4, 14},
113 {5, 9, 11, 7, 19},
114 {3, 11, 9, 1, 17},
115 {3, 13, 15, 7, 11},
116 {3, 17, 16, 2, 13},
117 {6, 18, 19, 7, 15},
118 {6, 15, 13, 2, 10},
119 {6, 10, 8, 4, 18}
120 };
121 for(size_t i = 0; i < faces.size(); i++) {
122 Allocator<DodMeshType>::AddFace(in, faces[i][0], faces[i][1], faces[i][2]);
123 in.face.back().SetF(2);
124 Allocator<DodMeshType>::AddFace(in, faces[i][0], faces[i][2], faces[i][3]);
125 in.face.back().SetF(0); in.face.back().SetF(2);
126 Allocator<DodMeshType>::AddFace(in, faces[i][0], faces[i][3], faces[i][4]);
127 in.face.back().SetF(0);
128 }
129}
130
136template <class DodMeshType>
137void DodecahedronSym(DodMeshType & in)
138{
139 typedef DodMeshType MeshType;
140 typedef typename MeshType::CoordType CoordType;
141 typedef typename MeshType::VertexPointer VertexPointer;
142 typedef typename MeshType::VertexIterator VertexIterator;
143 typedef typename MeshType::FaceIterator FaceIterator;
144 typedef typename MeshType::ScalarType ScalarType;
145 const int N_penta=12;
146 const int N_points=62;
147
148 int penta[N_penta*3*3]=
149 {20,11, 18, 18, 11, 8, 8, 11, 4,
150 13,23, 4, 4, 23, 8, 8, 23, 16,
151 13, 4, 30, 30, 4, 28, 28, 4, 11,
152 16,34, 8, 8, 34, 18, 18, 34, 36,
153 11,20, 28, 28, 20, 45, 45, 20, 38,
154 13,30, 23, 23, 30, 41, 41, 30, 47,
155 16,23, 34, 34, 23, 50, 50, 23, 41,
156 20,18, 38, 38, 18, 52, 52, 18, 36,
157 30,28, 47, 47, 28, 56, 56, 28, 45,
158 50,60, 34, 34, 60, 36, 36, 60, 52,
159 45,38, 56, 56, 38, 60, 60, 38, 52,
160 50,41, 60, 60, 41, 56, 56, 41, 47 };
161 //A B E D C
162 ScalarType p=(1.0 + math::Sqrt(5.0)) / 2.0;
163 ScalarType p2=p*p;
164 ScalarType p3=p*p*p;
165 const ScalarType scale = std::sqrt(p2*p2*3);
166 p=p/scale;
167 p2=p2/scale;
168 p3=p3/scale;
169
170 ScalarType vv[N_points*3]=
171 {
172 0, 0, 2*p2, p2, 0, p3, p, p2, p3,
173 0, p, p3, -p, p2, p3, -p2, 0, p3,
174 -p, -p2, p3, 0, -p, p3, p, -p2, p3,
175 p3, p, p2, p2, p2, p2, 0, p3, p2,
176 -p2, p2, p2, -p3, p, p2, -p3, -p, p2,
177 -p2, -p2, p2, 0, -p3, p2, p2, -p2, p2,
178 p3, -p, p2, p3, 0, p, p2, p3, p,
179 -p2, p3, p, -p3, 0, p, -p2, -p3, p,
180 p2, -p3, p, 2*p2, 0, 0, p3, p2, 0,
181 p, p3, 0, 0, 2*p2, 0, -p, p3, 0,
182 -p3, p2, 0, -2*p2, 0, 0, -p3, -p2, 0,
183 -p, -p3, 0, 0, -2*p2, 0, p, -p3, 0,
184 p3, -p2, 0, p3, 0, -p, p2, p3, -p,
185 -p2, p3, -p, -p3, 0, -p, -p2, -p3, -p,
186 p2, -p3, -p, p3, p, -p2, p2, p2, -p2,
187 0, p3, -p2, -p2, p2, -p2, -p3, p, -p2,
188 -p3, -p, -p2, -p2, -p2, -p2, 0, -p3, -p2,
189 p2, -p2, -p2, p3, -p, -p2, p2, 0, -p3,
190 p, p2, -p3, 0, p, -p3, -p, p2, -p3,
191 -p2, 0, -p3, -p, -p2, -p3, 0, -p, -p3,
192 p, -p2, -p3, 0, 0, -2*p2
193 };
194 in.Clear();
195 //in.face.clear();
197 Allocator<DodMeshType>::AddFaces(in, 5*12); // five pentagons, each made by 5 tri
198
199 int h,i,j,m=0;
200
201 bool used[N_points];
202 for (i=0; i<N_points; i++) used[i]=false;
203
204 int reindex[20+12 *10];
205 ScalarType xx,yy,zz, sx,sy,sz;
206
207 int order[5]={0,1,8,6,2};
208 int added[12];
209
210 VertexIterator vi=in.vert.begin();
211
212 for (i=0; i<12; i++) {
213 sx=sy=sz=0;
214 for (int j=0; j<5; j++) {
215 h= penta[ i*9 + order[j] ]-1;
216 xx=vv[h*3];yy=vv[h*3+1];zz=vv[h*3+2]; sx+=xx; sy+=yy; sz+=zz;
217 if (!used[h]) {
218 (*vi).P()=CoordType( xx, yy, zz ); vi++;
219 used[h]=true;
220 reindex[ h ] = m++;
221 }
222 }
223 (*vi).P()=CoordType( sx/5.0, sy/5.0, sz/5.0 ); vi++;
224 added[ i ] = m++;
225 }
226
227 std::vector<VertexPointer> index(in.vn);
228
229 for(j=0,vi=in.vert.begin();j<in.vn;++j,++vi) index[j] = &(*vi);
230
231 FaceIterator fi=in.face.begin();
232
233 for (i=0; i<12; i++) {
234 for (j=0; j<5; j++){
235 (*fi).V(0)=index[added[i] ];
236 (*fi).V(1)=index[reindex[penta[i*9 + order[j ] ] -1 ] ];
237 (*fi).V(2)=index[reindex[penta[i*9 + order[(j+1)%5] ] -1 ] ];
238 if (HasPerFaceFlags(in)) {
239 // tag faux edges
240 (*fi).SetF(0);
241 (*fi).SetF(2);
242 }
243 fi++;
244 }
245 }
246}
247
248template <class OctMeshType>
254void Octahedron(OctMeshType &in)
255{
256 typedef OctMeshType MeshType;
257 typedef typename MeshType::CoordType CoordType;
258 typedef typename MeshType::VertexPointer VertexPointer;
259 typedef typename MeshType::VertexIterator VertexIterator;
260 typedef typename MeshType::FaceIterator FaceIterator;
261
262 in.Clear();
265
266 VertexPointer ivp[6];
267
268 VertexIterator vi=in.vert.begin();
269 ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 0, 0); ++vi;
270 ivp[1]=&*vi;(*vi).P()=CoordType ( 0, 1, 0); ++vi;
271 ivp[2]=&*vi;(*vi).P()=CoordType ( 0, 0, 1); ++vi;
272 ivp[3]=&*vi;(*vi).P()=CoordType (-1, 0, 0); ++vi;
273 ivp[4]=&*vi;(*vi).P()=CoordType ( 0,-1, 0); ++vi;
274 ivp[5]=&*vi;(*vi).P()=CoordType ( 0, 0,-1);
275
276 FaceIterator fi=in.face.begin();
277 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
278 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi;
279 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[5]; ++fi;
280 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[1]; ++fi;
281 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[5]; ++fi;
282 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[4]; ++fi;
283 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi;
284 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1];
285}
286
287template <class IcoMeshType>
293void Icosahedron(IcoMeshType &in)
294{
295 typedef IcoMeshType MeshType;
296 typedef typename MeshType::ScalarType ScalarType;
297 typedef typename MeshType::CoordType CoordType;
298 typedef typename MeshType::VertexPointer VertexPointer;
299 typedef typename MeshType::VertexIterator VertexIterator;
300 typedef typename MeshType::FaceIterator FaceIterator;
301
302 ScalarType L=ScalarType((math::Sqrt(5.0)+1.0)/2.0);
303 CoordType vv[12]={
304 CoordType ( 0, L, 1),
305 CoordType ( 0, L,-1),
306 CoordType ( 0,-L, 1),
307 CoordType ( 0,-L,-1),
308
309 CoordType ( L, 1, 0),
310 CoordType ( L,-1, 0),
311 CoordType (-L, 1, 0),
312 CoordType (-L,-1, 0),
313
314 CoordType ( 1, 0, L),
315 CoordType (-1, 0, L),
316 CoordType ( 1, 0,-L),
317 CoordType (-1, 0,-L)
318 };
319
320 int ff[20][3]={
321 {1,0,4},{0,1,6},{2,3,5},{3,2,7},
322 {4,5,10},{5,4,8},{6,7,9},{7,6,11},
323 {8,9,2},{9,8,0},{10,11,1},{11,10,3},
324 {0,8,4},{0,6,9},{1,4,10},{1,11,6},
325 {2,5,8},{2,9,7},{3,10,5},{3,7,11}
326 };
327
328
329 in.Clear();
332 VertexPointer ivp[12];
333
334 VertexIterator vi;
335 int i;
336 for(i=0,vi=in.vert.begin();vi!=in.vert.end();++i,++vi){
337 (*vi).P()=vv[i];
338 ivp[i]=&*vi;
339 }
340
341 FaceIterator fi;
342 for(i=0,fi=in.face.begin();fi!=in.face.end();++i,++fi){
343 (*fi).V(0)=ivp[ff[i][0]];
344 (*fi).V(1)=ivp[ff[i][1]];
345 (*fi).V(2)=ivp[ff[i][2]];
346 }
347}
348
349template <class MeshType>
355void Hexahedron(MeshType &in)
356{
357 typedef typename MeshType::CoordType CoordType;
358 typedef typename MeshType::VertexPointer VertexPointer;
359 typedef typename MeshType::VertexIterator VertexIterator;
360 typedef typename MeshType::FaceIterator FaceIterator;
361
362 in.Clear();
365
366 VertexPointer ivp[8];
367
368 VertexIterator vi=in.vert.begin();
369
370 ivp[7]=&*vi;(*vi).P()=CoordType (-1,-1,-1); ++vi;
371 ivp[6]=&*vi;(*vi).P()=CoordType ( 1,-1,-1); ++vi;
372 ivp[5]=&*vi;(*vi).P()=CoordType (-1, 1,-1); ++vi;
373 ivp[4]=&*vi;(*vi).P()=CoordType ( 1, 1,-1); ++vi;
374 ivp[3]=&*vi;(*vi).P()=CoordType (-1,-1, 1); ++vi;
375 ivp[2]=&*vi;(*vi).P()=CoordType ( 1,-1, 1); ++vi;
376 ivp[1]=&*vi;(*vi).P()=CoordType (-1, 1, 1); ++vi;
377 ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 1, 1);
378
379 FaceIterator fi=in.face.begin();
380 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
381 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1]; ++fi;
382 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi;
383 (*fi).V(0)=ivp[6]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi;
384 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[1]; ++fi;
385 (*fi).V(0)=ivp[5]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[4]; ++fi;
386 (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[6]; ++fi;
387 (*fi).V(0)=ivp[4]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[5]; ++fi;
388 (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[3]; ++fi;
389 (*fi).V(0)=ivp[2]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[6]; ++fi;
390 (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[5]; ++fi;
391 (*fi).V(0)=ivp[1]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[3];
392
393 if (HasPerFaceFlags(in)) {
394 FaceIterator fi=in.face.begin();
395 for (int k=0; k<12; k++) {
396 (*fi).SetF(1); fi++;
397 }
398 }
399
400}
401
402template <class MeshType>
408void Square(MeshType &in)
409{
410 typedef typename MeshType::CoordType CoordType;
411 typedef typename MeshType::VertexPointer VertexPointer;
412 typedef typename MeshType::VertexIterator VertexIterator;
413 typedef typename MeshType::FaceIterator FaceIterator;
414
415 in.Clear();
418
419 VertexPointer ivp[4];
420
421 VertexIterator vi=in.vert.begin();
422 ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 0, 0); ++vi;
423 ivp[1]=&*vi;(*vi).P()=CoordType ( 0, 1, 0); ++vi;
424 ivp[2]=&*vi;(*vi).P()=CoordType (-1, 0, 0); ++vi;
425 ivp[3]=&*vi;(*vi).P()=CoordType ( 0,-1, 0);
426
427 FaceIterator fi=in.face.begin();
428 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
429 (*fi).V(0)=ivp[2]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[0];
430
431 if (HasPerFaceFlags(in)) {
432 FaceIterator fi=in.face.begin();
433 for (int k=0; k<2; k++) {
434 (*fi).SetF(2); fi++;
435 }
436 }
437}
438
439template <class MeshType>
450void SphericalCap(MeshType &in, float angleRad, const int subdiv = 3 )
451{
452 typedef typename MeshType::CoordType CoordType;
453 typedef typename MeshType::VertexIterator VertexIterator;
454 in.Clear();
455 tri::Allocator<MeshType>::AddVertex(in,CoordType(0,0,0));
456 for(int i=0;i<6;++i)
457 tri::Allocator<MeshType>::AddVertex(in,CoordType(cos(math::ToRad(i*60.0)),sin(math::ToRad(i*60.0)),0));
458
459 for(int i=0;i<6;++i)
460 tri::Allocator<MeshType>::AddFace(in,&(in.vert[0]),&(in.vert[1+i]),&(in.vert[1+(i+1)%6]));
461
463 for(int i=0;i<subdiv;++i)
464 {
465 tri::Refine(in, MidPoint<MeshType>(&in));
466
469
470 for(int i=0;i<in.vn;++i)
471 if(in.vert[i].IsB())
472 in.vert[i].P().Normalize();
473
476 tri::Smooth<MeshType>::VertexCoordLaplacian(in,10,true);
477 }
478
479 const float halfAngleRad = angleRad / 2.0f;
480 const float width = sin(halfAngleRad);
483 for(VertexIterator vi=in.vert.begin(); vi!=in.vert.end();++vi)
484 {
485 float cosVi = vi->P().Norm();
486 float angVi = asin (cosVi);
487 vi->P()[2] = cos(angVi) - cos(halfAngleRad);
488 }
489}
490
491// this function build a sphere starting from a eventually not empty mesh.
492// If the mesh is not empty it is 'spherified' and used as base for the subdivision process.
493// otherwise an icosahedron is used.
494template <class MeshType>
501void Sphere(MeshType &in, const int subdiv = 3 )
502{
503 typedef typename MeshType::CoordType CoordType;
504 typedef typename MeshType::VertexIterator VertexIterator;
505 typedef typename MeshType::FaceIterator FaceIterator;
506 if(in.vn==0 && in.fn==0) Icosahedron(in);
507
508 for(VertexIterator vi = in.vert.begin(); vi!=in.vert.end();++vi)
509 vi->P().Normalize();
510
511 for(int i = 0 ; i < subdiv; ++i)
512 {
513 MeshType newM;
514 for(FaceIterator fi=in.face.begin();fi!=in.face.end();++fi)
515 {
516 CoordType me01 = (fi->P(0)+fi->P(1))/2.0;
517 CoordType me12 = (fi->P(1)+fi->P(2))/2.0;
518 CoordType me20 = (fi->P(2)+fi->P(0))/2.0;
519 tri::Allocator<MeshType>::AddFace(newM,me01,me12,me20);
520 tri::Allocator<MeshType>::AddFace(newM,fi->P(0),me01,me20);
521 tri::Allocator<MeshType>::AddFace(newM,fi->P(1),me12,me01);
522 tri::Allocator<MeshType>::AddFace(newM,fi->P(2),me20,me12);
523 }
526
527 for(VertexIterator vi = in.vert.begin(); vi != in.vert.end(); ++vi)
528 vi->P().Normalize();
529 }
530}
531
532template <class MeshType>
541void Sphere(MeshType & m, const typename MeshType::CoordType & position, typename MeshType::ScalarType radius = 0, const int subdiv = 3)
542{
543 m.Clear();
544 tri::Sphere(m, subdiv);
547}
548
550
559template <class MeshType>
560void Cone( MeshType& in,
561 const typename MeshType::ScalarType r1,
562 const typename MeshType::ScalarType r2,
563 const typename MeshType::ScalarType h,
564 const int SubDiv = 36 )
565{
566 typedef typename MeshType::CoordType CoordType;
567 typedef typename MeshType::VertexPointer VertexPointer;
568 typedef typename MeshType::VertexIterator VertexIterator;
569 typedef typename MeshType::FaceIterator FaceIterator;
570
571 int i,b1,b2;
572 in.Clear();
573 int VN,FN;
574 if(r1==0 || r2==0) {
575 VN=SubDiv+2;
576 FN=SubDiv*2;
577 } else {
578 VN=SubDiv*2+2;
579 FN=SubDiv*4;
580 }
581
584 VertexPointer *ivp = new VertexPointer[VN];
585
586 VertexIterator vi=in.vert.begin();
587 ivp[0]=&*vi;(*vi).P()=CoordType ( 0,-h/2.0,0 ); ++vi;
588 ivp[1]=&*vi;(*vi).P()=CoordType ( 0, h/2.0,0 ); ++vi;
589
590 b1 = b2 = 2;
591 int cnt=2;
592 if(r1!=0)
593 {
594 for(i=0;i<SubDiv;++i)
595 {
596 double a = math::ToRad(i*360.0/SubDiv);
597 ivp[cnt]=&*vi; (*vi).P()= CoordType(r1*cos(a), -h/2.0, r1*sin(a)); ++vi;++cnt;
598 }
599 b2 += SubDiv;
600 }
601
602 if(r2!=0)
603 {
604 for(i=0;i<SubDiv;++i)
605 {
606 double a = math::ToRad(i*360.0/SubDiv);
607 ivp[cnt]=&*vi; (*vi).P()= CoordType( r2*cos(a), h/2.0, r2*sin(a)); ++vi;++cnt;
608 }
609 }
610
611 FaceIterator fi=in.face.begin();
612
613 if(r1!=0) for(i=0;i<SubDiv;++i,++fi) {
614 (*fi).V(0)=ivp[0];
615 (*fi).V(1)=ivp[b1+i];
616 (*fi).V(2)=ivp[b1+(i+1)%SubDiv];
617 }
618
619 if(r2!=0) for(i=0;i<SubDiv;++i,++fi) {
620 (*fi).V(0)=ivp[1];
621 (*fi).V(2)=ivp[b2+i];
622 (*fi).V(1)=ivp[b2+(i+1)%SubDiv];
623 }
624
625 if(r1==0) for(i=0;i<SubDiv;++i,++fi)
626 {
627 (*fi).V(0)=ivp[0];
628 (*fi).V(1)=ivp[b2+i];
629 (*fi).V(2)=ivp[b2+(i+1)%SubDiv];
630 }
631 if(r2==0) for(i=0;i<SubDiv;++i,++fi){
632 (*fi).V(0)=ivp[1];
633 (*fi).V(2)=ivp[b1+i];
634 (*fi).V(1)=ivp[b1+(i+1)%SubDiv];
635 }
636
637 if(r1!=0 && r2!=0)for(i=0;i<SubDiv;++i)
638 {
639 (*fi).V(0)=ivp[b1+i];
640 (*fi).V(1)=ivp[b2+i];
641 (*fi).V(2)=ivp[b2+(i+1)%SubDiv];
642 ++fi;
643 (*fi).V(0)=ivp[b1+i];
644 (*fi).V(1)=ivp[b2+(i+1)%SubDiv];
645 (*fi).V(2)=ivp[b1+(i+1)%SubDiv];
646 ++fi;
647 }
648}
649
650template <class MeshType>
661void OrientedCone(MeshType & m,
662 const typename MeshType::CoordType origin,
663 const typename MeshType::CoordType end,
664 const typename MeshType::ScalarType r1,
665 const typename MeshType::ScalarType r2,
666 const int SubDiv = 36 )
667{
668 typedef typename MeshType::ScalarType ScalarType;
669 typedef typename MeshType::CoordType CoordType;
670 typedef Matrix44<typename MeshType::ScalarType> Matrix44x;
671 Cone(m,r1,r2,Distance(origin,end),SubDiv);
672
673 tri::UpdatePosition<MeshType>::Translate(m,CoordType(0,Distance(origin,end)/2,0));
674
675 CoordType norm = end-origin;
676 ScalarType angleRad = Angle(CoordType(0,1,0),norm);
677 const ScalarType Delta= 0.000000001;
678 Matrix44x rotM;
679 if (fabs(angleRad)<Delta)
680 rotM.SetIdentity();
681 else
682 if (fabs(angleRad-M_PI)<Delta)
683 {
684 CoordType axis = CoordType(0,0,1)^norm;
685 rotM.SetRotateRad(angleRad,axis);
686 }
687 else
688 {
689 CoordType axis = CoordType(0,1,0)^norm;
690 rotM.SetRotateRad(angleRad,axis);
691 }
694}
695
696
697template <class MeshType >
704void Box(MeshType &in, const typename MeshType::BoxType & bb )
705{
706 typedef typename MeshType::CoordType CoordType;
707 typedef typename MeshType::VertexPointer VertexPointer;
708 typedef typename MeshType::VertexIterator VertexIterator;
709 typedef typename MeshType::FaceIterator FaceIterator;
710
711 in.Clear();
713 VertexPointer ivp[8];
714
715 VertexIterator vi=in.vert.begin();
716 ivp[0]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.min[2]); ++vi;
717 ivp[1]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.min[2]); ++vi;
718 ivp[2]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.min[2]); ++vi;
719 ivp[3]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.min[2]); ++vi;
720 ivp[4]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.max[2]); ++vi;
721 ivp[5]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.max[2]); ++vi;
722 ivp[6]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.max[2]); ++vi;
723 ivp[7]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.max[2]);
724
725 Allocator<MeshType>::AddFace(in,ivp[2],ivp[1],ivp[0]);
726 Allocator<MeshType>::AddFace(in,ivp[1],ivp[2],ivp[3]);
727 Allocator<MeshType>::AddFace(in,ivp[4],ivp[2],ivp[0]);
728 Allocator<MeshType>::AddFace(in,ivp[2],ivp[4],ivp[6]);
729 Allocator<MeshType>::AddFace(in,ivp[1],ivp[4],ivp[0]);
730 Allocator<MeshType>::AddFace(in,ivp[4],ivp[1],ivp[5]);
731 Allocator<MeshType>::AddFace(in,ivp[6],ivp[5],ivp[7]);
732 Allocator<MeshType>::AddFace(in,ivp[5],ivp[6],ivp[4]);
733 Allocator<MeshType>::AddFace(in,ivp[3],ivp[6],ivp[7]);
734 Allocator<MeshType>::AddFace(in,ivp[6],ivp[3],ivp[2]);
735 Allocator<MeshType>::AddFace(in,ivp[5],ivp[3],ivp[7]);
736 Allocator<MeshType>::AddFace(in,ivp[3],ivp[5],ivp[1]);
737
738 if (HasPerFaceFlags(in)) {
739 FaceIterator fi=in.face.begin();
740 for (int k=0; k<12; k++) {
741 (*fi).SetF(0); fi++;
742 }
743 }
744
745}
746
747// Torus
748template <class MeshType>
758void Torus(MeshType &m, float hRingRadius, float vRingRadius, int hRingDiv=24, int vRingDiv=12 )
759{
760 typedef typename MeshType::CoordType CoordType;
761 typedef typename MeshType::ScalarType ScalarType;
762 typedef Matrix44<ScalarType> Matrix44x;
763 m.Clear();
764 ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
765 ScalarType angleStepH = (2.0f*M_PI)/hRingDiv;
766
767 Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
768 for(int i=0;i<hRingDiv+1;++i)
769 {
770 Matrix44x RotM; RotM.SetRotateRad(float(i%hRingDiv)*angleStepH,CoordType(0,0,1));
771 for(int j=0;j<vRingDiv+1;++j)
772 {
773 CoordType p;
774 p[0]= vRingRadius*cos(float(j%vRingDiv)*angleStepV) + hRingRadius;
775 p[1] = 0;
776 p[2]= vRingRadius*sin(float(j%vRingDiv)*angleStepV);
777
778 m.vert[i*(vRingDiv+1)+j].P() = RotM*p;
779 }
780 }
781 FaceGrid(m,vRingDiv+1,hRingDiv+1);
784
785}
786
789template <class ScalarType>
790static ScalarType _SQfnC(ScalarType a, ScalarType b){
791 return math::Sgn(cos(a))*pow(fabs(cos(a)),b);
792}
793template <class ScalarType>
794static ScalarType _SQfnS(ScalarType a, ScalarType b){
795 return math::Sgn(sin(a))*pow(fabs(sin(a)),b);
796}
797
798
810template <class MeshType>
811void SuperToroid(MeshType &m, float hRingRadius, float vRingRadius, float vSquareness, float hSquareness, int hRingDiv=24, int vRingDiv=12 )
812{
813 typedef typename MeshType::CoordType CoordType;
814 typedef typename MeshType::ScalarType ScalarType;
815 m.Clear();
816 ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
817 ScalarType angleStepH = (2.0f*M_PI)/hRingDiv;
818
819 ScalarType u,v;
820 int count;
821 Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
822 for(int i=0;i<hRingDiv+1;++i)
823 {
824 u=float(i%hRingDiv)*angleStepH;
825 count=0;
826 for(int j=vRingDiv;j>=0;--j)
827 {
828 CoordType p;
829 v=float(j%vRingDiv)*angleStepV;
830 p[0]= (hRingRadius+vRingRadius*_SQfnC(u,vSquareness))*_SQfnC(v,hSquareness);;
831 p[1]= (hRingRadius+vRingRadius*_SQfnC(u,vSquareness))*_SQfnS(v,hSquareness);
832 p[2] = vRingRadius*_SQfnS(u,vSquareness);
833 m.vert[i*(vRingDiv+1)+count].P() = p;
834 count++;
835 }
836 }
837 FaceGrid(m,vRingDiv+1,hRingDiv+1);
840
841}
852template <class MeshType>
853void SuperEllipsoid(MeshType &m, float rFeature, float sFeature, float tFeature, int hRingDiv=24, int vRingDiv=12 )
854{
855 typedef typename MeshType::CoordType CoordType;
856 typedef typename MeshType::ScalarType ScalarType;
857 m.Clear();
858 ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
859 ScalarType angleStepH = (1.0f*M_PI)/hRingDiv;
860 float u;
861 float v;
862 Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
863 for(int i=0;i<hRingDiv+1;++i)
864 {
865 //u=ScalarType(i%hRingDiv)*angleStepH + angleStepH/2.0;
866 u=i*angleStepH;
867 for(int j=0;j<vRingDiv+1;++j)
868 {
869 CoordType p;
870 v=ScalarType(j%vRingDiv)*angleStepV;
871 p[0] = _SQfnC(v,2/rFeature)*_SQfnC(u,2/rFeature);
872 p[1] = _SQfnC(v,2/sFeature)*_SQfnS(u,2/sFeature);
873 p[2] = _SQfnS(v,2/tFeature);
874 m.vert[i*(vRingDiv+1)+j].P() = p;
875 }
876 }
877 FaceGrid(m,vRingDiv+1,hRingDiv+1);
878 tri::Clean<MeshType>::MergeCloseVertex(m,ScalarType(angleStepV*angleStepV*0.001));
880 bool oriented, orientable;
882 tri::Clean<MeshType>::OrientCoherentlyMesh(m,oriented,orientable);
884}
885
896template <class MeshType, class InCoordType, class InFaceIndexType >
897void BuildMeshFromCoordVectorIndexVector(MeshType & in, const std::vector<InCoordType> & v, const std::vector<InFaceIndexType> & f)
898{
899 typedef typename MeshType::CoordType CoordType;
900
901 in.Clear();
904
905 for(size_t i=0;i<v.size();++i)
906 {
907 const InCoordType &vv = v[i];
908 in.vert[i].P() = CoordType( vv[0],vv[1],vv[2]);
909 }
910
911 for(size_t i=0;i<f.size();++i)
912 {
913 const InFaceIndexType &ff= f[i];
914 assert( ff[0]>=0 && ff[0]<in.vn);
915 assert( ff[1]>=0 && ff[1]<in.vn);
916 assert( ff[2]>=0 && ff[2]<in.vn);
917 in.face[i].V(0) = &in.vert[ ff[0] ];
918 in.face[i].V(1) = &in.vert[ ff[1] ];
919 in.face[i].V(2) = &in.vert[ ff[2] ];
920 }
921
923}
924
925
926template <class MeshType,class V>
934void BuildMeshFromCoordVector( MeshType & in, const V & v)
935{
936 std::vector<Point3i> dummyfaceVec;
937 BuildMeshFromCoordVectorIndexVector(in,v,dummyfaceVec);
938}
939
940
941template <class TriMeshType,class EdgeMeshType >
949void BuildFromFaceEdgeSel(TriMeshType &in, EdgeMeshType &out)
950{
951 tri::RequireCompactness(in);
952 std::vector<typename tri::UpdateTopology<TriMeshType>::PEdge> edgevec;
954 out.Clear();
955 for(size_t i=0;i<in.vert.size();++i)
956 tri::Allocator<EdgeMeshType>::AddVertex(out, in.vert[i].P());
958
959 for(size_t i=0;i<edgevec.size();++i)
960 {
961 int i0 = tri::Index(in,edgevec[i].v[0]);
962 int i1 = tri::Index(in,edgevec[i].v[1]);
963 out.vert[i0].SetV();
964 out.vert[i1].SetV();
965 tri::Allocator<EdgeMeshType>::AddEdge(out,&out.vert[i0],&out.vert[i1]);
966 if(in.vert[i0].IsS()) out.vert[i0].SetS();
967 if(in.vert[i1].IsS()) out.vert[i1].SetS();
968 }
969
970 for(size_t i=0;i<out.vert.size();++i)
971 if(!out.vert[i].IsV()) tri::Allocator<EdgeMeshType>::DeleteVertex(out,out.vert[i]);
972
974}
975
976// Build a regular grid mesh as a typical height field mesh
977// 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)
978// z is taken from the <data> array
979// Once generated the vertex positions it uses the FaceGrid function to generate the faces;
980
981template <class MeshType>
992void Grid(MeshType & in, int w, int h, float wl, float hl, float *data=0)
993{
994 typedef typename MeshType::CoordType CoordType;
995
996 in.Clear();
998
999 float wld=wl/float(w-1);
1000 float hld=hl/float(h-1);
1001 float zVal=0;
1002 for(int i=0;i<h;++i)
1003 for(int j=0;j<w;++j)
1004 {
1005 if(data) zVal=data[i*w+j];
1006 in.vert[i*w+j].P()=CoordType ( j*wld, i*hld, zVal) ;
1007 }
1008 FaceGrid(in,w,h);
1009}
1010
1011
1012// Build a regular grid mesh of faces as a typical height field mesh
1013// Vertexes are assumed to be already be allocated.
1014
1015template <class MeshType>
1023void FaceGrid(MeshType & in, int w, int h)
1024{
1025 assert(in.vn == (int)in.vert.size()); // require a compact vertex vector
1026 assert(in.vn >= w*h); // the number of vertices should match the number of expected grid vertices
1027
1028 Allocator<MeshType>::AddFaces(in,(w-1)*(h-1)*2);
1029
1030// i+0,j+0 -- i+0,j+1
1031// | \ |
1032// | \ |
1033// | \ |
1034// | \ |
1035// i+1,j+0 -- i+1,j+1
1036//
1037 for(int i=0;i<h-1;++i)
1038 for(int j=0;j<w-1;++j)
1039 {
1040 in.face[2*(i*(w-1)+j)+0].V(0) = &(in.vert[(i+1)*w+j+1]);
1041 in.face[2*(i*(w-1)+j)+0].V(1) = &(in.vert[(i+0)*w+j+1]);
1042 in.face[2*(i*(w-1)+j)+0].V(2) = &(in.vert[(i+0)*w+j+0]);
1043
1044 in.face[2*(i*(w-1)+j)+1].V(0) = &(in.vert[(i+0)*w+j+0]);
1045 in.face[2*(i*(w-1)+j)+1].V(1) = &(in.vert[(i+1)*w+j+0]);
1046 in.face[2*(i*(w-1)+j)+1].V(2) = &(in.vert[(i+1)*w+j+1]);
1047 }
1048
1049 if (HasPerFaceFlags(in)) {
1050 for (int k=0; k<(h-1)*(w-1)*2; k++) {
1051 in.face[k].SetF(2);
1052 }
1053 }
1054
1055}
1056
1057
1058// Build a regular grid mesh of faces as the resulto of a sparsely regularly sampled height field.
1059// Vertexes are assumed to be already be allocated, but not all the grid vertexes are present.
1060// For this purpose vector with a grid of indexes is also passed.
1061// Negative indexes in this vector means that there is no vertex.
1062
1063template <class MeshType>
1072void SparseFaceGrid(MeshType & in, const std::vector<int> &grid, int w, int h)
1073{
1074 tri::RequireCompactness(in);
1075 assert(in.vn <= w*h); // the number of vertices should match the number of expected grid vertices
1076
1077// V0 V1
1078// i+0,j+0 -- i+0,j+1
1079// | \ |
1080// | \ |
1081// | \ |
1082// | \ |
1083// i+1,j+0 -- i+1,j+1
1084// V2 V3
1085
1086
1087 for(int i=0;i<h-1;++i)
1088 for(int j=0;j<w-1;++j)
1089 {
1090 int V0i= grid[(i+0)*w+j+0];
1091 int V1i= grid[(i+0)*w+j+1];
1092 int V2i= grid[(i+1)*w+j+0];
1093 int V3i= grid[(i+1)*w+j+1];
1094
1095 int ndone=0;
1096 bool quad = (V0i>=0 && V1i>=0 && V2i>=0 && V3i>=0 ) && tri::HasPerFaceFlags(in);
1097
1098 if(V0i>=0 && V2i>=0 && V3i>=0 )
1099 {
1100 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
1101 f->V(0)=&(in.vert[V3i]);
1102 f->V(1)=&(in.vert[V2i]);
1103 f->V(2)=&(in.vert[V0i]);
1104 if (quad) f->SetF(2);
1105 ndone++;
1106 }
1107 if(V0i>=0 && V1i>=0 && V3i>=0 )
1108 {
1109 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
1110 f->V(0)=&(in.vert[V0i]);
1111 f->V(1)=&(in.vert[V1i]);
1112 f->V(2)=&(in.vert[V3i]);
1113 if (quad) f->SetF(2);
1114 ndone++;
1115 }
1116
1117 if (ndone==0) { // try diag the other way
1118 if(V2i>=0 && V0i>=0 && V1i>=0 )
1119 {
1120 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
1121 f->V(0)=&(in.vert[V2i]);
1122 f->V(1)=&(in.vert[V0i]);
1123 f->V(2)=&(in.vert[V1i]);
1124 ndone++;
1125 }
1126 if(V1i>=0 && V3i>=0 && V2i>=0 )
1127 {
1128 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
1129 f->V(0)=&(in.vert[V1i]);
1130 f->V(1)=&(in.vert[V3i]);
1131 f->V(2)=&(in.vert[V2i]);
1132 ndone++;
1133 }
1134 }
1135 }
1136}
1137template <class MeshType>
1146void Annulus(MeshType & m, float externalRadius, float internalRadius, int slices)
1147{
1148 m.Clear();
1149 typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices*2);
1150
1151 for ( int j = 0; j < slices; ++j)
1152 {
1153 float x = cos( 2.0 * M_PI / slices * j);
1154 float y = sin( 2.0 * M_PI / slices * j);
1155
1156 (*vi).P() = typename MeshType::CoordType(x,y,0)*internalRadius;
1157 ++vi;
1158 (*vi).P() = typename MeshType::CoordType(x,y,0)*externalRadius;
1159 ++vi;
1160 }
1161 typename MeshType::FaceIterator fi ;
1162 for ( int j = 0; j < slices; ++j)
1163 {
1165 (*fi).V(0) = &m.vert[ ((j+0)*2+0)%(slices*2) ];
1166 (*fi).V(1) = &m.vert[ ((j+1)*2+1)%(slices*2) ];
1167 (*fi).V(2) = &m.vert[ ((j+0)*2+1)%(slices*2) ];
1168
1170 (*fi).V(0) = &m.vert[ ((j+1)*2+0)%(slices*2) ];
1171 (*fi).V(1) = &m.vert[ ((j+1)*2+1)%(slices*2) ];
1172 (*fi).V(2) = &m.vert[ ((j+0)*2+0)%(slices*2) ];
1173 }
1174}
1175
1176template <class MeshType>
1187void OrientedAnnulus(MeshType & m, typename MeshType::CoordType center, typename MeshType::CoordType norm, float externalRadius, float internalRadius, int slices)
1188{
1189 typedef typename MeshType::ScalarType ScalarType;
1190 typedef typename MeshType::CoordType CoordType;
1191 Annulus(m,externalRadius,internalRadius, slices);
1192 ScalarType angleRad = Angle(CoordType(0,0,1),norm);
1193 CoordType axis = CoordType(0,0,1)^norm;
1194
1195 Matrix44<ScalarType> rotM;
1196 rotM.SetRotateRad(angleRad,axis);
1199}
1200
1201
1202template <class MeshType>
1210void Circle2D(MeshType & m, float radius=1.0, int sides=32)
1211{
1212 m.Clear();
1213 for ( int j = 0; j < sides; ++j)
1214 {
1215 float x = cos( 2.0 * M_PI / sides * j)*radius;
1216 float y = sin( 2.0 * M_PI / sides * j)*radius;
1217
1219 }
1220for ( int j = 0; j < sides; ++j)
1221 {
1222 int a = j;
1223 int b = (j+1)%sides;
1224 tri::Allocator<MeshType>::AddEdge(m, &m.vert[a], &m.vert[b]);
1225 }
1226}
1227template <class MeshType>
1234void Disk(MeshType & m, int slices)
1235{
1236 m.Clear();
1237 typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices+1);
1238 (*vi).P() = typename MeshType::CoordType(0,0,0);
1239 ++vi;
1240
1241 for ( int j = 0; j < slices; ++j)
1242 {
1243 float x = cos( 2.0 * M_PI / slices * j);
1244 float y = sin( 2.0 * M_PI / slices * j);
1245
1246 (*vi).P() = typename MeshType::CoordType(x,y,0);
1247 ++vi;
1248 }
1249 typename MeshType::FaceIterator fi ;
1250 for ( int j = 0; j < slices; ++j)
1251 {
1252 int a = 1+(j+0)%slices;
1253 int b = 1+(j+1)%slices;
1255 (*fi).V(0) = &m.vert[ 0 ];
1256 (*fi).V(1) = &m.vert[ a ];
1257 (*fi).V(2) = &m.vert[ b ];
1258 }
1259}
1260
1261template <class MeshType>
1271void OrientedDisk(MeshType &m, typename MeshType::CoordType center, typename MeshType::CoordType norm, float radius, int slices)
1272{
1273 typedef typename MeshType::ScalarType ScalarType;
1274 typedef typename MeshType::CoordType CoordType;
1275
1276 Disk(m,slices);
1278 ScalarType angleRad = Angle(CoordType(0,0,1),norm);
1279 CoordType axis = CoordType(0,0,1)^norm;
1280
1281 Matrix44<ScalarType> rotM;
1282 rotM.SetRotateRad(angleRad,axis);
1285}
1286
1287template <class MeshType>
1301void 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 )
1302{
1303 typedef typename MeshType::ScalarType ScalarType;
1304 typedef typename MeshType::CoordType CoordType;
1305 typedef Matrix44<typename MeshType::ScalarType> Matrix44x;
1306 Cylinder(m,slices,stacks,capped);
1307 tri::UpdatePosition<MeshType>::Translate(m,CoordType(0,1,0));
1308 tri::UpdatePosition<MeshType>::Scale(m,CoordType(1,0.5f,1));
1309 tri::UpdatePosition<MeshType>::Scale(m,CoordType(xScale,1.0f,yScale));
1310
1311 float height = Distance(origin,end);
1312 tri::UpdatePosition<MeshType>::Scale(m,CoordType(radius,height,radius));
1313 CoordType norm = end-origin;
1314 ScalarType angleRad = Angle(CoordType(0,1,0),norm);
1315 const ScalarType Delta= 0.000000001;
1316 Matrix44x rotM;
1317 if (fabs(angleRad)<Delta)
1318 rotM.SetIdentity();
1319 else
1320 if (fabs(angleRad-M_PI)<Delta)
1321 {
1322 CoordType axis = CoordType(0,0,1)^norm;
1323 rotM.SetRotateRad(angleRad,axis);
1324 }
1325 else
1326 {
1327 CoordType axis = CoordType(0,1,0)^norm;
1328 rotM.SetRotateRad(angleRad,axis);
1329 }
1332
1333}
1334
1335template <class MeshType>
1347void OrientedCylinder(MeshType & m, const typename MeshType::CoordType origin, const typename MeshType::CoordType end, float radius, bool capped, int slices=32, int stacks=4 )
1348{
1349 OrientedEllipticPrism(m,origin,end,radius,1.0f,1.0f,capped,slices,stacks);
1350}
1351
1352
1353template <class MeshType>
1362void Cylinder(MeshType & m, int slices, int stacks, bool capped=false)
1363{
1364 m.Clear();
1365 typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices*(stacks+1));
1366 for ( int i = 0; i < stacks+1; ++i)
1367 for ( int j = 0; j < slices; ++j)
1368 {
1369 float x,y,h;
1370 x = cos( 2.0 * M_PI / slices * j);
1371 y = sin( 2.0 * M_PI / slices * j);
1372 h = 2 * i / (float)(stacks) - 1;
1373
1374 (*vi).P() = typename MeshType::CoordType(x,h,y);
1375 ++vi;
1376 }
1377
1378 for ( int j = 0; j < stacks; ++j)
1379 for ( int i = 0; i < slices; ++i)
1380 {
1381 int a,b,c,d;
1382 a = (j+0)*slices + i;
1383 b = (j+1)*slices + i;
1384 c = (j+1)*slices + (i+1)%slices;
1385 d = (j+0)*slices + (i+1)%slices;
1386 if(((i+j)%2) == 0){
1387 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ a ], &m.vert[ b ], &m.vert[ c ]);
1388 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ c ], &m.vert[ d ], &m.vert[ a ]);
1389 }
1390 else{
1391 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ b ], &m.vert[ c ], &m.vert[ d ]);
1392 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ d ], &m.vert[ a ], &m.vert[ b ]);
1393 }
1394 }
1395
1396 if(capped)
1397 {
1398 tri::Allocator<MeshType>::AddVertex(m,typename MeshType::CoordType(0,-1,0));
1399 tri::Allocator<MeshType>::AddVertex(m,typename MeshType::CoordType(0, 1,0));
1400 int base = 0;
1401 for ( int i = 0; i < slices; ++i)
1402 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ m.vn-2 ], &m.vert[ base+i ], &m.vert[ base+(i+1)%slices ]);
1403 base = (stacks)*slices;
1404 for ( int i = 0; i < slices; ++i)
1405 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ m.vn-1 ], &m.vert[ base+(i+1)%slices ], &m.vert[ base+i ]);
1406 }
1407 if (HasPerFaceFlags(m)) {
1408 for (typename MeshType::FaceIterator fi=m.face.begin(); fi!=m.face.end(); fi++) {
1409 (*fi).SetF(2);
1410 }
1411 }
1412}
1413
1424template <class MeshType>
1425void BuildPrismFaceShell(MeshType &mIn, MeshType &mOut, float height=0, float inset=0, bool smoothFlag=false )
1426{
1427 typedef typename MeshType::VertexPointer VertexPointer;
1428 typedef typename MeshType::FacePointer FacePointer;
1429 typedef typename MeshType::CoordType CoordType;
1430 if(height==0) height = mIn.bbox.Diag()/100.0f;
1431 if(inset==0) inset = mIn.bbox.Diag()/200.0f;
1435
1436 for(size_t i=0;i<mIn.face.size();++i) if(!mIn.face[i].IsV())
1437 {
1438 MeshType faceM;
1439 std::vector<VertexPointer> vertVec;
1440 std::vector<FacePointer> faceVec;
1441 tri::PolygonSupport<MeshType,MeshType>::ExtractPolygon(&(mIn.face[i]),vertVec,faceVec);
1442 size_t vn = vertVec.size();
1443 size_t fn = faceVec.size();
1444
1445 CoordType extrude_dir(0,0,0);
1446 for(size_t j=0;j<faceVec.size();++j)
1447 extrude_dir+=vcg::NormalizedTriangleNormal(*faceVec[j]) * DoubleArea(*faceVec[j]);
1448 extrude_dir.Normalize();
1449 extrude_dir = extrude_dir*height/2.0f;
1450
1451 CoordType bary(0,0,0);
1452 for(size_t j=0;j<faceVec.size();++j)
1453 bary+= Barycenter(*faceVec[j]);
1454 bary/=float(faceVec.size());
1455
1456 // Add vertices
1457 // We keeping maps from old vertex to new vertex
1458 std::map<size_t,size_t> topVertMap;
1459 std::map<size_t,size_t> botVertMap;
1460
1461 tri::Allocator<MeshType>::AddVertex(faceM, bary+extrude_dir);
1462 tri::Allocator<MeshType>::AddVertex(faceM, bary-extrude_dir);
1463 for(size_t j=0;j<vn;++j){
1464 CoordType delta = (vertVec[j]->P() - bary);
1465 delta.Normalize();
1466 delta = delta*inset;
1467 tri::Allocator<MeshType>::AddVertex(faceM, vertVec[j]->P()-delta+extrude_dir);
1468 topVertMap[tri::Index(mIn,vertVec[j])] = tri::Index(faceM,faceM.vert.back());
1469 tri::Allocator<MeshType>::AddVertex(faceM, vertVec[j]->P()-delta-extrude_dir);
1470 botVertMap[tri::Index(mIn,vertVec[j])] = tri::Index(faceM,faceM.vert.back());
1471 }
1472
1473 // Build top and bottom faces using the original faces retrieved by the ExtractPolygon
1474 for(size_t j=0;j<fn;++j)
1476 topVertMap[tri::Index(mIn, faceVec[j]->V(0))],
1477 topVertMap[tri::Index(mIn, faceVec[j]->V(1))],
1478 topVertMap[tri::Index(mIn, faceVec[j]->V(2))]);
1479
1480 for(size_t j=0;j<fn;++j)
1482 botVertMap[tri::Index(mIn, faceVec[j]->V(0))],
1483 botVertMap[tri::Index(mIn, faceVec[j]->V(1))],
1484 botVertMap[tri::Index(mIn, faceVec[j]->V(2))]);
1485
1486 // Build side strip
1487 for(size_t j=0;j<vn;++j){
1488 size_t j0=j;
1489 size_t j1=(j+1)%vn;
1490 tri::Allocator<MeshType>::AddFace(faceM, 2+ j0*2 + 0 , 2+ j0*2+1, 2+j1*2+0);
1491 tri::Allocator<MeshType>::AddFace(faceM, 2+ j0*2 + 1 , 2+ j1*2+1, 2+j1*2+0);
1492 }
1493
1494 if(smoothFlag)
1495 {
1496 for(size_t j=0;j<2*vn;++j)
1497 faceM.face[j].SetS();
1498
1501 tri::Refine(faceM, MidPoint<MeshType>(&faceM),0,true);
1502 tri::Refine(faceM, MidPoint<MeshType>(&faceM),0,true);
1504 tri::Smooth<MeshType>::VertexCoordLaplacian(faceM,2,true,true);
1505 }
1506
1508
1509 } // end main loop for each face;
1510}
1511
1512
1513template <class MeshType>
1523void BuildCylinderEdgeShell(MeshType &mIn, MeshType &mOut, float radius=0, int slices=16, int stacks=1 )
1524{
1525 if(radius==0) radius = mIn.bbox.Diag()/100.0f;
1526 if (mIn.edge.size() > 0)
1527 {
1528 for (size_t i = 0; i < mIn.edge.size(); ++i) {
1529 MeshType mCyl;
1531 mCyl, mIn.edge[i].V(0)->P(), mIn.edge[i].V(1)->P(), radius, true, slices, stacks);
1533 }
1534 }
1535 else
1536 {
1537 typedef typename tri::UpdateTopology<MeshType>::PEdge PEdge;
1538 std::vector<PEdge> edgeVec;
1540 for (size_t i = 0; i < edgeVec.size(); ++i) {
1541 MeshType mCyl;
1543 mCyl, edgeVec[i].v[0]->P(), edgeVec[i].v[1]->P(), radius, true, slices, stacks);
1545 }
1546 }
1547}
1548
1549template <class MeshType>
1558void BuildSphereVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, int recDiv=2 )
1559{
1560 if(radius==0) radius = mIn.bbox.Diag()/100.0f;
1561 for(size_t i=0;i<mIn.vert.size();++i)
1562 {
1563 MeshType mSph;
1564 tri::Sphere(mSph,recDiv);
1566 tri::UpdatePosition<MeshType>::Translate(mSph,mIn.vert[i].P());
1568 }
1569}
1570
1571template <class MeshType>
1582void BuildCylinderVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, float height=0, int slices=16, int stacks=1 )
1583{
1584 typedef typename MeshType::CoordType CoordType;
1585 if(radius==0) radius = mIn.bbox.Diag()/100.0f;
1586 if(height==0) height = mIn.bbox.Diag()/200.0f;
1587 for(size_t i=0;i<mIn.vert.size();++i)
1588 {
1589 CoordType p = mIn.vert[i].P();
1590 CoordType n = mIn.vert[i].N().Normalize();
1591
1592 MeshType mCyl;
1593 tri::OrientedCylinder(mCyl,p-n*height,p+n*height,radius,true,slices,stacks);
1595 }
1596}
1597
1598
1599template <class MeshType>
1605void GenerateCameraMesh(MeshType &in){
1606 typedef typename MeshType::CoordType MV;
1607 MV vv[52]={
1608 MV(-0.000122145 , -0.2 ,0.35),
1609 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),
1610 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),
1611 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),
1612 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),
1613 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),
1614 MV(-0.203079 , -0.1 ,0.471362), };
1615 int ff[88][3]={
1616 {0,2,3},
1617 {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},
1618 {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},
1619 {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},
1620 {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},
1621 {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},
1622 {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},
1623 {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},
1624 {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},
1625 {43,36,44},{51,44,45},{51,45,46},{51,46,47},{51,47,48},{51,49,50},{51,50,44},
1626 };
1627
1628 in.Clear();
1631
1632 in.vn=52;in.fn=88;
1633 int i,j;
1634 for(i=0;i<in.vn;i++)
1635 in.vert[i].P()=vv[i];;
1636
1637 std::vector<typename MeshType::VertexPointer> index(in.vn);
1638
1639 typename MeshType::VertexIterator vi;
1640 for(j=0,vi=in.vert.begin();j<in.vn;++j,++vi) index[j] = &*vi;
1641 for(j=0;j<in.fn;++j)
1642 {
1643 in.face[j].V(0)=index[ff[j][0]];
1644 in.face[j].V(1)=index[ff[j][1]];
1645 in.face[j].V(2)=index[ff[j][2]];
1646 }
1647}
1648
1649template <class MeshType>
1661void OrientedRect(MeshType &square, float width, float height, typename MeshType::CoordType c, typename MeshType::CoordType dir=typename MeshType::CoordType(0,0,0), float angleDeg=0,typename MeshType::CoordType preRotTra = typename MeshType::CoordType(0,0,0))
1662{
1663 typedef typename MeshType::ScalarType ScalarType;
1664 typedef typename MeshType::CoordType CoordType;
1665 float zeros[4]={0,0,0,0};
1666 square.Clear();
1667 Matrix44<ScalarType> rotM;
1668 tri::Grid(square,2,2,width,height,zeros);
1669 tri::UpdatePosition<MeshType>::Translate(square,CoordType(-width/2.0f,-height/2.0f,0.0f));
1670 if(angleDeg!=0){
1672 rotM.SetRotateDeg(angleDeg,dir);
1674 }
1677}
1678
1679template <class MeshType>
1690void OrientedSquare(MeshType &square, float width, typename MeshType::CoordType c, typename MeshType::CoordType dir=typename MeshType::CoordType(0,0,0), float angleDeg=0,typename MeshType::CoordType preRotTra = typename MeshType::CoordType(0,0,0))
1691{
1692 OrientedRect(square,width,width,c,dir,angleDeg,preRotTra);
1693}
1694
1695
1696
1698
1699} // End Namespace TriMesh
1700} // End Namespace vcg
1701#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:2015
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:367
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:431
static size_t VertexFromBorderFlag(MeshType &m, bool preserveSelection=false)
This function select the vertices with the border flag set.
Definition: selection.h:508
Auxiliary data structure for computing face face adjacency information.
Definition: topology.h:149
Generation of per-vertex and per-face topological information.
Definition: topology.h:43
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
void OrientedDisk(MeshType &m, typename MeshType::CoordType center, typename MeshType::CoordType norm, float radius, int slices)
Build a disk oriented in 3D space.
Definition: platonic.h:1271
void OrientedCone(MeshType &m, const typename MeshType::CoordType origin, const typename MeshType::CoordType end, const typename MeshType::ScalarType r1, const typename MeshType::ScalarType r2, const int SubDiv=36)
Build a cone/frustum oriented from origin to end.
Definition: platonic.h:661
void BuildFromFaceEdgeSel(TriMeshType &in, EdgeMeshType &out)
Build an edge mesh from the selected edges of a triangle mesh.
Definition: platonic.h:949
void BuildCylinderVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, float height=0, int slices=16, int stacks=1)
Build a cylindrical shell on each vertex aligned with its normal.
Definition: platonic.h:1582
void OrientedRect(MeshType &square, float width, float height, typename MeshType::CoordType c, typename MeshType::CoordType dir=typename MeshType::CoordType(0, 0, 0), float angleDeg=0, typename MeshType::CoordType preRotTra=typename MeshType::CoordType(0, 0, 0))
Build a rectangle in 3D with orientation and optional pre-rotation.
Definition: platonic.h:1661
void Icosahedron(IcoMeshType &in)
Build an icosahedron as a triangular mesh.
Definition: platonic.h:293
void OrientedAnnulus(MeshType &m, typename MeshType::CoordType center, typename MeshType::CoordType norm, float externalRadius, float internalRadius, int slices)
Build an oriented annulus in 3D, centered and rotated.
Definition: platonic.h:1187
void BuildMeshFromCoordVectorIndexVector(MeshType &in, const std::vector< InCoordType > &v, const std::vector< InFaceIndexType > &f)
Build a mesh from coordinate and face-index vectors.
Definition: platonic.h:897
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:560
void OrientedCylinder(MeshType &m, const typename MeshType::CoordType origin, const typename MeshType::CoordType end, float radius, bool capped, int slices=32, int stacks=4)
Build an oriented cylinder along a segment, optionally capped.
Definition: platonic.h:1347
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)
Build an oriented elliptic prism (scaled cylinder), optionally capped.
Definition: platonic.h:1301
void Torus(MeshType &m, float hRingRadius, float vRingRadius, int hRingDiv=24, int vRingDiv=12)
Build a torus mesh around Z axis.
Definition: platonic.h:758
void BuildCylinderEdgeShell(MeshType &mIn, MeshType &mOut, float radius=0, int slices=16, int stacks=1)
Build a tubular shell around edges using oriented cylinders.
Definition: platonic.h:1523
void BuildMeshFromCoordVector(MeshType &in, const V &v)
Build a point-only mesh from coordinate vector (no faces).
Definition: platonic.h:934
void Circle2D(MeshType &m, float radius=1.0, int sides=32)
Build a 2D circle as a polyline (edges only) in XY plane.
Definition: platonic.h:1210
void Dodecahedron(DodMeshType &in)
Build a dodecahedron as a triangular mesh.
Definition: platonic.h:87
void Grid(MeshType &in, int w, int h, float wl, float hl, float *data=0)
Build a regular height-field grid mesh (vertices and faces).
Definition: platonic.h:992
void Octahedron(OctMeshType &in)
Build an octahedron as a triangular mesh.
Definition: platonic.h:254
void BuildSphereVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, int recDiv=2)
Build a spherical shell on each vertex by instancing a small sphere.
Definition: platonic.h:1558
void BuildPrismFaceShell(MeshType &mIn, MeshType &mOut, float height=0, float inset=0, bool smoothFlag=false)
Build a shell made of face-aligned prisms for each face.
Definition: platonic.h:1425
void Hexahedron(MeshType &in)
Build a hexahedron (cube) as a triangular mesh.
Definition: platonic.h:355
void OrientedSquare(MeshType &square, float width, typename MeshType::CoordType c, typename MeshType::CoordType dir=typename MeshType::CoordType(0, 0, 0), float angleDeg=0, typename MeshType::CoordType preRotTra=typename MeshType::CoordType(0, 0, 0))
Build an oriented square (special case of OrientedRect).
Definition: platonic.h:1690
void Annulus(MeshType &m, float externalRadius, float internalRadius, int slices)
Build an annulus (ring) in the XY plane.
Definition: platonic.h:1146
void Square(MeshType &in)
Build a unit square in the XY plane as two triangles.
Definition: platonic.h:408
void SuperEllipsoid(MeshType &m, float rFeature, float sFeature, float tFeature, int hRingDiv=24, int vRingDiv=12)
Build a superellipsoid (superquadric sphere-like surface).
Definition: platonic.h:853
void Sphere(MeshType &in, const int subdiv=3)
Build a geodesic sphere by recursive icosahedron refinement.
Definition: platonic.h:501
void Cylinder(MeshType &m, int slices, int stacks, bool capped=false)
Build a unit cylinder aligned to Y, optionally capped.
Definition: platonic.h:1362
void DodecahedronSym(DodMeshType &in)
Build a symmetric dodecahedron as a triangular mesh.
Definition: platonic.h:137
void SuperToroid(MeshType &m, float hRingRadius, float vRingRadius, float vSquareness, float hSquareness, int hRingDiv=24, int vRingDiv=12)
Build a supertoroid (superquadric torus).
Definition: platonic.h:811
void SparseFaceGrid(MeshType &in, const std::vector< int > &grid, int w, int h)
Build faces for a sparsely sampled regular grid.
Definition: platonic.h:1072
void GenerateCameraMesh(MeshType &in)
Build a simple camera-shaped mesh (mainly for visualization).
Definition: platonic.h:1605
void Box(MeshType &in, const typename MeshType::BoxType &bb)
Build a box aligned with the axes from a bounding box.
Definition: platonic.h:704
void SphericalCap(MeshType &in, float angleRad, const int subdiv=3)
Build a spherical cap from a hexagon refined on the sphere.
Definition: platonic.h:450
void Disk(MeshType &m, int slices)
Build a unit disk (triangle fan) in the XY plane.
Definition: platonic.h:1234
void FaceGrid(MeshType &in, int w, int h)
Build faces for a regular grid given pre-allocated vertices.
Definition: platonic.h:1023
void Tetrahedron(TetraMeshType &in)
Build a tetrahedron as a triangular mesh.
Definition: platonic.h:54
Definition: color4.h:30
Definition: refine.h:126