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>
447void SphericalCap(MeshType &in, float angleRad, const int subdiv = 3 )
448{
449 typedef typename MeshType::CoordType CoordType;
450 typedef typename MeshType::VertexIterator VertexIterator;
451 in.Clear();
452 tri::Allocator<MeshType>::AddVertex(in,CoordType(0,0,0));
453 for(int i=0;i<6;++i)
454 tri::Allocator<MeshType>::AddVertex(in,CoordType(cos(math::ToRad(i*60.0)),sin(math::ToRad(i*60.0)),0));
455
456 for(int i=0;i<6;++i)
457 tri::Allocator<MeshType>::AddFace(in,&(in.vert[0]),&(in.vert[1+i]),&(in.vert[1+(i+1)%6]));
458
460 for(int i=0;i<subdiv;++i)
461 {
462 tri::Refine(in, MidPoint<MeshType>(&in));
463
466
467 for(int i=0;i<in.vn;++i)
468 if(in.vert[i].IsB())
469 in.vert[i].P().Normalize();
470
473 tri::Smooth<MeshType>::VertexCoordLaplacian(in,10,true);
474 }
475
476 float angleHalfRad = angleRad /2.0f;
477 float width = sin(angleHalfRad);
480 for(VertexIterator vi=in.vert.begin(); vi!=in.vert.end();++vi)
481 {
482 float cosVi = vi->P().Norm();
483 float angVi = asin (cosVi);
484 vi->P()[2] = cos(angVi) - cos(angleHalfRad);
485 }
486}
487
488// this function build a sphere starting from a eventually not empty mesh.
489// If the mesh is not empty it is 'spherified' and used as base for the subdivision process.
490// otherwise an icosahedron is used.
491template <class MeshType>
498void Sphere(MeshType &in, const int subdiv = 3 )
499{
500 typedef typename MeshType::CoordType CoordType;
501 typedef typename MeshType::VertexIterator VertexIterator;
502 typedef typename MeshType::FaceIterator FaceIterator;
503 if(in.vn==0 && in.fn==0) Icosahedron(in);
504
505 for(VertexIterator vi = in.vert.begin(); vi!=in.vert.end();++vi)
506 vi->P().Normalize();
507
508 for(int i = 0 ; i < subdiv; ++i)
509 {
510 MeshType newM;
511 for(FaceIterator fi=in.face.begin();fi!=in.face.end();++fi)
512 {
513 CoordType me01 = (fi->P(0)+fi->P(1))/2.0;
514 CoordType me12 = (fi->P(1)+fi->P(2))/2.0;
515 CoordType me20 = (fi->P(2)+fi->P(0))/2.0;
516 tri::Allocator<MeshType>::AddFace(newM,me01,me12,me20);
517 tri::Allocator<MeshType>::AddFace(newM,fi->P(0),me01,me20);
518 tri::Allocator<MeshType>::AddFace(newM,fi->P(1),me12,me01);
519 tri::Allocator<MeshType>::AddFace(newM,fi->P(2),me20,me12);
520 }
523
524 for(VertexIterator vi = in.vert.begin(); vi != in.vert.end(); ++vi)
525 vi->P().Normalize();
526 }
527}
528
529template <class MeshType>
538void Sphere(MeshType & m, const typename MeshType::CoordType & position, typename MeshType::ScalarType radius = 0, const int subdiv = 3)
539{
540 m.Clear();
541 tri::Sphere(m, subdiv);
544}
545
547
556template <class MeshType>
557void Cone( MeshType& in,
558 const typename MeshType::ScalarType r1,
559 const typename MeshType::ScalarType r2,
560 const typename MeshType::ScalarType h,
561 const int SubDiv = 36 )
562{
563 typedef typename MeshType::CoordType CoordType;
564 typedef typename MeshType::VertexPointer VertexPointer;
565 typedef typename MeshType::VertexIterator VertexIterator;
566 typedef typename MeshType::FaceIterator FaceIterator;
567
568 int i,b1,b2;
569 in.Clear();
570 int VN,FN;
571 if(r1==0 || r2==0) {
572 VN=SubDiv+2;
573 FN=SubDiv*2;
574 } else {
575 VN=SubDiv*2+2;
576 FN=SubDiv*4;
577 }
578
581 VertexPointer *ivp = new VertexPointer[VN];
582
583 VertexIterator vi=in.vert.begin();
584 ivp[0]=&*vi;(*vi).P()=CoordType ( 0,-h/2.0,0 ); ++vi;
585 ivp[1]=&*vi;(*vi).P()=CoordType ( 0, h/2.0,0 ); ++vi;
586
587 b1 = b2 = 2;
588 int cnt=2;
589 if(r1!=0)
590 {
591 for(i=0;i<SubDiv;++i)
592 {
593 double a = math::ToRad(i*360.0/SubDiv);
594 ivp[cnt]=&*vi; (*vi).P()= CoordType(r1*cos(a), -h/2.0, r1*sin(a)); ++vi;++cnt;
595 }
596 b2 += SubDiv;
597 }
598
599 if(r2!=0)
600 {
601 for(i=0;i<SubDiv;++i)
602 {
603 double a = math::ToRad(i*360.0/SubDiv);
604 ivp[cnt]=&*vi; (*vi).P()= CoordType( r2*cos(a), h/2.0, r2*sin(a)); ++vi;++cnt;
605 }
606 }
607
608 FaceIterator fi=in.face.begin();
609
610 if(r1!=0) for(i=0;i<SubDiv;++i,++fi) {
611 (*fi).V(0)=ivp[0];
612 (*fi).V(1)=ivp[b1+i];
613 (*fi).V(2)=ivp[b1+(i+1)%SubDiv];
614 }
615
616 if(r2!=0) for(i=0;i<SubDiv;++i,++fi) {
617 (*fi).V(0)=ivp[1];
618 (*fi).V(2)=ivp[b2+i];
619 (*fi).V(1)=ivp[b2+(i+1)%SubDiv];
620 }
621
622 if(r1==0) for(i=0;i<SubDiv;++i,++fi)
623 {
624 (*fi).V(0)=ivp[0];
625 (*fi).V(1)=ivp[b2+i];
626 (*fi).V(2)=ivp[b2+(i+1)%SubDiv];
627 }
628 if(r2==0) for(i=0;i<SubDiv;++i,++fi){
629 (*fi).V(0)=ivp[1];
630 (*fi).V(2)=ivp[b1+i];
631 (*fi).V(1)=ivp[b1+(i+1)%SubDiv];
632 }
633
634 if(r1!=0 && r2!=0)for(i=0;i<SubDiv;++i)
635 {
636 (*fi).V(0)=ivp[b1+i];
637 (*fi).V(1)=ivp[b2+i];
638 (*fi).V(2)=ivp[b2+(i+1)%SubDiv];
639 ++fi;
640 (*fi).V(0)=ivp[b1+i];
641 (*fi).V(1)=ivp[b2+(i+1)%SubDiv];
642 (*fi).V(2)=ivp[b1+(i+1)%SubDiv];
643 ++fi;
644 }
645}
646
647template <class MeshType>
658void OrientedCone(MeshType & m,
659 const typename MeshType::CoordType origin,
660 const typename MeshType::CoordType end,
661 const typename MeshType::ScalarType r1,
662 const typename MeshType::ScalarType r2,
663 const int SubDiv = 36 )
664{
665 typedef typename MeshType::ScalarType ScalarType;
666 typedef typename MeshType::CoordType CoordType;
667 typedef Matrix44<typename MeshType::ScalarType> Matrix44x;
668 Cone(m,r1,r2,Distance(origin,end),SubDiv);
669
670 tri::UpdatePosition<MeshType>::Translate(m,CoordType(0,Distance(origin,end)/2,0));
671
672 CoordType norm = end-origin;
673 ScalarType angleRad = Angle(CoordType(0,1,0),norm);
674 const ScalarType Delta= 0.000000001;
675 Matrix44x rotM;
676 if (fabs(angleRad)<Delta)
677 rotM.SetIdentity();
678 else
679 if (fabs(angleRad-M_PI)<Delta)
680 {
681 CoordType axis = CoordType(0,0,1)^norm;
682 rotM.SetRotateRad(angleRad,axis);
683 }
684 else
685 {
686 CoordType axis = CoordType(0,1,0)^norm;
687 rotM.SetRotateRad(angleRad,axis);
688 }
691}
692
693
694template <class MeshType >
701void Box(MeshType &in, const typename MeshType::BoxType & bb )
702{
703 typedef typename MeshType::CoordType CoordType;
704 typedef typename MeshType::VertexPointer VertexPointer;
705 typedef typename MeshType::VertexIterator VertexIterator;
706 typedef typename MeshType::FaceIterator FaceIterator;
707
708 in.Clear();
710 VertexPointer ivp[8];
711
712 VertexIterator vi=in.vert.begin();
713 ivp[0]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.min[2]); ++vi;
714 ivp[1]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.min[2]); ++vi;
715 ivp[2]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.min[2]); ++vi;
716 ivp[3]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.min[2]); ++vi;
717 ivp[4]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.max[2]); ++vi;
718 ivp[5]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.max[2]); ++vi;
719 ivp[6]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.max[2]); ++vi;
720 ivp[7]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.max[2]);
721
722 Allocator<MeshType>::AddFace(in,ivp[2],ivp[1],ivp[0]);
723 Allocator<MeshType>::AddFace(in,ivp[1],ivp[2],ivp[3]);
724 Allocator<MeshType>::AddFace(in,ivp[4],ivp[2],ivp[0]);
725 Allocator<MeshType>::AddFace(in,ivp[2],ivp[4],ivp[6]);
726 Allocator<MeshType>::AddFace(in,ivp[1],ivp[4],ivp[0]);
727 Allocator<MeshType>::AddFace(in,ivp[4],ivp[1],ivp[5]);
728 Allocator<MeshType>::AddFace(in,ivp[6],ivp[5],ivp[7]);
729 Allocator<MeshType>::AddFace(in,ivp[5],ivp[6],ivp[4]);
730 Allocator<MeshType>::AddFace(in,ivp[3],ivp[6],ivp[7]);
731 Allocator<MeshType>::AddFace(in,ivp[6],ivp[3],ivp[2]);
732 Allocator<MeshType>::AddFace(in,ivp[5],ivp[3],ivp[7]);
733 Allocator<MeshType>::AddFace(in,ivp[3],ivp[5],ivp[1]);
734
735 if (HasPerFaceFlags(in)) {
736 FaceIterator fi=in.face.begin();
737 for (int k=0; k<12; k++) {
738 (*fi).SetF(0); fi++;
739 }
740 }
741
742}
743
744// Torus
745template <class MeshType>
755void Torus(MeshType &m, float hRingRadius, float vRingRadius, int hRingDiv=24, int vRingDiv=12 )
756{
757 typedef typename MeshType::CoordType CoordType;
758 typedef typename MeshType::ScalarType ScalarType;
759 typedef Matrix44<ScalarType> Matrix44x;
760 m.Clear();
761 ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
762 ScalarType angleStepH = (2.0f*M_PI)/hRingDiv;
763
764 Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
765 for(int i=0;i<hRingDiv+1;++i)
766 {
767 Matrix44x RotM; RotM.SetRotateRad(float(i%hRingDiv)*angleStepH,CoordType(0,0,1));
768 for(int j=0;j<vRingDiv+1;++j)
769 {
770 CoordType p;
771 p[0]= vRingRadius*cos(float(j%vRingDiv)*angleStepV) + hRingRadius;
772 p[1] = 0;
773 p[2]= vRingRadius*sin(float(j%vRingDiv)*angleStepV);
774
775 m.vert[i*(vRingDiv+1)+j].P() = RotM*p;
776 }
777 }
778 FaceGrid(m,vRingDiv+1,hRingDiv+1);
781
782}
783
786template <class ScalarType>
787static ScalarType _SQfnC(ScalarType a, ScalarType b){
788 return math::Sgn(cos(a))*pow(fabs(cos(a)),b);
789}
790template <class ScalarType>
791static ScalarType _SQfnS(ScalarType a, ScalarType b){
792 return math::Sgn(sin(a))*pow(fabs(sin(a)),b);
793}
794
795
807template <class MeshType>
808void SuperToroid(MeshType &m, float hRingRadius, float vRingRadius, float vSquareness, float hSquareness, int hRingDiv=24, int vRingDiv=12 )
809{
810 typedef typename MeshType::CoordType CoordType;
811 typedef typename MeshType::ScalarType ScalarType;
812 m.Clear();
813 ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
814 ScalarType angleStepH = (2.0f*M_PI)/hRingDiv;
815
816 ScalarType u,v;
817 int count;
818 Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
819 for(int i=0;i<hRingDiv+1;++i)
820 {
821 u=float(i%hRingDiv)*angleStepH;
822 count=0;
823 for(int j=vRingDiv;j>=0;--j)
824 {
825 CoordType p;
826 v=float(j%vRingDiv)*angleStepV;
827 p[0]= (hRingRadius+vRingRadius*_SQfnC(u,vSquareness))*_SQfnC(v,hSquareness);;
828 p[1]= (hRingRadius+vRingRadius*_SQfnC(u,vSquareness))*_SQfnS(v,hSquareness);
829 p[2] = vRingRadius*_SQfnS(u,vSquareness);
830 m.vert[i*(vRingDiv+1)+count].P() = p;
831 count++;
832 }
833 }
834 FaceGrid(m,vRingDiv+1,hRingDiv+1);
837
838}
849template <class MeshType>
850void SuperEllipsoid(MeshType &m, float rFeature, float sFeature, float tFeature, int hRingDiv=24, int vRingDiv=12 )
851{
852 typedef typename MeshType::CoordType CoordType;
853 typedef typename MeshType::ScalarType ScalarType;
854 m.Clear();
855 ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
856 ScalarType angleStepH = (1.0f*M_PI)/hRingDiv;
857 float u;
858 float v;
859 Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
860 for(int i=0;i<hRingDiv+1;++i)
861 {
862 //u=ScalarType(i%hRingDiv)*angleStepH + angleStepH/2.0;
863 u=i*angleStepH;
864 for(int j=0;j<vRingDiv+1;++j)
865 {
866 CoordType p;
867 v=ScalarType(j%vRingDiv)*angleStepV;
868 p[0] = _SQfnC(v,2/rFeature)*_SQfnC(u,2/rFeature);
869 p[1] = _SQfnC(v,2/sFeature)*_SQfnS(u,2/sFeature);
870 p[2] = _SQfnS(v,2/tFeature);
871 m.vert[i*(vRingDiv+1)+j].P() = p;
872 }
873 }
874 FaceGrid(m,vRingDiv+1,hRingDiv+1);
875 tri::Clean<MeshType>::MergeCloseVertex(m,ScalarType(angleStepV*angleStepV*0.001));
877 bool oriented, orientable;
879 tri::Clean<MeshType>::OrientCoherentlyMesh(m,oriented,orientable);
881}
882
893template <class MeshType, class InCoordType, class InFaceIndexType >
894void BuildMeshFromCoordVectorIndexVector(MeshType & in, const std::vector<InCoordType> & v, const std::vector<InFaceIndexType> & f)
895{
896 typedef typename MeshType::CoordType CoordType;
897
898 in.Clear();
901
902 for(size_t i=0;i<v.size();++i)
903 {
904 const InCoordType &vv = v[i];
905 in.vert[i].P() = CoordType( vv[0],vv[1],vv[2]);
906 }
907
908 for(size_t i=0;i<f.size();++i)
909 {
910 const InFaceIndexType &ff= f[i];
911 assert( ff[0]>=0 && ff[0]<in.vn);
912 assert( ff[1]>=0 && ff[1]<in.vn);
913 assert( ff[2]>=0 && ff[2]<in.vn);
914 in.face[i].V(0) = &in.vert[ ff[0] ];
915 in.face[i].V(1) = &in.vert[ ff[1] ];
916 in.face[i].V(2) = &in.vert[ ff[2] ];
917 }
918
920}
921
922
923template <class MeshType,class V>
931void BuildMeshFromCoordVector( MeshType & in, const V & v)
932{
933 std::vector<Point3i> dummyfaceVec;
934 BuildMeshFromCoordVectorIndexVector(in,v,dummyfaceVec);
935}
936
937
938template <class TriMeshType,class EdgeMeshType >
946void BuildFromFaceEdgeSel(TriMeshType &in, EdgeMeshType &out)
947{
948 tri::RequireCompactness(in);
949 std::vector<typename tri::UpdateTopology<TriMeshType>::PEdge> edgevec;
951 out.Clear();
952 for(size_t i=0;i<in.vert.size();++i)
953 tri::Allocator<EdgeMeshType>::AddVertex(out, in.vert[i].P());
955
956 for(size_t i=0;i<edgevec.size();++i)
957 {
958 int i0 = tri::Index(in,edgevec[i].v[0]);
959 int i1 = tri::Index(in,edgevec[i].v[1]);
960 out.vert[i0].SetV();
961 out.vert[i1].SetV();
962 tri::Allocator<EdgeMeshType>::AddEdge(out,&out.vert[i0],&out.vert[i1]);
963 if(in.vert[i0].IsS()) out.vert[i0].SetS();
964 if(in.vert[i1].IsS()) out.vert[i1].SetS();
965 }
966
967 for(size_t i=0;i<out.vert.size();++i)
968 if(!out.vert[i].IsV()) tri::Allocator<EdgeMeshType>::DeleteVertex(out,out.vert[i]);
969
971}
972
973// Build a regular grid mesh as a typical height field mesh
974// 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)
975// z is taken from the <data> array
976// Once generated the vertex positions it uses the FaceGrid function to generate the faces;
977
978template <class MeshType>
989void Grid(MeshType & in, int w, int h, float wl, float hl, float *data=0)
990{
991 typedef typename MeshType::CoordType CoordType;
992
993 in.Clear();
995
996 float wld=wl/float(w-1);
997 float hld=hl/float(h-1);
998 float zVal=0;
999 for(int i=0;i<h;++i)
1000 for(int j=0;j<w;++j)
1001 {
1002 if(data) zVal=data[i*w+j];
1003 in.vert[i*w+j].P()=CoordType ( j*wld, i*hld, zVal) ;
1004 }
1005 FaceGrid(in,w,h);
1006}
1007
1008
1009// Build a regular grid mesh of faces as a typical height field mesh
1010// Vertexes are assumed to be already be allocated.
1011
1012template <class MeshType>
1020void FaceGrid(MeshType & in, int w, int h)
1021{
1022 assert(in.vn == (int)in.vert.size()); // require a compact vertex vector
1023 assert(in.vn >= w*h); // the number of vertices should match the number of expected grid vertices
1024
1025 Allocator<MeshType>::AddFaces(in,(w-1)*(h-1)*2);
1026
1027// i+0,j+0 -- i+0,j+1
1028// | \ |
1029// | \ |
1030// | \ |
1031// | \ |
1032// i+1,j+0 -- i+1,j+1
1033//
1034 for(int i=0;i<h-1;++i)
1035 for(int j=0;j<w-1;++j)
1036 {
1037 in.face[2*(i*(w-1)+j)+0].V(0) = &(in.vert[(i+1)*w+j+1]);
1038 in.face[2*(i*(w-1)+j)+0].V(1) = &(in.vert[(i+0)*w+j+1]);
1039 in.face[2*(i*(w-1)+j)+0].V(2) = &(in.vert[(i+0)*w+j+0]);
1040
1041 in.face[2*(i*(w-1)+j)+1].V(0) = &(in.vert[(i+0)*w+j+0]);
1042 in.face[2*(i*(w-1)+j)+1].V(1) = &(in.vert[(i+1)*w+j+0]);
1043 in.face[2*(i*(w-1)+j)+1].V(2) = &(in.vert[(i+1)*w+j+1]);
1044 }
1045
1046 if (HasPerFaceFlags(in)) {
1047 for (int k=0; k<(h-1)*(w-1)*2; k++) {
1048 in.face[k].SetF(2);
1049 }
1050 }
1051
1052}
1053
1054
1055// Build a regular grid mesh of faces as the resulto of a sparsely regularly sampled height field.
1056// Vertexes are assumed to be already be allocated, but not all the grid vertexes are present.
1057// For this purpose vector with a grid of indexes is also passed.
1058// Negative indexes in this vector means that there is no vertex.
1059
1060template <class MeshType>
1069void SparseFaceGrid(MeshType & in, const std::vector<int> &grid, int w, int h)
1070{
1071 tri::RequireCompactness(in);
1072 assert(in.vn <= w*h); // the number of vertices should match the number of expected grid vertices
1073
1074// V0 V1
1075// i+0,j+0 -- i+0,j+1
1076// | \ |
1077// | \ |
1078// | \ |
1079// | \ |
1080// i+1,j+0 -- i+1,j+1
1081// V2 V3
1082
1083
1084 for(int i=0;i<h-1;++i)
1085 for(int j=0;j<w-1;++j)
1086 {
1087 int V0i= grid[(i+0)*w+j+0];
1088 int V1i= grid[(i+0)*w+j+1];
1089 int V2i= grid[(i+1)*w+j+0];
1090 int V3i= grid[(i+1)*w+j+1];
1091
1092 int ndone=0;
1093 bool quad = (V0i>=0 && V1i>=0 && V2i>=0 && V3i>=0 ) && tri::HasPerFaceFlags(in);
1094
1095 if(V0i>=0 && V2i>=0 && V3i>=0 )
1096 {
1097 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
1098 f->V(0)=&(in.vert[V3i]);
1099 f->V(1)=&(in.vert[V2i]);
1100 f->V(2)=&(in.vert[V0i]);
1101 if (quad) f->SetF(2);
1102 ndone++;
1103 }
1104 if(V0i>=0 && V1i>=0 && V3i>=0 )
1105 {
1106 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
1107 f->V(0)=&(in.vert[V0i]);
1108 f->V(1)=&(in.vert[V1i]);
1109 f->V(2)=&(in.vert[V3i]);
1110 if (quad) f->SetF(2);
1111 ndone++;
1112 }
1113
1114 if (ndone==0) { // try diag the other way
1115 if(V2i>=0 && V0i>=0 && V1i>=0 )
1116 {
1117 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
1118 f->V(0)=&(in.vert[V2i]);
1119 f->V(1)=&(in.vert[V0i]);
1120 f->V(2)=&(in.vert[V1i]);
1121 ndone++;
1122 }
1123 if(V1i>=0 && V3i>=0 && V2i>=0 )
1124 {
1125 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
1126 f->V(0)=&(in.vert[V1i]);
1127 f->V(1)=&(in.vert[V3i]);
1128 f->V(2)=&(in.vert[V2i]);
1129 ndone++;
1130 }
1131 }
1132 }
1133}
1134template <class MeshType>
1143void Annulus(MeshType & m, float externalRadius, float internalRadius, int slices)
1144{
1145 m.Clear();
1146 typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices*2);
1147
1148 for ( int j = 0; j < slices; ++j)
1149 {
1150 float x = cos( 2.0 * M_PI / slices * j);
1151 float y = sin( 2.0 * M_PI / slices * j);
1152
1153 (*vi).P() = typename MeshType::CoordType(x,y,0)*internalRadius;
1154 ++vi;
1155 (*vi).P() = typename MeshType::CoordType(x,y,0)*externalRadius;
1156 ++vi;
1157 }
1158 typename MeshType::FaceIterator fi ;
1159 for ( int j = 0; j < slices; ++j)
1160 {
1162 (*fi).V(0) = &m.vert[ ((j+0)*2+0)%(slices*2) ];
1163 (*fi).V(1) = &m.vert[ ((j+1)*2+1)%(slices*2) ];
1164 (*fi).V(2) = &m.vert[ ((j+0)*2+1)%(slices*2) ];
1165
1167 (*fi).V(0) = &m.vert[ ((j+1)*2+0)%(slices*2) ];
1168 (*fi).V(1) = &m.vert[ ((j+1)*2+1)%(slices*2) ];
1169 (*fi).V(2) = &m.vert[ ((j+0)*2+0)%(slices*2) ];
1170 }
1171}
1172
1173template <class MeshType>
1184void OrientedAnnulus(MeshType & m, typename MeshType::CoordType center, typename MeshType::CoordType norm, float externalRadius, float internalRadius, int slices)
1185{
1186 typedef typename MeshType::ScalarType ScalarType;
1187 typedef typename MeshType::CoordType CoordType;
1188 Annulus(m,externalRadius,internalRadius, slices);
1189 ScalarType angleRad = Angle(CoordType(0,0,1),norm);
1190 CoordType axis = CoordType(0,0,1)^norm;
1191
1192 Matrix44<ScalarType> rotM;
1193 rotM.SetRotateRad(angleRad,axis);
1196}
1197
1198
1199template <class MeshType>
1207void Circle2D(MeshType & m, float radius=1.0, int sides=32)
1208{
1209 m.Clear();
1210 for ( int j = 0; j < sides; ++j)
1211 {
1212 float x = cos( 2.0 * M_PI / sides * j)*radius;
1213 float y = sin( 2.0 * M_PI / sides * j)*radius;
1214
1216 }
1217for ( int j = 0; j < sides; ++j)
1218 {
1219 int a = j;
1220 int b = (j+1)%sides;
1221 tri::Allocator<MeshType>::AddEdge(m, &m.vert[a], &m.vert[b]);
1222 }
1223}
1224template <class MeshType>
1231void Disk(MeshType & m, int slices)
1232{
1233 m.Clear();
1234 typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices+1);
1235 (*vi).P() = typename MeshType::CoordType(0,0,0);
1236 ++vi;
1237
1238 for ( int j = 0; j < slices; ++j)
1239 {
1240 float x = cos( 2.0 * M_PI / slices * j);
1241 float y = sin( 2.0 * M_PI / slices * j);
1242
1243 (*vi).P() = typename MeshType::CoordType(x,y,0);
1244 ++vi;
1245 }
1246 typename MeshType::FaceIterator fi ;
1247 for ( int j = 0; j < slices; ++j)
1248 {
1249 int a = 1+(j+0)%slices;
1250 int b = 1+(j+1)%slices;
1252 (*fi).V(0) = &m.vert[ 0 ];
1253 (*fi).V(1) = &m.vert[ a ];
1254 (*fi).V(2) = &m.vert[ b ];
1255 }
1256}
1257
1258template <class MeshType>
1268void OrientedDisk(MeshType &m, typename MeshType::CoordType center, typename MeshType::CoordType norm, float radius, int slices)
1269{
1270 typedef typename MeshType::ScalarType ScalarType;
1271 typedef typename MeshType::CoordType CoordType;
1272
1273 Disk(m,slices);
1275 ScalarType angleRad = Angle(CoordType(0,0,1),norm);
1276 CoordType axis = CoordType(0,0,1)^norm;
1277
1278 Matrix44<ScalarType> rotM;
1279 rotM.SetRotateRad(angleRad,axis);
1282}
1283
1284template <class MeshType>
1298void 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 )
1299{
1300 typedef typename MeshType::ScalarType ScalarType;
1301 typedef typename MeshType::CoordType CoordType;
1302 typedef Matrix44<typename MeshType::ScalarType> Matrix44x;
1303 Cylinder(m,slices,stacks,capped);
1304 tri::UpdatePosition<MeshType>::Translate(m,CoordType(0,1,0));
1305 tri::UpdatePosition<MeshType>::Scale(m,CoordType(1,0.5f,1));
1306 tri::UpdatePosition<MeshType>::Scale(m,CoordType(xScale,1.0f,yScale));
1307
1308 float height = Distance(origin,end);
1309 tri::UpdatePosition<MeshType>::Scale(m,CoordType(radius,height,radius));
1310 CoordType norm = end-origin;
1311 ScalarType angleRad = Angle(CoordType(0,1,0),norm);
1312 const ScalarType Delta= 0.000000001;
1313 Matrix44x rotM;
1314 if (fabs(angleRad)<Delta)
1315 rotM.SetIdentity();
1316 else
1317 if (fabs(angleRad-M_PI)<Delta)
1318 {
1319 CoordType axis = CoordType(0,0,1)^norm;
1320 rotM.SetRotateRad(angleRad,axis);
1321 }
1322 else
1323 {
1324 CoordType axis = CoordType(0,1,0)^norm;
1325 rotM.SetRotateRad(angleRad,axis);
1326 }
1329
1330}
1331
1332template <class MeshType>
1344void OrientedCylinder(MeshType & m, const typename MeshType::CoordType origin, const typename MeshType::CoordType end, float radius, bool capped, int slices=32, int stacks=4 )
1345{
1346 OrientedEllipticPrism(m,origin,end,radius,1.0f,1.0f,capped,slices,stacks);
1347}
1348
1349
1350template <class MeshType>
1359void Cylinder(MeshType & m, int slices, int stacks, bool capped=false)
1360{
1361 m.Clear();
1362 typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices*(stacks+1));
1363 for ( int i = 0; i < stacks+1; ++i)
1364 for ( int j = 0; j < slices; ++j)
1365 {
1366 float x,y,h;
1367 x = cos( 2.0 * M_PI / slices * j);
1368 y = sin( 2.0 * M_PI / slices * j);
1369 h = 2 * i / (float)(stacks) - 1;
1370
1371 (*vi).P() = typename MeshType::CoordType(x,h,y);
1372 ++vi;
1373 }
1374
1375 for ( int j = 0; j < stacks; ++j)
1376 for ( int i = 0; i < slices; ++i)
1377 {
1378 int a,b,c,d;
1379 a = (j+0)*slices + i;
1380 b = (j+1)*slices + i;
1381 c = (j+1)*slices + (i+1)%slices;
1382 d = (j+0)*slices + (i+1)%slices;
1383 if(((i+j)%2) == 0){
1384 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ a ], &m.vert[ b ], &m.vert[ c ]);
1385 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ c ], &m.vert[ d ], &m.vert[ a ]);
1386 }
1387 else{
1388 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ b ], &m.vert[ c ], &m.vert[ d ]);
1389 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ d ], &m.vert[ a ], &m.vert[ b ]);
1390 }
1391 }
1392
1393 if(capped)
1394 {
1395 tri::Allocator<MeshType>::AddVertex(m,typename MeshType::CoordType(0,-1,0));
1396 tri::Allocator<MeshType>::AddVertex(m,typename MeshType::CoordType(0, 1,0));
1397 int base = 0;
1398 for ( int i = 0; i < slices; ++i)
1399 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ m.vn-2 ], &m.vert[ base+i ], &m.vert[ base+(i+1)%slices ]);
1400 base = (stacks)*slices;
1401 for ( int i = 0; i < slices; ++i)
1402 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ m.vn-1 ], &m.vert[ base+(i+1)%slices ], &m.vert[ base+i ]);
1403 }
1404 if (HasPerFaceFlags(m)) {
1405 for (typename MeshType::FaceIterator fi=m.face.begin(); fi!=m.face.end(); fi++) {
1406 (*fi).SetF(2);
1407 }
1408 }
1409}
1410
1421template <class MeshType>
1422void BuildPrismFaceShell(MeshType &mIn, MeshType &mOut, float height=0, float inset=0, bool smoothFlag=false )
1423{
1424 typedef typename MeshType::VertexPointer VertexPointer;
1425 typedef typename MeshType::FacePointer FacePointer;
1426 typedef typename MeshType::CoordType CoordType;
1427 if(height==0) height = mIn.bbox.Diag()/100.0f;
1428 if(inset==0) inset = mIn.bbox.Diag()/200.0f;
1432
1433 for(size_t i=0;i<mIn.face.size();++i) if(!mIn.face[i].IsV())
1434 {
1435 MeshType faceM;
1436 std::vector<VertexPointer> vertVec;
1437 std::vector<FacePointer> faceVec;
1438 tri::PolygonSupport<MeshType,MeshType>::ExtractPolygon(&(mIn.face[i]),vertVec,faceVec);
1439 size_t vn = vertVec.size();
1440 size_t fn = faceVec.size();
1441
1442 CoordType extrude_dir(0,0,0);
1443 for(size_t j=0;j<faceVec.size();++j)
1444 extrude_dir+=vcg::NormalizedTriangleNormal(*faceVec[j]) * DoubleArea(*faceVec[j]);
1445 extrude_dir.Normalize();
1446 extrude_dir = extrude_dir*height/2.0f;
1447
1448 CoordType bary(0,0,0);
1449 for(size_t j=0;j<faceVec.size();++j)
1450 bary+= Barycenter(*faceVec[j]);
1451 bary/=float(faceVec.size());
1452
1453 // Add vertices
1454 // We keeping maps from old vertex to new vertex
1455 std::map<size_t,size_t> topVertMap;
1456 std::map<size_t,size_t> botVertMap;
1457
1458 tri::Allocator<MeshType>::AddVertex(faceM, bary+extrude_dir);
1459 tri::Allocator<MeshType>::AddVertex(faceM, bary-extrude_dir);
1460 for(size_t j=0;j<vn;++j){
1461 CoordType delta = (vertVec[j]->P() - bary);
1462 delta.Normalize();
1463 delta = delta*inset;
1464 tri::Allocator<MeshType>::AddVertex(faceM, vertVec[j]->P()-delta+extrude_dir);
1465 topVertMap[tri::Index(mIn,vertVec[j])] = tri::Index(faceM,faceM.vert.back());
1466 tri::Allocator<MeshType>::AddVertex(faceM, vertVec[j]->P()-delta-extrude_dir);
1467 botVertMap[tri::Index(mIn,vertVec[j])] = tri::Index(faceM,faceM.vert.back());
1468 }
1469
1470 // Build top and bottom faces using the original faces retrieved by the ExtractPolygon
1471 for(size_t j=0;j<fn;++j)
1473 topVertMap[tri::Index(mIn, faceVec[j]->V(0))],
1474 topVertMap[tri::Index(mIn, faceVec[j]->V(1))],
1475 topVertMap[tri::Index(mIn, faceVec[j]->V(2))]);
1476
1477 for(size_t j=0;j<fn;++j)
1479 botVertMap[tri::Index(mIn, faceVec[j]->V(0))],
1480 botVertMap[tri::Index(mIn, faceVec[j]->V(1))],
1481 botVertMap[tri::Index(mIn, faceVec[j]->V(2))]);
1482
1483 // Build side strip
1484 for(size_t j=0;j<vn;++j){
1485 size_t j0=j;
1486 size_t j1=(j+1)%vn;
1487 tri::Allocator<MeshType>::AddFace(faceM, 2+ j0*2 + 0 , 2+ j0*2+1, 2+j1*2+0);
1488 tri::Allocator<MeshType>::AddFace(faceM, 2+ j0*2 + 1 , 2+ j1*2+1, 2+j1*2+0);
1489 }
1490
1491 if(smoothFlag)
1492 {
1493 for(size_t j=0;j<2*vn;++j)
1494 faceM.face[j].SetS();
1495
1498 tri::Refine(faceM, MidPoint<MeshType>(&faceM),0,true);
1499 tri::Refine(faceM, MidPoint<MeshType>(&faceM),0,true);
1501 tri::Smooth<MeshType>::VertexCoordLaplacian(faceM,2,true,true);
1502 }
1503
1505
1506 } // end main loop for each face;
1507}
1508
1509
1510template <class MeshType>
1520void BuildCylinderEdgeShell(MeshType &mIn, MeshType &mOut, float radius=0, int slices=16, int stacks=1 )
1521{
1522 if(radius==0) radius = mIn.bbox.Diag()/100.0f;
1523 if (mIn.edge.size() > 0)
1524 {
1525 for (size_t i = 0; i < mIn.edge.size(); ++i) {
1526 MeshType mCyl;
1528 mCyl, mIn.edge[i].V(0)->P(), mIn.edge[i].V(1)->P(), radius, true, slices, stacks);
1530 }
1531 }
1532 else
1533 {
1534 typedef typename tri::UpdateTopology<MeshType>::PEdge PEdge;
1535 std::vector<PEdge> edgeVec;
1537 for (size_t i = 0; i < edgeVec.size(); ++i) {
1538 MeshType mCyl;
1540 mCyl, edgeVec[i].v[0]->P(), edgeVec[i].v[1]->P(), radius, true, slices, stacks);
1542 }
1543 }
1544}
1545
1546template <class MeshType>
1555void BuildSphereVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, int recDiv=2 )
1556{
1557 if(radius==0) radius = mIn.bbox.Diag()/100.0f;
1558 for(size_t i=0;i<mIn.vert.size();++i)
1559 {
1560 MeshType mSph;
1561 tri::Sphere(mSph,recDiv);
1563 tri::UpdatePosition<MeshType>::Translate(mSph,mIn.vert[i].P());
1565 }
1566}
1567
1568template <class MeshType>
1579void BuildCylinderVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, float height=0, int slices=16, int stacks=1 )
1580{
1581 typedef typename MeshType::CoordType CoordType;
1582 if(radius==0) radius = mIn.bbox.Diag()/100.0f;
1583 if(height==0) height = mIn.bbox.Diag()/200.0f;
1584 for(size_t i=0;i<mIn.vert.size();++i)
1585 {
1586 CoordType p = mIn.vert[i].P();
1587 CoordType n = mIn.vert[i].N().Normalize();
1588
1589 MeshType mCyl;
1590 tri::OrientedCylinder(mCyl,p-n*height,p+n*height,radius,true,slices,stacks);
1592 }
1593}
1594
1595
1596template <class MeshType>
1602void GenerateCameraMesh(MeshType &in){
1603 typedef typename MeshType::CoordType MV;
1604 MV vv[52]={
1605 MV(-0.000122145 , -0.2 ,0.35),
1606 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),
1607 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),
1608 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),
1609 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),
1610 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),
1611 MV(-0.203079 , -0.1 ,0.471362), };
1612 int ff[88][3]={
1613 {0,2,3},
1614 {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},
1615 {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},
1616 {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},
1617 {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},
1618 {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},
1619 {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},
1620 {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},
1621 {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},
1622 {43,36,44},{51,44,45},{51,45,46},{51,46,47},{51,47,48},{51,49,50},{51,50,44},
1623 };
1624
1625 in.Clear();
1628
1629 in.vn=52;in.fn=88;
1630 int i,j;
1631 for(i=0;i<in.vn;i++)
1632 in.vert[i].P()=vv[i];;
1633
1634 std::vector<typename MeshType::VertexPointer> index(in.vn);
1635
1636 typename MeshType::VertexIterator vi;
1637 for(j=0,vi=in.vert.begin();j<in.vn;++j,++vi) index[j] = &*vi;
1638 for(j=0;j<in.fn;++j)
1639 {
1640 in.face[j].V(0)=index[ff[j][0]];
1641 in.face[j].V(1)=index[ff[j][1]];
1642 in.face[j].V(2)=index[ff[j][2]];
1643 }
1644}
1645
1646template <class MeshType>
1658void 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))
1659{
1660 typedef typename MeshType::ScalarType ScalarType;
1661 typedef typename MeshType::CoordType CoordType;
1662 float zeros[4]={0,0,0,0};
1663 square.Clear();
1664 Matrix44<ScalarType> rotM;
1665 tri::Grid(square,2,2,width,height,zeros);
1666 tri::UpdatePosition<MeshType>::Translate(square,CoordType(-width/2.0f,-height/2.0f,0.0f));
1667 if(angleDeg!=0){
1669 rotM.SetRotateDeg(angleDeg,dir);
1671 }
1674}
1675
1676template <class MeshType>
1687void 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))
1688{
1689 OrientedRect(square,width,width,c,dir,angleDeg,preRotTra);
1690}
1691
1692
1693
1695
1696} // End Namespace TriMesh
1697} // End Namespace vcg
1698#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:1912
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:1268
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:658
void BuildFromFaceEdgeSel(TriMeshType &in, EdgeMeshType &out)
Build an edge mesh from the selected edges of a triangle mesh.
Definition: platonic.h:946
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:1579
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:1658
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:1184
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:894
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:557
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:1344
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:1298
void Torus(MeshType &m, float hRingRadius, float vRingRadius, int hRingDiv=24, int vRingDiv=12)
Build a torus mesh around Z axis.
Definition: platonic.h:755
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:1520
void BuildMeshFromCoordVector(MeshType &in, const V &v)
Build a point-only mesh from coordinate vector (no faces).
Definition: platonic.h:931
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:1207
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:989
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:1555
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:1422
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:1687
void Annulus(MeshType &m, float externalRadius, float internalRadius, int slices)
Build an annulus (ring) in the XY plane.
Definition: platonic.h:1143
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:850
void Sphere(MeshType &in, const int subdiv=3)
Build a geodesic sphere by recursive icosahedron refinement.
Definition: platonic.h:498
void Cylinder(MeshType &m, int slices, int stacks, bool capped=false)
Build a unit cylinder aligned to Y, optionally capped.
Definition: platonic.h:1359
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:808
void SparseFaceGrid(MeshType &in, const std::vector< int > &grid, int w, int h)
Build faces for a sparsely sampled regular grid.
Definition: platonic.h:1069
void GenerateCameraMesh(MeshType &in)
Build a simple camera-shaped mesh (mainly for visualization).
Definition: platonic.h:1602
void Box(MeshType &in, const typename MeshType::BoxType &bb)
Build a box aligned with the axes from a bounding box.
Definition: platonic.h:701
void SphericalCap(MeshType &in, float angleRad, const int subdiv=3)
Build a spherical cap from a hexagon refined on the sphere.
Definition: platonic.h:447
void Disk(MeshType &m, int slices)
Build a unit disk (triangle fan) in the XY plane.
Definition: platonic.h:1231
void FaceGrid(MeshType &in, int w, int h)
Build faces for a regular grid given pre-allocated vertices.
Definition: platonic.h:1020
void Tetrahedron(TetraMeshType &in)
Build a tetrahedron as a triangular mesh.
Definition: platonic.h:54
Definition: color4.h:30
Definition: refine.h:126