00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __VCGLIB_PLATONIC
00025 #define __VCGLIB_PLATONIC
00026
00027 #include<vcg/math/base.h>
00028 #include<vcg/complex/algorithms/refine.h>
00029 #include<vcg/complex/algorithms/update/flag.h>
00030 #include<vcg/complex/algorithms/update/position.h>
00031 #include<vcg/complex/algorithms/update/topology.h>
00032 #include<vcg/complex/algorithms/update/bounding.h>
00033 #include<vcg/complex/algorithms/clean.h>
00034 #include<vcg/complex/algorithms/polygon_support.h>
00035 #include<vcg/complex/algorithms/smooth.h>
00036
00037
00038 namespace vcg {
00039 namespace tri {
00050 template <class TetraMeshType>
00051 void Tetrahedron(TetraMeshType &in)
00052 {
00053 typedef typename TetraMeshType::CoordType CoordType;
00054 typedef typename TetraMeshType::VertexPointer VertexPointer;
00055 typedef typename TetraMeshType::VertexIterator VertexIterator;
00056 typedef typename TetraMeshType::FaceIterator FaceIterator;
00057
00058 in.Clear();
00059 Allocator<TetraMeshType>::AddVertices(in,4);
00060 Allocator<TetraMeshType>::AddFaces(in,4);
00061
00062 VertexPointer ivp[4];
00063 VertexIterator vi=in.vert.begin();
00064 ivp[0]=&*vi;(*vi).P()=CoordType ( 1.0, 1.0, 1.0); ++vi;
00065 ivp[1]=&*vi;(*vi).P()=CoordType (-1.0, 1.0,-1.0); ++vi;
00066 ivp[2]=&*vi;(*vi).P()=CoordType (-1.0,-1.0, 1.0); ++vi;
00067 ivp[3]=&*vi;(*vi).P()=CoordType ( 1.0,-1.0,-1.0);
00068
00069 FaceIterator fi=in.face.begin();
00070 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
00071 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[3]; ++fi;
00072 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[1]; ++fi;
00073 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1];
00074 }
00075
00076
00079 template <class DodMeshType>
00080 void Dodecahedron(DodMeshType & in)
00081 {
00082 typedef DodMeshType MeshType;
00083 typedef typename MeshType::CoordType CoordType;
00084 typedef typename MeshType::VertexPointer VertexPointer;
00085 typedef typename MeshType::VertexIterator VertexIterator;
00086 typedef typename MeshType::FaceIterator FaceIterator;
00087 typedef typename MeshType::ScalarType ScalarType;
00088 const int N_penta=12;
00089 const int N_points=62;
00090
00091 int penta[N_penta*3*3]=
00092 {20,11, 18, 18, 11, 8, 8, 11, 4,
00093 13,23, 4, 4, 23, 8, 8, 23, 16,
00094 13, 4, 30, 30, 4, 28, 28, 4, 11,
00095 16,34, 8, 8, 34, 18, 18, 34, 36,
00096 11,20, 28, 28, 20, 45, 45, 20, 38,
00097 13,30, 23, 23, 30, 41, 41, 30, 47,
00098 16,23, 34, 34, 23, 50, 50, 23, 41,
00099 20,18, 38, 38, 18, 52, 52, 18, 36,
00100 30,28, 47, 47, 28, 56, 56, 28, 45,
00101 50,60, 34, 34, 60, 36, 36, 60, 52,
00102 45,38, 56, 56, 38, 60, 60, 38, 52,
00103 50,41, 60, 60, 41, 56, 56, 41, 47 };
00104
00105 const ScalarType p=(1.0 + math::Sqrt(5.0)) / 2.0;
00106 const ScalarType p2=p*p;
00107 const ScalarType p3=p*p*p;
00108 ScalarType vv[N_points*3]=
00109 {
00110 0, 0, 2*p2, p2, 0, p3, p, p2, p3,
00111 0, p, p3, -p, p2, p3, -p2, 0, p3,
00112 -p, -p2, p3, 0, -p, p3, p, -p2, p3,
00113 p3, p, p2, p2, p2, p2, 0, p3, p2,
00114 -p2, p2, p2, -p3, p, p2, -p3, -p, p2,
00115 -p2, -p2, p2, 0, -p3, p2, p2, -p2, p2,
00116 p3, -p, p2, p3, 0, p, p2, p3, p,
00117 -p2, p3, p, -p3, 0, p, -p2, -p3, p,
00118 p2, -p3, p, 2*p2, 0, 0, p3, p2, 0,
00119 p, p3, 0, 0, 2*p2, 0, -p, p3, 0,
00120 -p3, p2, 0, -2*p2, 0, 0, -p3, -p2, 0,
00121 -p, -p3, 0, 0, -2*p2, 0, p, -p3, 0,
00122 p3, -p2, 0, p3, 0, -p, p2, p3, -p,
00123 -p2, p3, -p, -p3, 0, -p, -p2, -p3, -p,
00124 p2, -p3, -p, p3, p, -p2, p2, p2, -p2,
00125 0, p3, -p2, -p2, p2, -p2, -p3, p, -p2,
00126 -p3, -p, -p2, -p2, -p2, -p2, 0, -p3, -p2,
00127 p2, -p2, -p2, p3, -p, -p2, p2, 0, -p3,
00128 p, p2, -p3, 0, p, -p3, -p, p2, -p3,
00129 -p2, 0, -p3, -p, -p2, -p3, 0, -p, -p3,
00130 p, -p2, -p3, 0, 0, -2*p2
00131 };
00132 in.Clear();
00133
00134 Allocator<DodMeshType>::AddVertices(in,20+12);
00135 Allocator<DodMeshType>::AddFaces(in, 5*12);
00136
00137 int h,i,j,m=0;
00138
00139 bool used[N_points];
00140 for (i=0; i<N_points; i++) used[i]=false;
00141
00142 int reindex[20+12 *10];
00143 ScalarType xx,yy,zz, sx,sy,sz;
00144
00145 int order[5]={0,1,8,6,2};
00146 int added[12];
00147
00148 VertexIterator vi=in.vert.begin();
00149
00150 for (i=0; i<12; i++) {
00151 sx=sy=sz=0;
00152 for (int j=0; j<5; j++) {
00153 h= penta[ i*9 + order[j] ]-1;
00154 xx=vv[h*3];yy=vv[h*3+1];zz=vv[h*3+2]; sx+=xx; sy+=yy; sz+=zz;
00155 if (!used[h]) {
00156 (*vi).P()=CoordType( xx, yy, zz ); vi++;
00157 used[h]=true;
00158 reindex[ h ] = m++;
00159 }
00160 }
00161 (*vi).P()=CoordType( sx/5.0, sy/5.0, sz/5.0 ); vi++;
00162 added[ i ] = m++;
00163 }
00164
00165 std::vector<VertexPointer> index(in.vn);
00166
00167 for(j=0,vi=in.vert.begin();j<in.vn;++j,++vi) index[j] = &(*vi);
00168
00169 FaceIterator fi=in.face.begin();
00170
00171 for (i=0; i<12; i++) {
00172 for (j=0; j<5; j++){
00173 (*fi).V(0)=index[added[i] ];
00174 (*fi).V(1)=index[reindex[penta[i*9 + order[j ] ] -1 ] ];
00175 (*fi).V(2)=index[reindex[penta[i*9 + order[(j+1)%5] ] -1 ] ];
00176 if (HasPerFaceFlags(in)) {
00177
00178 (*fi).SetF(0);
00179 (*fi).SetF(2);
00180 }
00181 fi++;
00182 }
00183 }
00184 }
00185
00186 template <class OctMeshType>
00187 void Octahedron(OctMeshType &in)
00188 {
00189 typedef OctMeshType MeshType;
00190 typedef typename MeshType::CoordType CoordType;
00191 typedef typename MeshType::VertexPointer VertexPointer;
00192 typedef typename MeshType::VertexIterator VertexIterator;
00193 typedef typename MeshType::FaceIterator FaceIterator;
00194
00195 in.Clear();
00196 Allocator<OctMeshType>::AddVertices(in,6);
00197 Allocator<OctMeshType>::AddFaces(in,8);
00198
00199 VertexPointer ivp[6];
00200
00201 VertexIterator vi=in.vert.begin();
00202 ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 0, 0); ++vi;
00203 ivp[1]=&*vi;(*vi).P()=CoordType ( 0, 1, 0); ++vi;
00204 ivp[2]=&*vi;(*vi).P()=CoordType ( 0, 0, 1); ++vi;
00205 ivp[3]=&*vi;(*vi).P()=CoordType (-1, 0, 0); ++vi;
00206 ivp[4]=&*vi;(*vi).P()=CoordType ( 0,-1, 0); ++vi;
00207 ivp[5]=&*vi;(*vi).P()=CoordType ( 0, 0,-1);
00208
00209 FaceIterator fi=in.face.begin();
00210 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
00211 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi;
00212 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[5]; ++fi;
00213 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[1]; ++fi;
00214 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[5]; ++fi;
00215 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[4]; ++fi;
00216 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi;
00217 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1];
00218 }
00219
00220 template <class IcoMeshType>
00221 void Icosahedron(IcoMeshType &in)
00222 {
00223 typedef IcoMeshType MeshType;
00224 typedef typename MeshType::ScalarType ScalarType;
00225 typedef typename MeshType::CoordType CoordType;
00226 typedef typename MeshType::VertexPointer VertexPointer;
00227 typedef typename MeshType::VertexIterator VertexIterator;
00228 typedef typename MeshType::FaceIterator FaceIterator;
00229
00230 ScalarType L=ScalarType((math::Sqrt(5.0)+1.0)/2.0);
00231 CoordType vv[12]={
00232 CoordType ( 0, L, 1),
00233 CoordType ( 0, L,-1),
00234 CoordType ( 0,-L, 1),
00235 CoordType ( 0,-L,-1),
00236
00237 CoordType ( L, 1, 0),
00238 CoordType ( L,-1, 0),
00239 CoordType (-L, 1, 0),
00240 CoordType (-L,-1, 0),
00241
00242 CoordType ( 1, 0, L),
00243 CoordType (-1, 0, L),
00244 CoordType ( 1, 0,-L),
00245 CoordType (-1, 0,-L)
00246 };
00247
00248 int ff[20][3]={
00249 {1,0,4},{0,1,6},{2,3,5},{3,2,7},
00250 {4,5,10},{5,4,8},{6,7,9},{7,6,11},
00251 {8,9,2},{9,8,0},{10,11,1},{11,10,3},
00252 {0,8,4},{0,6,9},{1,4,10},{1,11,6},
00253 {2,5,8},{2,9,7},{3,10,5},{3,7,11}
00254 };
00255
00256
00257 in.Clear();
00258 Allocator<IcoMeshType>::AddVertices(in,12);
00259 Allocator<IcoMeshType>::AddFaces(in,20);
00260 VertexPointer ivp[12];
00261
00262 VertexIterator vi;
00263 int i;
00264 for(i=0,vi=in.vert.begin();vi!=in.vert.end();++i,++vi){
00265 (*vi).P()=vv[i];
00266 ivp[i]=&*vi;
00267 }
00268
00269 FaceIterator fi;
00270 for(i=0,fi=in.face.begin();fi!=in.face.end();++i,++fi){
00271 (*fi).V(0)=ivp[ff[i][0]];
00272 (*fi).V(1)=ivp[ff[i][1]];
00273 (*fi).V(2)=ivp[ff[i][2]];
00274 }
00275 }
00276
00277 template <class MeshType>
00278 void Hexahedron(MeshType &in)
00279 {
00280 typedef typename MeshType::CoordType CoordType;
00281 typedef typename MeshType::VertexPointer VertexPointer;
00282 typedef typename MeshType::VertexIterator VertexIterator;
00283 typedef typename MeshType::FaceIterator FaceIterator;
00284
00285 in.Clear();
00286 Allocator<MeshType>::AddVertices(in,8);
00287 Allocator<MeshType>::AddFaces(in,12);
00288
00289 VertexPointer ivp[8];
00290
00291 VertexIterator vi=in.vert.begin();
00292
00293 ivp[7]=&*vi;(*vi).P()=CoordType (-1,-1,-1); ++vi;
00294 ivp[6]=&*vi;(*vi).P()=CoordType ( 1,-1,-1); ++vi;
00295 ivp[5]=&*vi;(*vi).P()=CoordType (-1, 1,-1); ++vi;
00296 ivp[4]=&*vi;(*vi).P()=CoordType ( 1, 1,-1); ++vi;
00297 ivp[3]=&*vi;(*vi).P()=CoordType (-1,-1, 1); ++vi;
00298 ivp[2]=&*vi;(*vi).P()=CoordType ( 1,-1, 1); ++vi;
00299 ivp[1]=&*vi;(*vi).P()=CoordType (-1, 1, 1); ++vi;
00300 ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 1, 1);
00301
00302 FaceIterator fi=in.face.begin();
00303 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
00304 (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1]; ++fi;
00305 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi;
00306 (*fi).V(0)=ivp[6]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi;
00307 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[1]; ++fi;
00308 (*fi).V(0)=ivp[5]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[4]; ++fi;
00309 (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[6]; ++fi;
00310 (*fi).V(0)=ivp[4]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[5]; ++fi;
00311 (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[3]; ++fi;
00312 (*fi).V(0)=ivp[2]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[6]; ++fi;
00313 (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[5]; ++fi;
00314 (*fi).V(0)=ivp[1]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[3];
00315
00316 if (HasPerFaceFlags(in)) {
00317 FaceIterator fi=in.face.begin();
00318 for (int k=0; k<12; k++) {
00319 (*fi).SetF(1); fi++;
00320 }
00321 }
00322
00323 }
00324
00325 template <class MeshType>
00326 void Square(MeshType &in)
00327 {
00328 typedef typename MeshType::CoordType CoordType;
00329 typedef typename MeshType::VertexPointer VertexPointer;
00330 typedef typename MeshType::VertexIterator VertexIterator;
00331 typedef typename MeshType::FaceIterator FaceIterator;
00332
00333 in.Clear();
00334 Allocator<MeshType>::AddVertices(in,4);
00335 Allocator<MeshType>::AddFaces(in,2);
00336
00337 VertexPointer ivp[4];
00338
00339 VertexIterator vi=in.vert.begin();
00340 ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 0, 0); ++vi;
00341 ivp[1]=&*vi;(*vi).P()=CoordType ( 0, 1, 0); ++vi;
00342 ivp[2]=&*vi;(*vi).P()=CoordType (-1, 0, 0); ++vi;
00343 ivp[3]=&*vi;(*vi).P()=CoordType ( 0,-1, 0);
00344
00345 FaceIterator fi=in.face.begin();
00346 (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi;
00347 (*fi).V(0)=ivp[2]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[0];
00348
00349 if (HasPerFaceFlags(in)) {
00350 FaceIterator fi=in.face.begin();
00351 for (int k=0; k<2; k++) {
00352 (*fi).SetF(2); fi++;
00353 }
00354 }
00355 }
00356
00357 template <class MeshType>
00358 void SphericalCap(MeshType &in, float angleRad, const int subdiv = 3 )
00359 {
00360 typedef typename MeshType::CoordType CoordType;
00361 typedef typename MeshType::VertexIterator VertexIterator;
00362 in.Clear();
00363 tri::Allocator<MeshType>::AddVertex(in,CoordType(0,0,0));
00364 for(int i=0;i<6;++i)
00365 tri::Allocator<MeshType>::AddVertex(in,CoordType(cos(math::ToRad(i*60.0)),sin(math::ToRad(i*60.0)),0));
00366
00367 for(int i=0;i<6;++i)
00368 tri::Allocator<MeshType>::AddFace(in,&(in.vert[0]),&(in.vert[1+i]),&(in.vert[1+(i+1)%6]));
00369
00370 tri::UpdateTopology<MeshType>::FaceFace(in);
00371 for(int i=0;i<subdiv;++i)
00372 {
00373 tri::Refine(in, MidPoint<MeshType>(&in));
00374
00375 tri::UpdateFlags<MeshType>::FaceBorderFromFF(in);
00376 tri::UpdateFlags<MeshType>::VertexBorderFromFaceBorder(in);
00377
00378 for(int i=0;i<in.vn;++i)
00379 if(in.vert[i].IsB())
00380 in.vert[i].P().Normalize();
00381
00382 tri::UpdateSelection<MeshType>::VertexFromBorderFlag(in);
00383 tri::UpdateSelection<MeshType>::VertexInvert(in);
00384 tri::Smooth<MeshType>::VertexCoordLaplacian(in,10,true);
00385 }
00386
00387 float angleHalfRad = angleRad /2.0f;
00388 float width = sin(angleHalfRad);
00389 tri::UpdatePosition<MeshType>::Scale(in,width);
00390 tri::Allocator<MeshType>::CompactEveryVector(in);
00391 for(VertexIterator vi=in.vert.begin(); vi!=in.vert.end();++vi)
00392 {
00393 float cosVi = vi->P().Norm();
00394 float angVi = asin (cosVi);
00395 vi->P()[2] = cos(angVi) - cos(angleHalfRad);
00396 }
00397 }
00398
00399
00400
00401
00402 template <class MeshType>
00403 void Sphere(MeshType &in, const int subdiv = 3 )
00404 {
00405 typedef typename MeshType::CoordType CoordType;
00406 typedef typename MeshType::VertexIterator VertexIterator;
00407 typedef typename MeshType::FaceIterator FaceIterator;
00408 if(in.vn==0 && in.fn==0) Icosahedron(in);
00409
00410 for(VertexIterator vi = in.vert.begin(); vi!=in.vert.end();++vi)
00411 vi->P().Normalize();
00412
00413 for(int i = 0 ; i < subdiv; ++i)
00414 {
00415 MeshType newM;
00416 for(FaceIterator fi=in.face.begin();fi!=in.face.end();++fi)
00417 {
00418 CoordType me01 = (fi->P(0)+fi->P(1))/2.0;
00419 CoordType me12 = (fi->P(1)+fi->P(2))/2.0;
00420 CoordType me20 = (fi->P(2)+fi->P(0))/2.0;
00421 tri::Allocator<MeshType>::AddFace(newM,me01,me12,me20);
00422 tri::Allocator<MeshType>::AddFace(newM,fi->P(0),me01,me20);
00423 tri::Allocator<MeshType>::AddFace(newM,fi->P(1),me12,me01);
00424 tri::Allocator<MeshType>::AddFace(newM,fi->P(2),me20,me12);
00425 }
00426 tri::Clean<MeshType>::RemoveDuplicateVertex(newM);
00427 tri::Append<MeshType,MeshType>::MeshCopy(in,newM);
00428
00429 for(VertexIterator vi = in.vert.begin(); vi != in.vert.end(); ++vi)
00430 vi->P().Normalize();
00431 }
00432 }
00433
00434
00436 template <class MeshType>
00437 void Cone( MeshType& in,
00438 const typename MeshType::ScalarType r1,
00439 const typename MeshType::ScalarType r2,
00440 const typename MeshType::ScalarType h,
00441 const int SubDiv = 36 )
00442 {
00443 typedef typename MeshType::CoordType CoordType;
00444 typedef typename MeshType::VertexPointer VertexPointer;
00445 typedef typename MeshType::VertexIterator VertexIterator;
00446 typedef typename MeshType::FaceIterator FaceIterator;
00447
00448 int i,b1,b2;
00449 in.Clear();
00450 int VN,FN;
00451 if(r1==0 || r2==0) {
00452 VN=SubDiv+2;
00453 FN=SubDiv*2;
00454 } else {
00455 VN=SubDiv*2+2;
00456 FN=SubDiv*4;
00457 }
00458
00459 Allocator<MeshType>::AddVertices(in,VN);
00460 Allocator<MeshType>::AddFaces(in,FN);
00461 VertexPointer *ivp = new VertexPointer[VN];
00462
00463 VertexIterator vi=in.vert.begin();
00464 ivp[0]=&*vi;(*vi).P()=CoordType ( 0,-h/2.0,0 ); ++vi;
00465 ivp[1]=&*vi;(*vi).P()=CoordType ( 0, h/2.0,0 ); ++vi;
00466
00467 b1 = b2 = 2;
00468 int cnt=2;
00469 if(r1!=0)
00470 {
00471 for(i=0;i<SubDiv;++i)
00472 {
00473 double a = math::ToRad(i*360.0/SubDiv);
00474 ivp[cnt]=&*vi; (*vi).P()= CoordType(r1*cos(a), -h/2.0, r1*sin(a)); ++vi;++cnt;
00475 }
00476 b2 += SubDiv;
00477 }
00478
00479 if(r2!=0)
00480 {
00481 for(i=0;i<SubDiv;++i)
00482 {
00483 double a = math::ToRad(i*360.0/SubDiv);
00484 ivp[cnt]=&*vi; (*vi).P()= CoordType( r2*cos(a), h/2.0, r2*sin(a)); ++vi;++cnt;
00485 }
00486 }
00487
00488 FaceIterator fi=in.face.begin();
00489
00490 if(r1!=0) for(i=0;i<SubDiv;++i,++fi) {
00491 (*fi).V(0)=ivp[0];
00492 (*fi).V(1)=ivp[b1+i];
00493 (*fi).V(2)=ivp[b1+(i+1)%SubDiv];
00494 }
00495
00496 if(r2!=0) for(i=0;i<SubDiv;++i,++fi) {
00497 (*fi).V(0)=ivp[1];
00498 (*fi).V(2)=ivp[b2+i];
00499 (*fi).V(1)=ivp[b2+(i+1)%SubDiv];
00500 }
00501
00502 if(r1==0) for(i=0;i<SubDiv;++i,++fi)
00503 {
00504 (*fi).V(0)=ivp[0];
00505 (*fi).V(1)=ivp[b2+i];
00506 (*fi).V(2)=ivp[b2+(i+1)%SubDiv];
00507 }
00508 if(r2==0) for(i=0;i<SubDiv;++i,++fi){
00509 (*fi).V(0)=ivp[1];
00510 (*fi).V(2)=ivp[b1+i];
00511 (*fi).V(1)=ivp[b1+(i+1)%SubDiv];
00512 }
00513
00514 if(r1!=0 && r2!=0)for(i=0;i<SubDiv;++i)
00515 {
00516 (*fi).V(0)=ivp[b1+i];
00517 (*fi).V(1)=ivp[b2+i];
00518 (*fi).V(2)=ivp[b2+(i+1)%SubDiv];
00519 ++fi;
00520 (*fi).V(0)=ivp[b1+i];
00521 (*fi).V(1)=ivp[b2+(i+1)%SubDiv];
00522 (*fi).V(2)=ivp[b1+(i+1)%SubDiv];
00523 ++fi;
00524 }
00525 }
00526
00527
00528 template <class MeshType >
00529 void Box(MeshType &in, const typename MeshType::BoxType & bb )
00530 {
00531 typedef typename MeshType::CoordType CoordType;
00532 typedef typename MeshType::VertexPointer VertexPointer;
00533 typedef typename MeshType::VertexIterator VertexIterator;
00534 typedef typename MeshType::FaceIterator FaceIterator;
00535
00536 in.Clear();
00537 Allocator<MeshType>::AddVertices(in,8);
00538 VertexPointer ivp[8];
00539
00540 VertexIterator vi=in.vert.begin();
00541 ivp[0]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.min[2]); ++vi;
00542 ivp[1]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.min[2]); ++vi;
00543 ivp[2]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.min[2]); ++vi;
00544 ivp[3]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.min[2]); ++vi;
00545 ivp[4]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.max[2]); ++vi;
00546 ivp[5]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.max[2]); ++vi;
00547 ivp[6]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.max[2]); ++vi;
00548 ivp[7]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.max[2]);
00549
00550 Allocator<MeshType>::AddFace(in,ivp[2],ivp[1],ivp[0]);
00551 Allocator<MeshType>::AddFace(in,ivp[1],ivp[2],ivp[3]);
00552 Allocator<MeshType>::AddFace(in,ivp[4],ivp[2],ivp[0]);
00553 Allocator<MeshType>::AddFace(in,ivp[2],ivp[4],ivp[6]);
00554 Allocator<MeshType>::AddFace(in,ivp[1],ivp[4],ivp[0]);
00555 Allocator<MeshType>::AddFace(in,ivp[4],ivp[1],ivp[5]);
00556 Allocator<MeshType>::AddFace(in,ivp[6],ivp[5],ivp[7]);
00557 Allocator<MeshType>::AddFace(in,ivp[5],ivp[6],ivp[4]);
00558 Allocator<MeshType>::AddFace(in,ivp[3],ivp[6],ivp[7]);
00559 Allocator<MeshType>::AddFace(in,ivp[6],ivp[3],ivp[2]);
00560 Allocator<MeshType>::AddFace(in,ivp[5],ivp[3],ivp[7]);
00561 Allocator<MeshType>::AddFace(in,ivp[3],ivp[5],ivp[1]);
00562
00563 if (HasPerFaceFlags(in)) {
00564 FaceIterator fi=in.face.begin();
00565 for (int k=0; k<12; k++) {
00566 (*fi).SetF(0); fi++;
00567 }
00568 }
00569
00570 }
00571
00572
00573 template <class MeshType>
00574 void Torus(MeshType &m, float hRingRadius, float vRingRadius, int hRingDiv=24, int vRingDiv=12 )
00575 {
00576 typedef typename MeshType::CoordType CoordType;
00577 typedef typename MeshType::ScalarType ScalarType;
00578 typedef Matrix44<ScalarType> Matrix44x;
00579 m.Clear();
00580 ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
00581 ScalarType angleStepH = (2.0f*M_PI)/hRingDiv;
00582
00583 Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
00584 for(int i=0;i<hRingDiv+1;++i)
00585 {
00586 Matrix44x RotM; RotM.SetRotateRad(float(i%hRingDiv)*angleStepH,CoordType(0,0,1));
00587 for(int j=0;j<vRingDiv+1;++j)
00588 {
00589 CoordType p;
00590 p[0]= vRingRadius*cos(float(j%vRingDiv)*angleStepV) + hRingRadius;
00591 p[1] = 0;
00592 p[2]= vRingRadius*sin(float(j%vRingDiv)*angleStepV);
00593
00594 m.vert[i*(vRingDiv+1)+j].P() = RotM*p;
00595 }
00596 }
00597 FaceGrid(m,vRingDiv+1,hRingDiv+1);
00598 tri::Clean<MeshType>::RemoveDuplicateVertex(m);
00599 tri::Allocator<MeshType>::CompactEveryVector(m);
00600
00601 }
00602
00605 template <class ScalarType>
00606 static ScalarType _SQfnC(ScalarType a, ScalarType b){
00607 return math::Sgn(cos(a))*pow(fabs(cos(a)),b);
00608 };
00609 template <class ScalarType>
00610 static ScalarType _SQfnS(ScalarType a, ScalarType b){
00611 return math::Sgn(sin(a))*pow(fabs(sin(a)),b);
00612 };
00613
00614
00622 template <class MeshType>
00623 void SuperToroid(MeshType &m, float hRingRadius, float vRingRadius, float vSquareness, float hSquareness, int hRingDiv=24, int vRingDiv=12 )
00624 {
00625 typedef typename MeshType::CoordType CoordType;
00626 typedef typename MeshType::ScalarType ScalarType;
00627 m.Clear();
00628 ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
00629 ScalarType angleStepH = (2.0f*M_PI)/hRingDiv;
00630
00631 ScalarType u,v;
00632 int count;
00633 Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
00634 for(int i=0;i<hRingDiv+1;++i)
00635 {
00636 u=float(i%hRingDiv)*angleStepH;
00637 count=0;
00638 for(int j=vRingDiv;j>=0;--j)
00639 {
00640 CoordType p;
00641 v=float(j%vRingDiv)*angleStepV;
00642 p[0]= (hRingRadius+vRingRadius*_SQfnC(u,vSquareness))*_SQfnC(v,hSquareness);;
00643 p[1]= (hRingRadius+vRingRadius*_SQfnC(u,vSquareness))*_SQfnS(v,hSquareness);
00644 p[2] = vRingRadius*_SQfnS(u,vSquareness);
00645 m.vert[i*(vRingDiv+1)+count].P() = p;
00646 count++;
00647 }
00648 }
00649 FaceGrid(m,vRingDiv+1,hRingDiv+1);
00650 tri::Clean<MeshType>::RemoveDuplicateVertex(m);
00651 tri::Allocator<MeshType>::CompactEveryVector(m);
00652
00653 }
00659 template <class MeshType>
00660 void SuperEllipsoid(MeshType &m, float rFeature, float sFeature, float tFeature, int hRingDiv=24, int vRingDiv=12 )
00661 {
00662 typedef typename MeshType::CoordType CoordType;
00663 typedef typename MeshType::ScalarType ScalarType;
00664 m.Clear();
00665 ScalarType angleStepV = (2.0f*M_PI)/vRingDiv;
00666 ScalarType angleStepH = (1.0f*M_PI)/hRingDiv;
00667 float u;
00668 float v;
00669 Allocator<MeshType>::AddVertices(m,(vRingDiv+1)*(hRingDiv+1));
00670 for(int i=0;i<hRingDiv+1;++i)
00671 {
00672
00673 u=i*angleStepH;
00674 for(int j=0;j<vRingDiv+1;++j)
00675 {
00676 CoordType p;
00677 v=ScalarType(j%vRingDiv)*angleStepV;
00678 p[0] = _SQfnC(v,2/rFeature)*_SQfnC(u,2/rFeature);
00679 p[1] = _SQfnC(v,2/sFeature)*_SQfnS(u,2/sFeature);
00680 p[2] = _SQfnS(v,2/tFeature);
00681 m.vert[i*(vRingDiv+1)+j].P() = p;
00682 }
00683 }
00684 FaceGrid(m,vRingDiv+1,hRingDiv+1);
00685 tri::Clean<MeshType>::MergeCloseVertex(m,ScalarType(angleStepV*angleStepV*0.001));
00686 tri::Allocator<MeshType>::CompactEveryVector(m);
00687 bool oriented, orientable;
00688 tri::UpdateTopology<MeshType>::FaceFace(m);
00689 tri::Clean<MeshType>::OrientCoherentlyMesh(m,oriented,orientable);
00690 tri::UpdateSelection<MeshType>::Clear(m);
00691 }
00692
00693
00694 template <class MeshType,class V, class F >
00695 void BuildMeshFromCoordVectorIndexVector( MeshType & in, const V & v, const F & f)
00696 {
00697 typedef typename MeshType::CoordType CoordType;
00698 typedef typename MeshType::VertexPointer VertexPointer;
00699 typedef typename MeshType::VertexIterator VertexIterator;
00700
00701 in.Clear();
00702 Allocator<MeshType>::AddVertices(in,v.size());
00703 Allocator<MeshType>::AddFaces(in,f.size());
00704
00705 for(size_t i=0;i<v.size();++i)
00706 {
00707 float *vv=(float *)(&v[i]);
00708 in.vert[i].P() = CoordType( vv[0],vv[1],vv[2]);
00709 }
00710
00711 std::vector<VertexPointer> index(in.vn);
00712 VertexIterator j;
00713 int k;
00714 for(k=0,j=in.vert.begin();j!=in.vert.end();++j,++k)
00715 index[k] = &*j;
00716
00717 for(size_t i=0;i<f.size();++i)
00718 {
00719 int * ff=(int *)(&f[i]);
00720 assert( ff[0]>=0 );
00721 assert( ff[1]>=0 );
00722 assert( ff[2]>=0 );
00723 assert( ff[0]<in.vn );
00724 assert( ff[1]<in.vn );
00725 assert( ff[2]<in.vn );
00726 in.face[i].V(0) = &in.vert[ ff[0] ];
00727 in.face[i].V(1) = &in.vert[ ff[0] ];
00728 in.face[i].V(2) = &in.vert[ ff[0] ];
00729 }
00730
00731 tri::UpdateBounding<MeshType>::Box(in);
00732 }
00733
00734
00735 template <class MeshType,class V>
00736 void BuildMeshFromCoordVector( MeshType & in, const V & v)
00737 {
00738 std::vector<Point3i> dummyfaceVec;
00739 BuildMeshFromCoordVectorIndexVector(in,v,dummyfaceVec);
00740 }
00741
00742
00743 template <class TriMeshType,class EdgeMeshType >
00744 void BuildFromNonFaux(TriMeshType &in, EdgeMeshType &out)
00745 {
00746 tri::RequireCompactness(in);
00747 std::vector<typename tri::UpdateTopology<TriMeshType>::PEdge> edgevec;
00748 tri::UpdateTopology<TriMeshType>::FillUniqueEdgeVector(in, edgevec, false);
00749 out.Clear();
00750 for(size_t i=0;i<in.vert.size();++i)
00751 tri::Allocator<EdgeMeshType>::AddVertex(out, in.vert[i].P());
00752 tri::UpdateFlags<EdgeMeshType>::VertexClearV(out);
00753
00754 for(size_t i=0;i<edgevec.size();++i)
00755 {
00756 int i0 = tri::Index(in,edgevec[i].v[0]);
00757 int i1 = tri::Index(in,edgevec[i].v[1]);
00758 out.vert[i0].SetV();
00759 out.vert[i1].SetV();
00760 tri::Allocator<EdgeMeshType>::AddEdge(out,&out.vert[i0],&out.vert[i1]);
00761 if(in.vert[i0].IsS()) out.vert[i0].SetS();
00762 if(in.vert[i1].IsS()) out.vert[i1].SetS();
00763 }
00764
00765 for(size_t i=0;i<out.vert.size();++i)
00766 if(!out.vert[i].IsV()) tri::Allocator<EdgeMeshType>::DeleteVertex(out,out.vert[i]);
00767
00768 tri::Allocator<EdgeMeshType>::CompactEveryVector(out);
00769 }
00770
00771
00772
00773
00774
00775
00776 template <class MeshType>
00777 void Grid(MeshType & in, int w, int h, float wl, float hl, float *data=0)
00778 {
00779 typedef typename MeshType::CoordType CoordType;
00780
00781 in.Clear();
00782 Allocator<MeshType>::AddVertices(in,w*h);
00783
00784 float wld=wl/float(w-1);
00785 float hld=hl/float(h-1);
00786 float zVal=0;
00787 for(int i=0;i<h;++i)
00788 for(int j=0;j<w;++j)
00789 {
00790 if(data) zVal=data[i*w+j];
00791 in.vert[i*w+j].P()=CoordType ( j*wld, i*hld, zVal) ;
00792 }
00793 FaceGrid(in,w,h);
00794 }
00795
00796
00797
00798
00799
00800 template <class MeshType>
00801 void FaceGrid(MeshType & in, int w, int h)
00802 {
00803 assert(in.vn == (int)in.vert.size());
00804 assert(in.vn >= w*h);
00805
00806 Allocator<MeshType>::AddFaces(in,(w-1)*(h-1)*2);
00807
00808
00809
00810
00811
00812
00813
00814
00815 for(int i=0;i<h-1;++i)
00816 for(int j=0;j<w-1;++j)
00817 {
00818 in.face[2*(i*(w-1)+j)+0].V(0) = &(in.vert[(i+1)*w+j+1]);
00819 in.face[2*(i*(w-1)+j)+0].V(1) = &(in.vert[(i+0)*w+j+1]);
00820 in.face[2*(i*(w-1)+j)+0].V(2) = &(in.vert[(i+0)*w+j+0]);
00821
00822 in.face[2*(i*(w-1)+j)+1].V(0) = &(in.vert[(i+0)*w+j+0]);
00823 in.face[2*(i*(w-1)+j)+1].V(1) = &(in.vert[(i+1)*w+j+0]);
00824 in.face[2*(i*(w-1)+j)+1].V(2) = &(in.vert[(i+1)*w+j+1]);
00825 }
00826
00827 if (HasPerFaceFlags(in)) {
00828 for (int k=0; k<(h-1)*(w-1)*2; k++) {
00829 in.face[k].SetF(2);
00830 }
00831 }
00832
00833 }
00834
00835
00836
00837
00838
00839
00840 template <class MeshType>
00841 void FaceGrid(MeshType & in, const std::vector<int> &grid, int w, int h)
00842 {
00843 tri::RequireCompactness(in);
00844 assert(in.vn <= w*h);
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856 for(int i=0;i<h-1;++i)
00857 for(int j=0;j<w-1;++j)
00858 {
00859 int V0i= grid[(i+0)*w+j+0];
00860 int V1i= grid[(i+0)*w+j+1];
00861 int V2i= grid[(i+1)*w+j+0];
00862 int V3i= grid[(i+1)*w+j+1];
00863
00864 int ndone=0;
00865 bool quad = (V0i>=0 && V1i>=0 && V2i>=0 && V3i>=0 ) && tri::HasPerFaceFlags(in);
00866
00867 if(V0i>=0 && V2i>=0 && V3i>=0 )
00868 {
00869 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
00870 f->V(0)=&(in.vert[V3i]);
00871 f->V(1)=&(in.vert[V2i]);
00872 f->V(2)=&(in.vert[V0i]);
00873 if (quad) f->SetF(2);
00874 ndone++;
00875 }
00876 if(V0i>=0 && V1i>=0 && V3i>=0 )
00877 {
00878 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
00879 f->V(0)=&(in.vert[V0i]);
00880 f->V(1)=&(in.vert[V1i]);
00881 f->V(2)=&(in.vert[V3i]);
00882 if (quad) f->SetF(2);
00883 ndone++;
00884 }
00885
00886 if (ndone==0) {
00887 if(V2i>=0 && V0i>=0 && V1i>=0 )
00888 {
00889 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
00890 f->V(0)=&(in.vert[V2i]);
00891 f->V(1)=&(in.vert[V0i]);
00892 f->V(2)=&(in.vert[V1i]);
00893 ndone++;
00894 }
00895 if(V1i>=0 && V3i>=0 && V2i>=0 )
00896 {
00897 typename MeshType::FaceIterator f= Allocator<MeshType>::AddFaces(in,1);
00898 f->V(0)=&(in.vert[V1i]);
00899 f->V(1)=&(in.vert[V3i]);
00900 f->V(2)=&(in.vert[V2i]);
00901 ndone++;
00902 }
00903 }
00904 }
00905 }
00906 template <class MeshType>
00907 void Annulus(MeshType & m, float externalRadius, float internalRadius, int slices)
00908 {
00909 m.Clear();
00910 typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices*2);
00911
00912 for ( int j = 0; j < slices; ++j)
00913 {
00914 float x = cos( 2.0 * M_PI / slices * j);
00915 float y = sin( 2.0 * M_PI / slices * j);
00916
00917 (*vi).P() = typename MeshType::CoordType(x,y,0)*internalRadius;
00918 ++vi;
00919 (*vi).P() = typename MeshType::CoordType(x,y,0)*externalRadius;
00920 ++vi;
00921 }
00922 typename MeshType::FaceIterator fi ;
00923 for ( int j = 0; j < slices; ++j)
00924 {
00925 fi = vcg::tri::Allocator<MeshType>::AddFaces(m,1);
00926 (*fi).V(0) = &m.vert[ ((j+0)*2+0)%(slices*2) ];
00927 (*fi).V(1) = &m.vert[ ((j+1)*2+1)%(slices*2) ];
00928 (*fi).V(2) = &m.vert[ ((j+0)*2+1)%(slices*2) ];
00929
00930 fi = vcg::tri::Allocator<MeshType>::AddFaces(m,1);
00931 (*fi).V(0) = &m.vert[ ((j+1)*2+0)%(slices*2) ];
00932 (*fi).V(1) = &m.vert[ ((j+1)*2+1)%(slices*2) ];
00933 (*fi).V(2) = &m.vert[ ((j+0)*2+0)%(slices*2) ];
00934 }
00935 }
00936
00937 template <class MeshType>
00938 void OrientedAnnulus(MeshType & m, Point3f center, Point3f norm, float externalRadius, float internalRadius, int slices)
00939 {
00940 Annulus(m,externalRadius,internalRadius, slices);
00941 float angleRad = Angle(Point3f(0,0,1),norm);
00942 Point3f axis = Point3f(0,0,1)^norm;
00943
00944 Matrix44f rotM;
00945 rotM.SetRotateRad(angleRad,axis);
00946 tri::UpdatePosition<MeshType>::Matrix(m,rotM);
00947 tri::UpdatePosition<MeshType>::Translate(m,center);
00948 }
00949
00950
00951 template <class MeshType>
00952 void Disk(MeshType & m, int slices)
00953 {
00954 m.Clear();
00955 typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices+1);
00956 (*vi).P() = typename MeshType::CoordType(0,0,0);
00957 ++vi;
00958
00959 for ( int j = 0; j < slices; ++j)
00960 {
00961 float x = cos( 2.0 * M_PI / slices * j);
00962 float y = sin( 2.0 * M_PI / slices * j);
00963
00964 (*vi).P() = typename MeshType::CoordType(x,y,0);
00965 ++vi;
00966 }
00967 typename MeshType::FaceIterator fi ;
00968 for ( int j = 0; j < slices; ++j)
00969 {
00970 int a = 1+(j+0)%slices;
00971 int b = 1+(j+1)%slices;
00972 fi = vcg::tri::Allocator<MeshType>::AddFaces(m,1);
00973 (*fi).V(0) = &m.vert[ 0 ];
00974 (*fi).V(1) = &m.vert[ a ];
00975 (*fi).V(2) = &m.vert[ b ];
00976 }
00977 }
00978
00979 template <class MeshType>
00980 void OrientedDisk(MeshType &m, int slices, typename MeshType::CoordType center, typename MeshType::CoordType norm, float radius)
00981 {
00982 typedef typename MeshType::ScalarType ScalarType;
00983 typedef typename MeshType::CoordType CoordType;
00984
00985 Disk(m,slices);
00986 tri::UpdatePosition<MeshType>::Scale(m,radius);
00987 ScalarType angleRad = Angle(CoordType(0,0,1),norm);
00988 CoordType axis = CoordType(0,0,1)^norm;
00989
00990 Matrix44<ScalarType> rotM;
00991 rotM.SetRotateRad(angleRad,axis);
00992 tri::UpdatePosition<MeshType>::Matrix(m,rotM);
00993 tri::UpdatePosition<MeshType>::Translate(m,center);
00994 }
00995
00996 template <class MeshType>
00997 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 )
00998 {
00999 typedef typename MeshType::ScalarType ScalarType;
01000 typedef typename MeshType::CoordType CoordType;
01001 typedef Matrix44<typename MeshType::ScalarType> Matrix44x;
01002 Cylinder(slices,stacks,m,capped);
01003 tri::UpdatePosition<MeshType>::Translate(m,CoordType(0,1,0));
01004 tri::UpdatePosition<MeshType>::Scale(m,CoordType(1,0.5f,1));
01005 tri::UpdatePosition<MeshType>::Scale(m,CoordType(xScale,1.0f,yScale));
01006
01007 float height = Distance(origin,end);
01008 tri::UpdatePosition<MeshType>::Scale(m,CoordType(radius,height,radius));
01009 CoordType norm = end-origin;
01010 ScalarType angleRad = Angle(CoordType(0,1,0),norm);
01011 CoordType axis = CoordType(0,1,0)^norm;
01012 Matrix44x rotM;
01013 rotM.SetRotateRad(angleRad,axis);
01014 tri::UpdatePosition<MeshType>::Matrix(m,rotM);
01015 tri::UpdatePosition<MeshType>::Translate(m,origin);
01016
01017 }
01018
01019 template <class MeshType>
01020 void OrientedCylinder(MeshType & m, const typename MeshType::CoordType origin, const typename MeshType::CoordType end, float radius, bool capped, int slices=32, int stacks=4 )
01021 {
01022 OrientedEllipticPrism(m,origin,end,radius,1.0f,1.0f,capped,slices,stacks);
01023 }
01024
01025
01026 template <class MeshType>
01027 void Cylinder(int slices, int stacks, MeshType & m, bool capped=false)
01028 {
01029 m.Clear();
01030 typename MeshType::VertexIterator vi = vcg::tri::Allocator<MeshType>::AddVertices(m,slices*(stacks+1));
01031 for ( int i = 0; i < stacks+1; ++i)
01032 for ( int j = 0; j < slices; ++j)
01033 {
01034 float x,y,h;
01035 x = cos( 2.0 * M_PI / slices * j);
01036 y = sin( 2.0 * M_PI / slices * j);
01037 h = 2 * i / (float)(stacks) - 1;
01038
01039 (*vi).P() = typename MeshType::CoordType(x,h,y);
01040 ++vi;
01041 }
01042
01043 for ( int j = 0; j < stacks; ++j)
01044 for ( int i = 0; i < slices; ++i)
01045 {
01046 int a,b,c,d;
01047 a = (j+0)*slices + i;
01048 b = (j+1)*slices + i;
01049 c = (j+1)*slices + (i+1)%slices;
01050 d = (j+0)*slices + (i+1)%slices;
01051 if(((i+j)%2) == 0){
01052 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ a ], &m.vert[ b ], &m.vert[ c ]);
01053 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ c ], &m.vert[ d ], &m.vert[ a ]);
01054 }
01055 else{
01056 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ b ], &m.vert[ c ], &m.vert[ d ]);
01057 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ d ], &m.vert[ a ], &m.vert[ b ]);
01058 }
01059 }
01060
01061 if(capped)
01062 {
01063 tri::Allocator<MeshType>::AddVertex(m,typename MeshType::CoordType(0,-1,0));
01064 tri::Allocator<MeshType>::AddVertex(m,typename MeshType::CoordType(0, 1,0));
01065 int base = 0;
01066 for ( int i = 0; i < slices; ++i)
01067 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ m.vn-2 ], &m.vert[ base+i ], &m.vert[ base+(i+1)%slices ]);
01068 base = (stacks)*slices;
01069 for ( int i = 0; i < slices; ++i)
01070 vcg::tri::Allocator<MeshType>::AddFace(m, &m.vert[ m.vn-1 ], &m.vert[ base+(i+1)%slices ], &m.vert[ base+i ]);
01071 }
01072 if (HasPerFaceFlags(m)) {
01073 for (typename MeshType::FaceIterator fi=m.face.begin(); fi!=m.face.end(); fi++) {
01074 (*fi).SetF(2);
01075 }
01076 }
01077 }
01078
01079
01080
01081 class _SphFace;
01082 class _SphVertex;
01083 struct _SphUsedTypes : public UsedTypes< Use<_SphVertex> ::AsVertexType,
01084 Use<_SphFace> ::AsFaceType>{};
01085
01086 class _SphVertex : public Vertex<_SphUsedTypes, vertex::Coord3f, vertex::Normal3f, vertex::BitFlags >{};
01087 class _SphFace : public Face< _SphUsedTypes, face::VertexRef, face::Normal3f, face::BitFlags, face::FFAdj > {};
01088 class _SphMesh : public tri::TriMesh< vector<_SphVertex>, vector<_SphFace> > {};
01089
01090
01091 template <class MeshType>
01092 void BuildPrismFaceShell(MeshType &mIn, MeshType &mOut, float height=0, float inset=0, bool smoothFlag=true )
01093 {
01094 typedef typename MeshType::VertexPointer VertexPointer;
01095 typedef typename MeshType::FacePointer FacePointer;
01096 typedef typename MeshType::CoordType CoordType;
01097 if(height==0) height = mIn.bbox.Diag()/100.0f;
01098 if(inset==0) inset = mIn.bbox.Diag()/200.0f;
01099 tri::UpdateTopology<MeshType>::FaceFace(mIn);
01100 tri::UpdateFlags<MeshType>::FaceClearV(mIn);
01101 for(size_t i=0;i<mIn.face.size();++i) if(!mIn.face[i].IsV())
01102 {
01103 MeshType faceM;
01104 std::vector<VertexPointer> vertVec;
01105 std::vector<FacePointer> faceVec;
01106 tri::PolygonSupport<MeshType,MeshType>::ExtractPolygon(&(mIn.face[i]),vertVec,faceVec);
01107 size_t vn = vertVec.size();
01108
01109 CoordType nf(0,0,0);
01110 for(size_t j=0;j<faceVec.size();++j)
01111 nf+=faceVec[j]->N().Normalize() * DoubleArea(*faceVec[j]);
01112 nf.Normalize();
01113 nf = nf*height/2.0f;
01114
01115 CoordType bary(0,0,0);
01116 for(size_t j=0;j<faceVec.size();++j)
01117 bary+= Barycenter(*faceVec[j]);
01118 bary/=float(faceVec.size());
01119
01120
01121 tri::Allocator<MeshType>::AddVertex(faceM, bary-nf);
01122 tri::Allocator<MeshType>::AddVertex(faceM, bary+nf);
01123 for(size_t j=0;j<vn;++j){
01124 CoordType delta = (vertVec[j]->P() - bary);
01125 delta.Normalize();
01126 delta = delta*inset;
01127 tri::Allocator<MeshType>::AddVertex(faceM, vertVec[j]->P()-delta-nf);
01128 tri::Allocator<MeshType>::AddVertex(faceM, vertVec[j]->P()-delta+nf);
01129 }
01130
01131
01132 for(size_t j=0;j<vn;++j)
01133 tri::Allocator<MeshType>::AddFace(faceM, 0, 2+(j+0)*2, 2+((j+1)%vn)*2 );
01134 for(size_t j=0;j<vn;++j)
01135 tri::Allocator<MeshType>::AddFace(faceM, 1, 3+((j+1)%vn)*2, 3+(j+0)*2 );
01136
01137
01138 for(size_t j=0;j<vn;++j){
01139 size_t j0=j;
01140 size_t j1=(j+1)%vn;
01141 tri::Allocator<MeshType>::AddFace(faceM, 2+ j0*2 + 0 , 2+ j0*2+1, 2+j1*2+0);
01142 tri::Allocator<MeshType>::AddFace(faceM, 2+ j0*2 + 1 , 2+ j1*2+1, 2+j1*2+0);
01143 }
01144
01145 for(size_t j=0;j<2*vn;++j)
01146 faceM.face[j].SetS();
01147
01148 if(smoothFlag)
01149 {
01150 faceM.face.EnableFFAdjacency();
01151 tri::UpdateTopology<MeshType>::FaceFace(faceM);
01152 tri::UpdateFlags<MeshType>::FaceBorderFromFF(faceM);
01153 tri::Refine(faceM, MidPoint<MeshType>(&faceM),0,true);
01154 tri::Refine(faceM, MidPoint<MeshType>(&faceM),0,true);
01155 tri::UpdateSelection<MeshType>::VertexFromFaceStrict(faceM);
01156 tri::Smooth<MeshType>::VertexCoordLaplacian(faceM,2,true,true);
01157 }
01158
01159 tri::Append<MeshType,MeshType>::Mesh(mOut,faceM);
01160
01161 }
01162 }
01163
01164
01165 template <class MeshType>
01166 void BuildCylinderEdgeShell(MeshType &mIn, MeshType &mOut, float radius=0, int slices=16, int stacks=1 )
01167 {
01168 if(radius==0) radius = mIn.bbox.Diag()/100.0f;
01169 typedef typename tri::UpdateTopology<MeshType>::PEdge PEdge;
01170 std::vector<PEdge> edgeVec;
01171 tri::UpdateTopology<MeshType>::FillUniqueEdgeVector(mIn,edgeVec,false);
01172 for(size_t i=0;i<edgeVec.size();++i)
01173 {
01174 MeshType mCyl;
01175 tri::OrientedCylinder(mCyl,edgeVec[i].v[0]->P(),edgeVec[i].v[1]->P(),radius,true,slices,stacks);
01176 tri::Append<MeshType,MeshType>::Mesh(mOut,mCyl);
01177 }
01178 }
01179
01180 template <class MeshType>
01181 void BuildSphereVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, int recDiv=2 )
01182 {
01183 if(radius==0) radius = mIn.bbox.Diag()/100.0f;
01184 for(size_t i=0;i<mIn.vert.size();++i)
01185 {
01186 MeshType mSph;
01187 tri::Sphere(mSph,recDiv);
01188 tri::UpdatePosition<MeshType>::Scale(mSph,radius);
01189 tri::UpdatePosition<MeshType>::Translate(mSph,mIn.vert[i].P());
01190 tri::Append<MeshType,MeshType>::Mesh(mOut,mSph);
01191 }
01192 }
01193
01194 template <class MeshType>
01195 void BuildCylinderVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, float height=0, int slices=16, int stacks=1 )
01196 {
01197 typedef typename MeshType::CoordType CoordType;
01198 if(radius==0) radius = mIn.bbox.Diag()/100.0f;
01199 if(height==0) height = mIn.bbox.Diag()/200.0f;
01200 for(size_t i=0;i<mIn.vert.size();++i)
01201 {
01202 CoordType p = mIn.vert[i].P();
01203 CoordType n = mIn.vert[i].N().Normalize();
01204
01205 MeshType mCyl;
01206 tri::OrientedCylinder(mCyl,p-n*height,p+n*height,radius,true,slices,stacks);
01207 tri::Append<MeshType,MeshType>::Mesh(mOut,mCyl);
01208 }
01209 }
01210
01211
01212 template <class MeshType>
01213 void GenerateCameraMesh(MeshType &in){
01214 typedef typename MeshType::CoordType MV;
01215 MV vv[52]={
01216 MV(-0.000122145 , -0.2 ,0.35),
01217 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),
01218 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),
01219 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),
01220 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),
01221 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),
01222 MV(-0.203079 , -0.1 ,0.471362), };
01223 int ff[88][3]={
01224 {0,2,3},
01225 {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},
01226 {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},
01227 {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},
01228 {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},
01229 {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},
01230 {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},
01231 {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},
01232 {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},
01233 {43,36,44},{51,44,45},{51,45,46},{51,46,47},{51,47,48},{51,49,50},{51,50,44},
01234 };
01235
01236 in.Clear();
01237 Allocator<MeshType>::AddVertices(in,52);
01238 Allocator<MeshType>::AddFaces(in,88);
01239
01240 in.vn=52;in.fn=88;
01241 int i,j;
01242 for(i=0;i<in.vn;i++)
01243 in.vert[i].P()=vv[i];;
01244
01245 std::vector<typename MeshType::VertexPointer> index(in.vn);
01246
01247 typename MeshType::VertexIterator vi;
01248 for(j=0,vi=in.vert.begin();j<in.vn;++j,++vi) index[j] = &*vi;
01249 for(j=0;j<in.fn;++j)
01250 {
01251 in.face[j].V(0)=index[ff[j][0]];
01252 in.face[j].V(1)=index[ff[j][1]];
01253 in.face[j].V(2)=index[ff[j][2]];
01254 }
01255 }
01256
01257 template <class MeshType>
01258 void OrientedRect(MeshType &square, float width, float height, Point3f c, Point3f dir=Point3f(0,0,0), float angleDeg=0,Point3f preRotTra = Point3f(0,0,0))
01259 {
01260 float zeros[4]={0,0,0,0};
01261 square.Clear();
01262 Matrix44f rotM;
01263 tri::Grid(square,2,2,width,height,zeros);
01264 tri::UpdatePosition<MeshType>::Translate(square,Point3f(-width/2.0f,-height/2.0f,0.0f));
01265 if(angleDeg!=0){
01266 tri::UpdatePosition<MeshType>::Translate(square,preRotTra);
01267 rotM.SetRotateDeg(angleDeg,dir);
01268 tri::UpdatePosition<MeshType>::Matrix(square,rotM);
01269 }
01270 tri::UpdatePosition<MeshType>::Translate(square,c);
01271 tri::UpdateBounding<MeshType>::Box(square);
01272 }
01273
01274 template <class MeshType>
01275 void OrientedSquare(MeshType &square, float width, Point3f c, Point3f dir=Point3f(0,0,0), float angleDeg=0,Point3f preRotTra = Point3f(0,0,0))
01276 {
01277 OrientedRect(square,width,width,c,dir,angleDeg,preRotTra);
01278 }
01279
01280
01281
01283
01284 }
01285 }
01286 #endif