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
|
// topology computation
|
||||||
#include<vcg/complex/algorithms/update/topology.h>
|
#include<vcg/complex/algorithms/update/topology.h>
|
||||||
#include<vcg/complex/algorithms/update/bounding.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
|
// normals
|
||||||
#include<vcg/complex/algorithms/update/normal.h>
|
#include<vcg/complex/algorithms/update/normal.h>
|
||||||
#include <vcg/complex/algorithms/intersection.h>
|
#include <vcg/complex/algorithms/intersection.h>
|
||||||
|
#include <vcg/complex/algorithms/refine.h>
|
||||||
#include <wrap/gl/glu_tessellator_cap.h>
|
#include <wrap/gl/glu_tessellator_cap.h>
|
||||||
|
|
||||||
using namespace vcg;
|
using namespace vcg;
|
||||||
|
@ -57,11 +61,126 @@ struct MyUsedTypes : public UsedTypes< Use<MyVertex> ::AsVertexType,
|
||||||
Use<MyEdge> ::AsEdgeType,
|
Use<MyEdge> ::AsEdgeType,
|
||||||
Use<MyFace> ::AsFaceType>{};
|
Use<MyFace> ::AsFaceType>{};
|
||||||
|
|
||||||
class MyVertex : public Vertex<MyUsedTypes, vertex::Coord3f, vertex::Normal3f, vertex::BitFlags >{};
|
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 MyFace : public Face< MyUsedTypes, face::FFAdj, face::VertexRef, face::BitFlags >{};
|
||||||
class MyEdge : public Edge<MyUsedTypes,edge::EVAdj,edge::BitFlags,edge::EEAdj>{};
|
class MyEdge : public Edge<MyUsedTypes, edge::VertexRef,edge::BitFlags,edge::EEAdj>{};
|
||||||
class MyMesh : public tri::TriMesh< vector<MyVertex>, vector<MyFace> , vector<MyEdge> > {};
|
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 )
|
int main( int argc, char **argv )
|
||||||
{
|
{
|
||||||
if(argc<2)
|
if(argc<2)
|
||||||
|
@ -70,45 +189,38 @@ int main( int argc, char **argv )
|
||||||
return -1;
|
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)
|
if(tri::io::ImporterPLY<MyMesh>::Open(m,argv[1])!=0)
|
||||||
{
|
{
|
||||||
printf("Error reading file %s\n",argv[1]);
|
printf("Error reading file %s\n",argv[1]);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tri::UpdateFlags<MyMesh>::FaceBorderFromFF(m);
|
|
||||||
tri::UpdateNormals<MyMesh>::PerVertexNormalized(m);
|
|
||||||
tri::UpdateBounding<MyMesh>::Box(m);
|
tri::UpdateBounding<MyMesh>::Box(m);
|
||||||
|
|
||||||
printf("Input mesh vn:%i fn:%i\n",m.vn,m.fn);
|
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));
|
srand(time(0));
|
||||||
|
|
||||||
Plane3f slicingPlane;
|
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)
|
MyMesh A,B;
|
||||||
{
|
bool ret=SplitMesh(m,A,B,slicingPlane);
|
||||||
cm.Clear();
|
tri::UpdatePosition<MyMesh>::Translate(A, slicingPlane.Direction()*m.bbox.Diag()/80.0);
|
||||||
em.Clear();
|
tri::UpdatePosition<MyMesh>::Translate(B,-slicingPlane.Direction()*m.bbox.Diag()/80.0);
|
||||||
Point3f planeDir = Point3f(-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX);
|
tri::Append<MyMesh,MyMesh>::Mesh(sliced,A);
|
||||||
planeDir.Normalize();
|
tri::Append<MyMesh,MyMesh>::Mesh(sliced,B);
|
||||||
printf("slicing dir %5.2f %5.2f %5.2f\n",planeDir[0],planeDir[1],planeDir[2]);
|
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);
|
tri::io::ExporterPLY<MyMesh>::Save(slice,"slice.ply",false);
|
||||||
|
tri::io::ExporterPLY<MyMesh>::Save(sliced,"sliced.ply",false);
|
||||||
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);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
######################################################################
|
|
||||||
# Automatically generated by qmake (2.00a) ven 24. giu 14:14:20 2005
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
TARGET = trimesh_edge
|
TARGET = trimesh_edge
|
||||||
DEPENDPATH += .
|
DEPENDPATH += . ../../..
|
||||||
INCLUDEPATH += . ../../..
|
INCLUDEPATH += . ../../..
|
||||||
CONFIG += console stl opengl
|
CONFIG += console stl opengl
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
|
|
Loading…
Reference in New Issue