platonic.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
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    //A B   E                D       C
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     //in.face.clear();
00134   Allocator<DodMeshType>::AddVertices(in,20+12);
00135   Allocator<DodMeshType>::AddFaces(in, 5*12); // five pentagons, each made by 5 tri
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         // tag faux edges
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 // this function build a sphere starting from a eventually not empty mesh.
00400 // If the mesh is not empty it is 'spherified' and used as base for the subdivision process.
00401 // otherwise an icosahedron is used.
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 // Torus
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     //u=ScalarType(i%hRingDiv)*angleStepH + angleStepH/2.0;
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 // this function build a mesh starting from a vector of generic coords (objects having a triple of float at their beginning)
00693 // and a vector of faces (objects having a triple of ints at theri beginning).
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 // Build a regular grid mesh as a typical height field mesh
00772 // 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)
00773 // z is taken from the <data> array
00774 // Once generated the vertex positions it uses the FaceGrid function to generate the faces;
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 // Build a regular grid mesh of faces as a typical height field mesh
00798 // Vertexes are assumed to be already be allocated.
00799 
00800 template <class MeshType>
00801 void FaceGrid(MeshType & in, int w, int h)
00802 {
00803     assert(in.vn == (int)in.vert.size()); // require a compact vertex vector
00804     assert(in.vn >= w*h); // the number of vertices should match the number of expected grid vertices
00805 
00806     Allocator<MeshType>::AddFaces(in,(w-1)*(h-1)*2);
00807 
00808 //   i+0,j+0 -- i+0,j+1
00809 //      |   \     |
00810 //      |    \    |
00811 //      |     \   |
00812 //      |      \  |
00813 //   i+1,j+0 -- i+1,j+1
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 // Build a regular grid mesh of faces as a typical height field mesh
00837 // Vertexes are assumed to be already be allocated, but not oll the grid vertexes are present.
00838 // For this purpos a grid of indexes is also passed. negative indexes means that there is no vertex.
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); // the number of vertices should match the number of expected grid vertices
00845 
00846 //          V0       V1
00847 //   i+0,j+0 -- i+0,j+1
00848 //      |   \     |
00849 //      |    \    |
00850 //      |     \   |
00851 //      |      \  |
00852 //   i+1,j+0 -- i+1,j+1
00853 //     V2        V3
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) { // try diag the other way
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     // Add vertices (alternated top and bottom)
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     // Build top and bottom faces
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     // Build side strip
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   } // end main loop for each face;
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 } // End Namespace TriMesh
01285 } // End Namespace vcg
01286 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:34:12