From d155a347408a354665eef9f68f264cb267e059fc Mon Sep 17 00:00:00 2001 From: cignoni Date: Mon, 24 Oct 2011 12:19:05 +0000 Subject: [PATCH] Cleaned up the example of the mesh slicing. Now the sample take a mesh, split it along a random plane and saves two meshes, one with the filled triangulated slice and one with the two pieces of the mesh moved apart to reveal the cut. --- apps/sample/trimesh_edge/trimesh_edge.cpp | 172 ++++++++++++++++++---- apps/sample/trimesh_edge/trimesh_edge.pro | 6 +- 2 files changed, 143 insertions(+), 35 deletions(-) diff --git a/apps/sample/trimesh_edge/trimesh_edge.cpp b/apps/sample/trimesh_edge/trimesh_edge.cpp index 9ba7ca44..cc502d2c 100644 --- a/apps/sample/trimesh_edge/trimesh_edge.cpp +++ b/apps/sample/trimesh_edge/trimesh_edge.cpp @@ -41,10 +41,14 @@ // topology computation #include #include +#include +#include +#include // normals #include #include +#include #include using namespace vcg; @@ -57,11 +61,126 @@ struct MyUsedTypes : public UsedTypes< Use ::AsVertexType, Use ::AsEdgeType, Use ::AsFaceType>{}; -class MyVertex : public Vertex{}; -class MyFace : public Face< MyUsedTypes, face::FFAdj, face::VertexRef, face::BitFlags > {}; -class MyEdge : public Edge{}; +class MyVertex : public Vertex{}; +class MyFace : public Face< MyUsedTypes, face::FFAdj, face::VertexRef, face::BitFlags >{}; +class MyEdge : public Edge{}; class MyMesh : public tri::TriMesh< vector, vector , vector > {}; + + +void CapHole(MyMesh &m, MyMesh &capMesh, bool reverseFlag) +{ + capMesh.Clear(); + std::vector< std::vector > outlines; + std::vector outline; + + tri::Allocator::CompactVertexVector(m); + tri::Allocator::CompactFaceVector(m); + tri::UpdateFlags::FaceClearV(m); + tri::UpdateFlags::VertexClearV(m); + tri::UpdateTopology::FaceFace(m); + int nv=0; + + for(size_t i=0;i p(startB,j); + assert(p.IsBorder()); + do + { + assert(p.IsManifold()); + p.F()->SetV(); + outline.push_back(p.V()->P()); + p.NextB(); + nv++; + } + while(!p.F()->IsV()); + if (reverseFlag) + std::reverse(outline.begin(),outline.end()); + + outlines.push_back(outline); + outline.clear(); + } + } + if (nv<2) return; + MyMesh::VertexIterator vi=vcg::tri::Allocator::AddVertices(capMesh,nv); + for (size_t i=0;iP()=outlines[i][j]; + } + + std::vector indices; + glu_tesselator::tesselate(outlines, indices); + + std::vector points; + glu_tesselator::unroll(outlines, points); + MyMesh::FaceIterator fi=tri::Allocator::AddFaces(capMesh,nv-2); + for (size_t i=0; iV(0)=&capMesh.vert[ indices[i+0] ]; + (*&fi)->V(1)=&capMesh.vert[ indices[i+1] ]; + (*&fi)->V(2)=&capMesh.vert[ indices[i+2] ]; + } + tri::Clean::RemoveDuplicateVertex(capMesh); + tri::UpdateBounding::Box(capMesh); +} + + + + +bool SplitMesh(MyMesh &m, /// The mesh that has to be splitted. It is NOT changed + MyMesh &A, MyMesh &B, /// The two resulting pieces, correct only if true is returned + Plane3f plane) +{ + tri::Append::Mesh(A,m); + tri::UpdateQuality::VertexFromPlane(A, plane); + QualityMidPointFunctor slicingfunc(0.0f); + QualityEdgePredicate slicingpred(0.0f); + tri::UpdateTopology::FaceFace(A); + // The Actual Slicing + RefineE, QualityEdgePredicate > (A, slicingfunc, slicingpred, false); + + tri::Append::Mesh(B,A); + + tri::UpdateSelection::VertexFromQualityRange(A,-std::numeric_limits::max(),0); + tri::UpdateSelection::FaceFromVertexStrict(A); + for(MyMesh::FaceIterator fi=A.face.begin();fi!=A.face.end();++fi) + if(!(*fi).IsD() && (*fi).IsS() ) tri::Allocator::DeleteFace(A,*fi); + tri::Clean::RemoveUnreferencedVertex(A); + + tri::UpdateSelection::VertexFromQualityRange(B,0,std::numeric_limits::max()); + tri::UpdateSelection::FaceFromVertexStrict(B); + for(MyMesh::FaceIterator fi=B.face.begin();fi!=B.face.end();++fi) + if(!(*fi).IsD() && (*fi).IsS() ) tri::Allocator::DeleteFace(B,*fi); + tri::Clean::RemoveUnreferencedVertex(B); + + tri::UpdateTopology::FaceFace(m); + + MyMesh Cap; + CapHole(A,Cap,0); + tri::Append::Mesh(A,Cap); + + CapHole(B,Cap,0); + tri::Append::Mesh(B,Cap); + + tri::Clean::RemoveDuplicateVertex(A); + tri::Clean::RemoveDuplicateVertex(B); + return true; +} + +void GetRandPlane(Box3f &bb, Plane3f &plane) +{ + Point3f planeCenter = bb.Center(); + Point3f planeDir = Point3f(-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX); + planeDir.Normalize(); + + plane.Init(planeCenter+planeDir*0.3f*bb.Diag()*float(rand())/RAND_MAX,planeDir); +} + int main( int argc, char **argv ) { if(argc<2) @@ -70,45 +189,38 @@ int main( int argc, char **argv ) return -1; } - MyMesh m,em,cm,full; + MyMesh m, // The loaded mesh + em, // the 2D polyline representing the section + slice, // the planar mesh resulting from the triangulation of the above + sliced; // the 3D mesh resulting by the actual slicing of m into two capped sub pieces if(tri::io::ImporterPLY::Open(m,argv[1])!=0) { printf("Error reading file %s\n",argv[1]); exit(0); } - - tri::UpdateFlags::FaceBorderFromFF(m); - tri::UpdateNormals::PerVertexNormalized(m); tri::UpdateBounding::Box(m); - printf("Input mesh vn:%i fn:%i\n",m.vn,m.fn); - printf( "Mesh has %i vert and %i faces\n", m.vn, m.fn ); srand(time(0)); + Plane3f slicingPlane; - Point3f planeCenter = m.bbox.Center(); + GetRandPlane(m.bbox,slicingPlane); + printf("slicing dir %5.2f %5.2f %5.2f\n",slicingPlane.Direction()[0],slicingPlane.Direction()[1],slicingPlane.Direction()[2]); + vcg::IntersectionPlaneMesh(m, slicingPlane, em ); + tri::Clean::RemoveDuplicateVertex(em); + vcg::tri::CapEdgeMesh(em,slice); + printf("Slice mesh has %i vert and %i faces\n", slice.vn, slice.fn ); - for(int i=0;i<10;++i) - { - cm.Clear(); - em.Clear(); - Point3f planeDir = Point3f(-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX); - planeDir.Normalize(); - printf("slicing dir %5.2f %5.2f %5.2f\n",planeDir[0],planeDir[1],planeDir[2]); + MyMesh A,B; + bool ret=SplitMesh(m,A,B,slicingPlane); + tri::UpdatePosition::Translate(A, slicingPlane.Direction()*m.bbox.Diag()/80.0); + tri::UpdatePosition::Translate(B,-slicingPlane.Direction()*m.bbox.Diag()/80.0); + tri::Append::Mesh(sliced,A); + tri::Append::Mesh(sliced,B); + printf("Sliced mesh has %i vert and %i faces\n", sliced.vn, sliced.fn ); - slicingPlane.Init(planeCenter+planeDir*0.3f*m.bbox.Diag()*float(rand())/RAND_MAX,planeDir); - - vcg::IntersectionPlaneMesh(m, slicingPlane, em ); - tri::Clean::RemoveDuplicateVertex(em); - vcg::tri::CapEdgeMesh(em,cm); - - printf(" edge mesh vn %5i en %5i fn %5i\n",em.vn,em.en,em.fn); - printf("sliced mesh vn %5i en %5i fn %5i\n",cm.vn,cm.en,cm.fn); - - tri::Append::Mesh(full,cm); - } - - tri::io::ExporterPLY::Save(full,"out.ply",false); + tri::io::ExporterPLY::Save(slice,"slice.ply",false); + tri::io::ExporterPLY::Save(sliced,"sliced.ply",false); return 0; } diff --git a/apps/sample/trimesh_edge/trimesh_edge.pro b/apps/sample/trimesh_edge/trimesh_edge.pro index f73fd735..50a39fbb 100644 --- a/apps/sample/trimesh_edge/trimesh_edge.pro +++ b/apps/sample/trimesh_edge/trimesh_edge.pro @@ -1,9 +1,5 @@ -###################################################################### -# Automatically generated by qmake (2.00a) ven 24. giu 14:14:20 2005 -###################################################################### - TARGET = trimesh_edge -DEPENDPATH += . +DEPENDPATH += . ../../.. INCLUDEPATH += . ../../.. CONFIG += console stl opengl TEMPLATE = app