/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef __VCGLIB_PLATONIC #define __VCGLIB_PLATONIC #include #include #include #include #include #include #include #include #include namespace vcg { namespace tri { /** \addtogroup trimesh */ //@{ /** A set of functions that builds meshes that represent surfaces of platonic solids, and other simple shapes. The 1st parameter is the mesh that will be filled with the solid. */ template void Tetrahedron(TetraMeshType &in) { typedef TetraMeshType MeshType; typedef typename TetraMeshType::CoordType CoordType; typedef typename TetraMeshType::VertexPointer VertexPointer; typedef typename TetraMeshType::VertexIterator VertexIterator; typedef typename TetraMeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,4); Allocator::AddFaces(in,4); VertexPointer ivp[4]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType ( 1.0, 1.0, 1.0); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType (-1.0, 1.0,-1.0); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType (-1.0,-1.0, 1.0); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType ( 1.0,-1.0,-1.0); FaceIterator fi=in.face.begin(); (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[3]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[1]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1]; } /// builds a Dodecahedron, /// (each pentagon is composed of 5 triangles) template void Dodecahedron(DodMeshType & in) { typedef DodMeshType MeshType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::ScalarType ScalarType; const int N_penta=12; const int N_points=62; int penta[N_penta*3*3]= {20,11, 18, 18, 11, 8, 8, 11, 4, 13,23, 4, 4, 23, 8, 8, 23, 16, 13, 4, 30, 30, 4, 28, 28, 4, 11, 16,34, 8, 8, 34, 18, 18, 34, 36, 11,20, 28, 28, 20, 45, 45, 20, 38, 13,30, 23, 23, 30, 41, 41, 30, 47, 16,23, 34, 34, 23, 50, 50, 23, 41, 20,18, 38, 38, 18, 52, 52, 18, 36, 30,28, 47, 47, 28, 56, 56, 28, 45, 50,60, 34, 34, 60, 36, 36, 60, 52, 45,38, 56, 56, 38, 60, 60, 38, 52, 50,41, 60, 60, 41, 56, 56, 41, 47 }; //A B E D C const ScalarType p=(1.0 + math::Sqrt(5.0)) / 2.0; const ScalarType p2=p*p; const ScalarType p3=p*p*p; ScalarType vv[N_points*3]= { 0, 0, 2*p2, p2, 0, p3, p, p2, p3, 0, p, p3, -p, p2, p3, -p2, 0, p3, -p, -p2, p3, 0, -p, p3, p, -p2, p3, p3, p, p2, p2, p2, p2, 0, p3, p2, -p2, p2, p2, -p3, p, p2, -p3, -p, p2, -p2, -p2, p2, 0, -p3, p2, p2, -p2, p2, p3, -p, p2, p3, 0, p, p2, p3, p, -p2, p3, p, -p3, 0, p, -p2, -p3, p, p2, -p3, p, 2*p2, 0, 0, p3, p2, 0, p, p3, 0, 0, 2*p2, 0, -p, p3, 0, -p3, p2, 0, -2*p2, 0, 0, -p3, -p2, 0, -p, -p3, 0, 0, -2*p2, 0, p, -p3, 0, p3, -p2, 0, p3, 0, -p, p2, p3, -p, -p2, p3, -p, -p3, 0, -p, -p2, -p3, -p, p2, -p3, -p, p3, p, -p2, p2, p2, -p2, 0, p3, -p2, -p2, p2, -p2, -p3, p, -p2, -p3, -p, -p2, -p2, -p2, -p2, 0, -p3, -p2, p2, -p2, -p2, p3, -p, -p2, p2, 0, -p3, p, p2, -p3, 0, p, -p3, -p, p2, -p3, -p2, 0, -p3, -p, -p2, -p3, 0, -p, -p3, p, -p2, -p3, 0, 0, -2*p2 }; in.Clear(); //in.face.clear(); Allocator::AddVertices(in,20+12); Allocator::AddFaces(in, 5*12); // five pentagons, each made by 5 tri int h,i,j,m=0; bool used[N_points]; for (i=0; i index(in.vn); for(j=0,vi=in.vert.begin();j void Octahedron(OctMeshType &in) { typedef OctMeshType MeshType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,6); Allocator::AddFaces(in,8); VertexPointer ivp[6]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 0, 0); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType ( 0, 1, 0); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType ( 0, 0, 1); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType (-1, 0, 0); ++vi; ivp[4]=&*vi;(*vi).P()=CoordType ( 0,-1, 0); ++vi; ivp[5]=&*vi;(*vi).P()=CoordType ( 0, 0,-1); FaceIterator fi=in.face.begin(); (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[5]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[1]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[5]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[4]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1]; } template void Icosahedron(IcoMeshType &in) { typedef IcoMeshType MeshType; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; ScalarType L=ScalarType((math::Sqrt(5.0)+1.0)/2.0); CoordType vv[12]={ CoordType ( 0, L, 1), CoordType ( 0, L,-1), CoordType ( 0,-L, 1), CoordType ( 0,-L,-1), CoordType ( L, 1, 0), CoordType ( L,-1, 0), CoordType (-L, 1, 0), CoordType (-L,-1, 0), CoordType ( 1, 0, L), CoordType (-1, 0, L), CoordType ( 1, 0,-L), CoordType (-1, 0,-L) }; int ff[20][3]={ {1,0,4},{0,1,6},{2,3,5},{3,2,7}, {4,5,10},{5,4,8},{6,7,9},{7,6,11}, {8,9,2},{9,8,0},{10,11,1},{11,10,3}, {0,8,4},{0,6,9},{1,4,10},{1,11,6}, {2,5,8},{2,9,7},{3,10,5},{3,7,11} }; in.Clear(); Allocator::AddVertices(in,12); Allocator::AddFaces(in,20); VertexPointer ivp[12]; VertexIterator vi; int i; for(i=0,vi=in.vert.begin();vi!=in.vert.end();++i,++vi){ (*vi).P()=vv[i]; ivp[i]=&*vi; } FaceIterator fi; for(i=0,fi=in.face.begin();fi!=in.face.end();++i,++fi){ (*fi).V(0)=ivp[ff[i][0]]; (*fi).V(1)=ivp[ff[i][1]]; (*fi).V(2)=ivp[ff[i][2]]; } } template void Hexahedron(MeshType &in) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,8); Allocator::AddFaces(in,12); VertexPointer ivp[8]; VertexIterator vi=in.vert.begin(); ivp[7]=&*vi;(*vi).P()=CoordType (-1,-1,-1); ++vi; ivp[6]=&*vi;(*vi).P()=CoordType ( 1,-1,-1); ++vi; ivp[5]=&*vi;(*vi).P()=CoordType (-1, 1,-1); ++vi; ivp[4]=&*vi;(*vi).P()=CoordType ( 1, 1,-1); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType (-1,-1, 1); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType ( 1,-1, 1); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType (-1, 1, 1); ++vi; ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 1, 1); FaceIterator fi=in.face.begin(); (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi; (*fi).V(0)=ivp[6]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[1]; ++fi; (*fi).V(0)=ivp[5]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[4]; ++fi; (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[6]; ++fi; (*fi).V(0)=ivp[4]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[5]; ++fi; (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[3]; ++fi; (*fi).V(0)=ivp[2]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[6]; ++fi; (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[5]; ++fi; (*fi).V(0)=ivp[1]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[3]; if (HasPerFaceFlags(in)) { FaceIterator fi=in.face.begin(); for (int k=0; k<12; k++) { (*fi).SetF(1); fi++; } } } template void Square(MeshType &in) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,4); Allocator::AddFaces(in,2); VertexPointer ivp[4]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 0, 0); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType ( 0, 1, 0); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType (-1, 0, 0); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType ( 0,-1, 0); FaceIterator fi=in.face.begin(); (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[2]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[0]; if (HasPerFaceFlags(in)) { FaceIterator fi=in.face.begin(); for (int k=0; k<2; k++) { (*fi).SetF(2); fi++; } } } template void SphericalCap(MeshType &in, float angleRad, const int subdiv = 3 ) { typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexIterator VertexIterator; in.Clear(); tri::Allocator::AddVertex(in,CoordType(0,0,0)); for(int i=0;i<6;++i) tri::Allocator::AddVertex(in,CoordType(cos(math::ToRad(i*60.0)),sin(math::ToRad(i*60.0)),0)); for(int i=0;i<6;++i) tri::Allocator::AddFace(in,&(in.vert[0]),&(in.vert[1+i]),&(in.vert[1+(i+1)%6])); tri::UpdateTopology::FaceFace(in); for(int i=0;i(&in)); tri::UpdateFlags::FaceBorderFromFF(in); tri::UpdateFlags::VertexBorderFromFaceBorder(in); for(int i=0;i::VertexFromBorderFlag(in); tri::UpdateSelection::VertexInvert(in); tri::Smooth::VertexCoordLaplacian(in,10,true); } float angleHalfRad = angleRad /2.0f; float width = sin(angleHalfRad); tri::UpdatePosition::Scale(in,width); tri::Allocator::CompactEveryVector(in); for(VertexIterator vi=in.vert.begin(); vi!=in.vert.end();++vi) { float cosVi = vi->P().Norm(); float angVi = asin (cosVi); vi->P()[2] = cos(angVi) - cos(angleHalfRad); } } // this function build a sphere starting from a eventually not empty mesh. // If the mesh is not empty it is 'spherified' and used as base for the subdivision process. // otherwise an icosahedron is used. template void Sphere(MeshType &in, const int subdiv = 3 ) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; if(in.vn==0 && in.fn==0) Icosahedron(in); VertexIterator vi; for(vi = in.vert.begin(); vi!=in.vert.end();++vi) vi->P().Normalize(); tri::UpdateFlags::FaceBorderFromNone(in); tri::UpdateTopology::FaceFace(in); size_t lastsize = 0; for(int i = 0 ; i < subdiv; ++i) { Refine< MeshType, MidPoint >(in, MidPoint(&in), 0); for(vi = in.vert.begin() + lastsize; vi != in.vert.end(); ++vi) vi->P().Normalize(); lastsize = in.vert.size(); } } /// r1 = raggio 1, r2 = raggio2, h = altezza (asse y) template void Cone( MeshType& in, const typename MeshType::ScalarType r1, const typename MeshType::ScalarType r2, const typename MeshType::ScalarType h, const int SubDiv = 36 ) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; int i,b1,b2; in.Clear(); int VN,FN; if(r1==0 || r2==0) { VN=SubDiv+2; FN=SubDiv*2; } else { VN=SubDiv*2+2; FN=SubDiv*4; } Allocator::AddVertices(in,VN); Allocator::AddFaces(in,FN); VertexPointer *ivp = new VertexPointer[VN]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType ( 0,-h/2.0,0 ); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType ( 0, h/2.0,0 ); ++vi; b1 = b2 = 2; int cnt=2; if(r1!=0) { for(i=0;i void Box(MeshType &in, const typename MeshType::BoxType & bb ) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,8); VertexPointer ivp[8]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.min[2]); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.min[2]); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.min[2]); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.min[2]); ++vi; ivp[4]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.max[2]); ++vi; ivp[5]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.max[2]); ++vi; ivp[6]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.max[2]); ++vi; ivp[7]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.max[2]); Allocator::AddFace(in,ivp[2],ivp[1],ivp[0]); Allocator::AddFace(in,ivp[1],ivp[2],ivp[3]); Allocator::AddFace(in,ivp[4],ivp[2],ivp[0]); Allocator::AddFace(in,ivp[2],ivp[4],ivp[6]); Allocator::AddFace(in,ivp[1],ivp[4],ivp[0]); Allocator::AddFace(in,ivp[4],ivp[1],ivp[5]); Allocator::AddFace(in,ivp[6],ivp[5],ivp[7]); Allocator::AddFace(in,ivp[5],ivp[6],ivp[4]); Allocator::AddFace(in,ivp[3],ivp[6],ivp[7]); Allocator::AddFace(in,ivp[6],ivp[3],ivp[2]); Allocator::AddFace(in,ivp[5],ivp[3],ivp[7]); Allocator::AddFace(in,ivp[3],ivp[5],ivp[1]); if (HasPerFaceFlags(in)) { FaceIterator fi=in.face.begin(); for (int k=0; k<12; k++) { (*fi).SetF(0); fi++; } } } // Torus template void Torus(MeshType &m, float hRingRadius, float vRingRadius, int hRingDiv=24, int vRingDiv=12 ) { typedef typename MeshType::CoordType CoordType; typedef typename MeshType::ScalarType ScalarType; typedef Matrix44 Matrix44x; m.Clear(); ScalarType angleStepV = (2.0f*M_PI)/vRingDiv; ScalarType angleStepH = (2.0f*M_PI)/hRingDiv; Allocator::AddVertices(m,(vRingDiv+1)*(hRingDiv+1)); for(int i=0;i::RemoveDuplicateVertex(m); tri::Allocator::CompactVertexVector(m); } // this function build a mesh starting from a vector of generic coords (objects having a triple of float at their beginning) // and a vector of faces (objects having a triple of ints at theri beginning). template void Build( MeshType & in, const V & v, const F & f) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,v.size()); Allocator::AddFaces(in,f.size()); for(size_t i=0;i index(in.vn); VertexIterator j; int k; for(k=0,j=in.vert.begin();j!=in.vert.end();++j,++k) index[k] = &*j; for(size_t i=0;i=0 ); assert( ff[1]>=0 ); assert( ff[2]>=0 ); assert( ff[0]::Box(in); } template void Build( MeshType & in, const V & v) { std::vector dummyfaceVec; Build(in,v,dummyfaceVec); } template void BuildFromNonFaux(TriMeshType &in, EdgeMeshType &out) { tri::RequireCompactness(in); std::vector::PEdge> edgevec; tri::UpdateTopology::FillUniqueEdgeVector(in, edgevec, false); out.Clear(); for(size_t i=0;i::AddVertex(out, in.vert[i].P()); tri::UpdateFlags::VertexClearV(out); for(size_t i=0;i::AddEdge(out,&out.vert[i0],&out.vert[i1]); if(in.vert[i0].IsS()) out.vert[i0].SetS(); if(in.vert[i1].IsS()) out.vert[i1].SetS(); } for(size_t i=0;i::DeleteVertex(out,out.vert[i]); tri::Allocator::CompactEveryVector(out); } // Build a regular grid mesh as a typical height field mesh // 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) // z is taken from the array // Once generated the vertex positions it uses the FaceGrid function to generate the faces; template void Grid(MeshType & in, int w, int h, float wl, float hl, float *data=0) { typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,w*h); float wld=wl/float(w-1); float hld=hl/float(h-1); float zVal=0; for(int i=0;i void FaceGrid(MeshType & in, int w, int h) { assert(in.vn == (int)in.vert.size()); // require a compact vertex vector assert(in.vn >= w*h); // the number of vertices should match the number of expected grid vertices Allocator::AddFaces(in,(w-1)*(h-1)*2); // i+0,j+0 -- i+0,j+1 // | \ | // | \ | // | \ | // | \ | // i+1,j+0 -- i+1,j+1 // for(int i=0;i void FaceGrid(MeshType & in, const std::vector &grid, int w, int h) { assert(in.vn == (int)in.vert.size()); // require a compact vertex vector assert(in.vn <= w*h); // the number of vertices should match the number of expected grid vertices // V0 V1 // i+0,j+0 -- i+0,j+1 // | \ | // | \ | // | \ | // | \ | // i+1,j+0 -- i+1,j+1 // V2 V3 for(int i=0;i=0 && V1i>=0 && V2i>=0 && V3i>=0 ) && tri::HasPerFaceFlags(in); if(V0i>=0 && V2i>=0 && V3i>=0 ) { typename MeshType::FaceIterator f= Allocator::AddFaces(in,1); f->V(0)=&(in.vert[V3i]); f->V(1)=&(in.vert[V2i]); f->V(2)=&(in.vert[V0i]); if (quad) f->SetF(2); ndone++; } if(V0i>=0 && V1i>=0 && V3i>=0 ) { typename MeshType::FaceIterator f= Allocator::AddFaces(in,1); f->V(0)=&(in.vert[V0i]); f->V(1)=&(in.vert[V1i]); f->V(2)=&(in.vert[V3i]); if (quad) f->SetF(2); ndone++; } if (ndone==0) { // try diag the other way if(V2i>=0 && V0i>=0 && V1i>=0 ) { typename MeshType::FaceIterator f= Allocator::AddFaces(in,1); f->V(0)=&(in.vert[V2i]); f->V(1)=&(in.vert[V0i]); f->V(2)=&(in.vert[V1i]); ndone++; } if(V1i>=0 && V3i>=0 && V2i>=0 ) { typename MeshType::FaceIterator f= Allocator::AddFaces(in,1); f->V(0)=&(in.vert[V1i]); f->V(1)=&(in.vert[V3i]); f->V(2)=&(in.vert[V2i]); ndone++; } } } } template void Annulus(MeshType & m, float externalRadius, float internalRadius, int slices) { m.Clear(); typename MeshType::VertexIterator vi = vcg::tri::Allocator::AddVertices(m,slices*2); for ( int j = 0; j < slices; ++j) { float x = cos( 2.0 * M_PI / slices * j); float y = sin( 2.0 * M_PI / slices * j); (*vi).P() = typename MeshType::CoordType(x,y,0)*internalRadius; ++vi; (*vi).P() = typename MeshType::CoordType(x,y,0)*externalRadius; ++vi; } typename MeshType::FaceIterator fi ; for ( int j = 0; j < slices; ++j) { fi = vcg::tri::Allocator::AddFaces(m,1); (*fi).V(0) = &m.vert[ ((j+0)*2+0)%(slices*2) ]; (*fi).V(1) = &m.vert[ ((j+1)*2+1)%(slices*2) ]; (*fi).V(2) = &m.vert[ ((j+0)*2+1)%(slices*2) ]; fi = vcg::tri::Allocator::AddFaces(m,1); (*fi).V(0) = &m.vert[ ((j+1)*2+0)%(slices*2) ]; (*fi).V(1) = &m.vert[ ((j+1)*2+1)%(slices*2) ]; (*fi).V(2) = &m.vert[ ((j+0)*2+0)%(slices*2) ]; } } template void OrientedAnnulus(MeshType & m, Point3f center, Point3f norm, float externalRadius, float internalRadius, int slices) { Annulus(m,externalRadius,internalRadius, slices); float angleRad = Angle(Point3f(0,0,1),norm); Point3f axis = Point3f(0,0,1)^norm; Matrix44f rotM; rotM.SetRotateRad(angleRad,axis); tri::UpdatePosition::Matrix(m,rotM); tri::UpdatePosition::Translate(m,center); } template void Disk(MeshType & m, int slices) { m.Clear(); typename MeshType::VertexIterator vi = vcg::tri::Allocator::AddVertices(m,slices+1); (*vi).P() = typename MeshType::CoordType(0,0,0); ++vi; for ( int j = 0; j < slices; ++j) { float x = cos( 2.0 * M_PI / slices * j); float y = sin( 2.0 * M_PI / slices * j); (*vi).P() = typename MeshType::CoordType(x,y,0); ++vi; } typename MeshType::FaceIterator fi ; for ( int j = 0; j < slices; ++j) { int a = 1+(j+0)%slices; int b = 1+(j+1)%slices; fi = vcg::tri::Allocator::AddFaces(m,1); (*fi).V(0) = &m.vert[ 0 ]; (*fi).V(1) = &m.vert[ a ]; (*fi).V(2) = &m.vert[ b ]; } } template void OrientedDisk(MeshType &m, int slices, typename MeshType::CoordType center, typename MeshType::CoordType norm, float radius) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; Disk(m,slices); tri::UpdatePosition::Scale(m,radius); ScalarType angleRad = Angle(CoordType(0,0,1),norm); CoordType axis = CoordType(0,0,1)^norm; Matrix44 rotM; rotM.SetRotateRad(angleRad,axis); tri::UpdatePosition::Matrix(m,rotM); tri::UpdatePosition::Translate(m,center); } template 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 ) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef Matrix44 Matrix44x; Cylinder(slices,stacks,m,capped); tri::UpdatePosition::Translate(m,CoordType(0,1,0)); tri::UpdatePosition::Scale(m,CoordType(1,0.5f,1)); tri::UpdatePosition::Scale(m,CoordType(xScale,1.0f,yScale)); float height = Distance(origin,end); tri::UpdatePosition::Scale(m,CoordType(radius,height,radius)); CoordType norm = end-origin; ScalarType angleRad = Angle(CoordType(0,1,0),norm); CoordType axis = CoordType(0,1,0)^norm; Matrix44x rotM; rotM.SetRotateRad(angleRad,axis); tri::UpdatePosition::Matrix(m,rotM); tri::UpdatePosition::Translate(m,origin); } template void OrientedCylinder(MeshType & m, const typename MeshType::CoordType origin, const typename MeshType::CoordType end, float radius, bool capped, int slices=32, int stacks=4 ) { OrientedEllipticPrism(m,origin,end,radius,1.0f,1.0f,capped,slices,stacks); } template void Cylinder(int slices, int stacks, MeshType & m, bool capped=false) { m.Clear(); typename MeshType::VertexIterator vi = vcg::tri::Allocator::AddVertices(m,slices*(stacks+1)); for ( int i = 0; i < stacks+1; ++i) for ( int j = 0; j < slices; ++j) { float x,y,h; x = cos( 2.0 * M_PI / slices * j); y = sin( 2.0 * M_PI / slices * j); h = 2 * i / (float)(stacks) - 1; (*vi).P() = typename MeshType::CoordType(x,h,y); ++vi; } for ( int j = 0; j < stacks; ++j) for ( int i = 0; i < slices; ++i) { int a,b,c,d; a = (j+0)*slices + i; b = (j+1)*slices + i; c = (j+1)*slices + (i+1)%slices; d = (j+0)*slices + (i+1)%slices; if(((i+j)%2) == 0){ vcg::tri::Allocator::AddFace(m, &m.vert[ a ], &m.vert[ b ], &m.vert[ c ]); vcg::tri::Allocator::AddFace(m, &m.vert[ c ], &m.vert[ d ], &m.vert[ a ]); } else{ vcg::tri::Allocator::AddFace(m, &m.vert[ b ], &m.vert[ c ], &m.vert[ d ]); vcg::tri::Allocator::AddFace(m, &m.vert[ d ], &m.vert[ a ], &m.vert[ b ]); } } if(capped) { tri::Allocator::AddVertex(m,typename MeshType::CoordType(0,-1,0)); tri::Allocator::AddVertex(m,typename MeshType::CoordType(0, 1,0)); int base = 0; for ( int i = 0; i < slices; ++i) vcg::tri::Allocator::AddFace(m, &m.vert[ m.vn-2 ], &m.vert[ base+i ], &m.vert[ base+(i+1)%slices ]); base = (stacks)*slices; for ( int i = 0; i < slices; ++i) vcg::tri::Allocator::AddFace(m, &m.vert[ m.vn-1 ], &m.vert[ base+(i+1)%slices ], &m.vert[ base+i ]); } if (HasPerFaceFlags(m)) { for (typename MeshType::FaceIterator fi=m.face.begin(); fi!=m.face.end(); fi++) { (*fi).SetF(2); } } } class _SphFace; class _SphVertex; struct _SphUsedTypes : public UsedTypes< Use<_SphVertex> ::AsVertexType, Use<_SphFace> ::AsFaceType>{}; class _SphVertex : public Vertex<_SphUsedTypes, vertex::Coord3f, vertex::Normal3f, vertex::BitFlags >{}; class _SphFace : public Face< _SphUsedTypes, face::VertexRef, face::Normal3f, face::BitFlags, face::FFAdj > {}; class _SphMesh : public tri::TriMesh< vector<_SphVertex>, vector<_SphFace> > {}; template void BuildPrismFaceShell(MeshType &mIn, MeshType &mOut, float height=0, float inset=0, bool smoothFlag=true ) { typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::CoordType CoordType; if(height==0) height = mIn.bbox.Diag()/100.0f; if(inset==0) inset = mIn.bbox.Diag()/200.0f; tri::UpdateTopology::FaceFace(mIn); tri::UpdateFlags::FaceClearV(mIn); for(size_t i=0;i vertVec; std::vector faceVec; tri::PolygonSupport::ExtractPolygon(&(mIn.face[i]),vertVec,faceVec); size_t vn = vertVec.size(); CoordType nf(0,0,0); for(size_t j=0;jN().Normalize() * DoubleArea(*faceVec[j]); nf.Normalize(); nf = nf*height/2.0f; CoordType bary(0,0,0); for(size_t j=0;j::AddVertex(faceM, bary-nf); tri::Allocator::AddVertex(faceM, bary+nf); for(size_t j=0;jP() - bary); delta.Normalize(); delta = delta*inset; tri::Allocator::AddVertex(faceM, vertVec[j]->P()-delta-nf); tri::Allocator::AddVertex(faceM, vertVec[j]->P()-delta+nf); } // Build top and bottom faces for(size_t j=0;j::AddFace(faceM, 0, 2+(j+0)*2, 2+((j+1)%vn)*2 ); for(size_t j=0;j::AddFace(faceM, 1, 3+((j+1)%vn)*2, 3+(j+0)*2 ); // Build side strip for(size_t j=0;j::AddFace(faceM, 2+ j0*2 + 0 , 2+ j0*2+1, 2+j1*2+0); tri::Allocator::AddFace(faceM, 2+ j0*2 + 1 , 2+ j1*2+1, 2+j1*2+0); } for(size_t j=0;j<2*vn;++j) faceM.face[j].SetS(); if(smoothFlag) { faceM.face.EnableFFAdjacency(); tri::UpdateTopology::FaceFace(faceM); tri::UpdateFlags::FaceBorderFromFF(faceM); tri::Refine(faceM, MidPoint(&faceM),0,true); tri::Refine(faceM, MidPoint(&faceM),0,true); tri::UpdateSelection::VertexFromFaceStrict(faceM); tri::Smooth::VertexCoordLaplacian(faceM,2,true,true); } tri::Append::Mesh(mOut,faceM); } // end main loop for each face; } template void BuildCylinderEdgeShell(MeshType &mIn, MeshType &mOut, float radius=0, int slices=16, int stacks=1 ) { if(radius==0) radius = mIn.bbox.Diag()/100.0f; typedef typename tri::UpdateTopology::PEdge PEdge; std::vector edgeVec; tri::UpdateTopology::FillUniqueEdgeVector(mIn,edgeVec,false); for(size_t i=0;iP(),edgeVec[i].v[1]->P(),radius,false,slices,stacks); tri::Append::Mesh(mOut,mCyl); } } template void BuildSphereVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, int recDiv=2 ) { if(radius==0) radius = mIn.bbox.Diag()/100.0f; for(size_t i=0;i::Scale(mSph,radius); tri::UpdatePosition::Translate(mSph,mIn.vert[i].P()); tri::Append::Mesh(mOut,mSph); } } template void BuildCylinderVertexShell(MeshType &mIn, MeshType &mOut, float radius=0, float height=0 ) { typedef typename MeshType::CoordType CoordType; if(radius==0) radius = mIn.bbox.Diag()/100.0f; if(height==0) height = mIn.bbox.Diag()/200.0f; for(size_t i=0;i::Mesh(mOut,mCyl); } } template void GenerateCameraMesh(MeshType &in){ typedef typename MeshType::CoordType MV; MV vv[52]={ MV(-0.000122145 , -0.2 ,0.35), 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), 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), 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), 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), 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), MV(-0.203079 , -0.1 ,0.471362), }; int ff[88][3]={ {0,2,3}, {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}, {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}, {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}, {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}, {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}, {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}, {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}, {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}, {43,36,44},{51,44,45},{51,45,46},{51,46,47},{51,47,48},{51,49,50},{51,50,44}, }; in.Clear(); Allocator::AddVertices(in,52); Allocator::AddFaces(in,88); in.vn=52;in.fn=88; int i,j; for(i=0;i index(in.vn); typename MeshType::VertexIterator vi; for(j=0,vi=in.vert.begin();j 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)) { float zeros[4]={0,0,0,0}; square.Clear(); Matrix44f rotM; tri::Grid(square,2,2,width,height,zeros); tri::UpdatePosition::Translate(square,Point3f(-width/2.0f,-height/2.0f,0.0f)); if(angleDeg!=0){ tri::UpdatePosition::Translate(square,preRotTra); rotM.SetRotateDeg(angleDeg,dir); tri::UpdatePosition::Matrix(square,rotM); } tri::UpdatePosition::Translate(square,c); tri::UpdateBounding::Box(square); } template void OrientedSquare(MeshType &square, float width, Point3f c, Point3f dir=Point3f(0,0,0), float angleDeg=0,Point3f preRotTra = Point3f(0,0,0)) { OrientedRect(square,width,width,c,dir,angleDeg,preRotTra); } //@} } // End Namespace TriMesh } // End Namespace vcg #endif