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.
This commit is contained in:
parent
6bd8470965
commit
d155a34740
|
@ -41,10 +41,14 @@
|
|||
// topology computation
|
||||
#include<vcg/complex/algorithms/update/topology.h>
|
||||
#include<vcg/complex/algorithms/update/bounding.h>
|
||||
#include <vcg/complex/algorithms/update/position.h>
|
||||
#include <vcg/complex/algorithms/update/quality.h>
|
||||
#include <vcg/complex/algorithms/stat.h>
|
||||
|
||||
// normals
|
||||
#include<vcg/complex/algorithms/update/normal.h>
|
||||
#include <vcg/complex/algorithms/intersection.h>
|
||||
#include <vcg/complex/algorithms/refine.h>
|
||||
#include <wrap/gl/glu_tessellator_cap.h>
|
||||
|
||||
using namespace vcg;
|
||||
|
@ -57,11 +61,126 @@ struct MyUsedTypes : public UsedTypes< Use<MyVertex> ::AsVertexType,
|
|||
Use<MyEdge> ::AsEdgeType,
|
||||
Use<MyFace> ::AsFaceType>{};
|
||||
|
||||
class MyVertex : public Vertex<MyUsedTypes, vertex::Coord3f, vertex::Normal3f, vertex::BitFlags >{};
|
||||
class MyFace : public Face< MyUsedTypes, face::FFAdj, face::VertexRef, face::BitFlags > {};
|
||||
class MyEdge : public Edge<MyUsedTypes,edge::EVAdj,edge::BitFlags,edge::EEAdj>{};
|
||||
class MyVertex : public Vertex<MyUsedTypes, vertex::Coord3f, vertex::Normal3f, vertex::Qualityf,vertex::BitFlags >{};
|
||||
class MyFace : public Face< MyUsedTypes, face::FFAdj, face::VertexRef, face::BitFlags >{};
|
||||
class MyEdge : public Edge<MyUsedTypes, edge::VertexRef,edge::BitFlags,edge::EEAdj>{};
|
||||
class MyMesh : public tri::TriMesh< vector<MyVertex>, vector<MyFace> , vector<MyEdge> > {};
|
||||
|
||||
|
||||
|
||||
void CapHole(MyMesh &m, MyMesh &capMesh, bool reverseFlag)
|
||||
{
|
||||
capMesh.Clear();
|
||||
std::vector< std::vector<Point3f> > outlines;
|
||||
std::vector<Point3f> outline;
|
||||
|
||||
tri::Allocator<MyMesh>::CompactVertexVector(m);
|
||||
tri::Allocator<MyMesh>::CompactFaceVector(m);
|
||||
tri::UpdateFlags<MyMesh>::FaceClearV(m);
|
||||
tri::UpdateFlags<MyMesh>::VertexClearV(m);
|
||||
tri::UpdateTopology<MyMesh>::FaceFace(m);
|
||||
int nv=0;
|
||||
|
||||
for(size_t i=0;i<m.face.size();i++)
|
||||
{
|
||||
for (int j=0;j<3;j++)
|
||||
if (!m.face[i].IsV() && face::IsBorder(m.face[i],j))
|
||||
{
|
||||
MyFace* startB=&(m.face[i]);
|
||||
vcg::face::Pos<MyFace> 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<MyMesh>::AddVertices(capMesh,nv);
|
||||
for (size_t i=0;i<outlines.size();i++)
|
||||
{
|
||||
for(size_t j=0;j<outlines[i].size();++j,++vi)
|
||||
(&*vi)->P()=outlines[i][j];
|
||||
}
|
||||
|
||||
std::vector<int> indices;
|
||||
glu_tesselator::tesselate(outlines, indices);
|
||||
|
||||
std::vector<Point3f> points;
|
||||
glu_tesselator::unroll(outlines, points);
|
||||
MyMesh::FaceIterator fi=tri::Allocator<MyMesh>::AddFaces(capMesh,nv-2);
|
||||
for (size_t i=0; i<indices.size(); i+=3,++fi)
|
||||
{
|
||||
(*&fi)->V(0)=&capMesh.vert[ indices[i+0] ];
|
||||
(*&fi)->V(1)=&capMesh.vert[ indices[i+1] ];
|
||||
(*&fi)->V(2)=&capMesh.vert[ indices[i+2] ];
|
||||
}
|
||||
tri::Clean<MyMesh>::RemoveDuplicateVertex(capMesh);
|
||||
tri::UpdateBounding<MyMesh>::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<MyMesh,MyMesh>::Mesh(A,m);
|
||||
tri::UpdateQuality<MyMesh>::VertexFromPlane(A, plane);
|
||||
QualityMidPointFunctor<MyMesh> slicingfunc(0.0f);
|
||||
QualityEdgePredicate<MyMesh> slicingpred(0.0f);
|
||||
tri::UpdateTopology<MyMesh>::FaceFace(A);
|
||||
// The Actual Slicing
|
||||
RefineE<MyMesh, QualityMidPointFunctor<MyMesh>, QualityEdgePredicate<MyMesh> > (A, slicingfunc, slicingpred, false);
|
||||
|
||||
tri::Append<MyMesh,MyMesh>::Mesh(B,A);
|
||||
|
||||
tri::UpdateSelection<MyMesh>::VertexFromQualityRange(A,-std::numeric_limits<float>::max(),0);
|
||||
tri::UpdateSelection<MyMesh>::FaceFromVertexStrict(A);
|
||||
for(MyMesh::FaceIterator fi=A.face.begin();fi!=A.face.end();++fi)
|
||||
if(!(*fi).IsD() && (*fi).IsS() ) tri::Allocator<MyMesh>::DeleteFace(A,*fi);
|
||||
tri::Clean<MyMesh>::RemoveUnreferencedVertex(A);
|
||||
|
||||
tri::UpdateSelection<MyMesh>::VertexFromQualityRange(B,0,std::numeric_limits<float>::max());
|
||||
tri::UpdateSelection<MyMesh>::FaceFromVertexStrict(B);
|
||||
for(MyMesh::FaceIterator fi=B.face.begin();fi!=B.face.end();++fi)
|
||||
if(!(*fi).IsD() && (*fi).IsS() ) tri::Allocator<MyMesh>::DeleteFace(B,*fi);
|
||||
tri::Clean<MyMesh>::RemoveUnreferencedVertex(B);
|
||||
|
||||
tri::UpdateTopology<MyMesh>::FaceFace(m);
|
||||
|
||||
MyMesh Cap;
|
||||
CapHole(A,Cap,0);
|
||||
tri::Append<MyMesh,MyMesh>::Mesh(A,Cap);
|
||||
|
||||
CapHole(B,Cap,0);
|
||||
tri::Append<MyMesh,MyMesh>::Mesh(B,Cap);
|
||||
|
||||
tri::Clean<MyMesh>::RemoveDuplicateVertex(A);
|
||||
tri::Clean<MyMesh>::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<MyMesh>::Open(m,argv[1])!=0)
|
||||
{
|
||||
printf("Error reading file %s\n",argv[1]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
tri::UpdateFlags<MyMesh>::FaceBorderFromFF(m);
|
||||
tri::UpdateNormals<MyMesh>::PerVertexNormalized(m);
|
||||
tri::UpdateBounding<MyMesh>::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<MyMesh, MyMesh, float>(m, slicingPlane, em );
|
||||
tri::Clean<MyMesh>::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<MyMesh>::Translate(A, slicingPlane.Direction()*m.bbox.Diag()/80.0);
|
||||
tri::UpdatePosition<MyMesh>::Translate(B,-slicingPlane.Direction()*m.bbox.Diag()/80.0);
|
||||
tri::Append<MyMesh,MyMesh>::Mesh(sliced,A);
|
||||
tri::Append<MyMesh,MyMesh>::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<MyMesh, MyMesh, float>(m, slicingPlane, em );
|
||||
tri::Clean<MyMesh>::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<MyMesh,MyMesh>::Mesh(full,cm);
|
||||
}
|
||||
|
||||
tri::io::ExporterPLY<MyMesh>::Save(full,"out.ply",false);
|
||||
tri::io::ExporterPLY<MyMesh>::Save(slice,"slice.ply",false);
|
||||
tri::io::ExporterPLY<MyMesh>::Save(sliced,"sliced.ply",false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue