edgemesh uniform sampler fixed + voronoi remesher improved
This commit is contained in:
parent
7f38262616
commit
992ab0ca2e
|
|
@ -78,7 +78,7 @@ int main( int argc, char **argv )
|
||||||
} catch (exception &) {}
|
} catch (exception &) {}
|
||||||
}
|
}
|
||||||
std::cout << "Remeshing using sampling radius: " << samplingRadius << std::endl;
|
std::cout << "Remeshing using sampling radius: " << samplingRadius << std::endl;
|
||||||
auto remeshed = Remesher<MyMesh>::Remesh(startMesh, samplingRadius, 50.0, 0.0);
|
auto remeshed = Remesher<MyMesh>::Remesh(startMesh, samplingRadius, 70.0);
|
||||||
|
|
||||||
|
|
||||||
tri::io::ExporterPLY<MyMesh>::Save(*remeshed,"Full.ply",tri::io::Mask::IOM_VERTCOLOR|tri::io::Mask::IOM_WEDGTEXCOORD );
|
tri::io::ExporterPLY<MyMesh>::Save(*remeshed,"Full.ply",tri::io::Mask::IOM_VERTCOLOR|tri::io::Mask::IOM_WEDGTEXCOORD );
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ sampling strategies (montecarlo, stratified etc).
|
||||||
#include <vcg/complex/algorithms/update/bounding.h>
|
#include <vcg/complex/algorithms/update/bounding.h>
|
||||||
#include <vcg/space/segment2.h>
|
#include <vcg/space/segment2.h>
|
||||||
#include <vcg/space/index/grid_static_ptr.h>
|
#include <vcg/space/index/grid_static_ptr.h>
|
||||||
|
|
||||||
namespace vcg
|
namespace vcg
|
||||||
{
|
{
|
||||||
namespace tri
|
namespace tri
|
||||||
|
|
@ -770,13 +771,13 @@ static void EdgeMeshUniform(MeshType &m, VertexSampler &ps, float radius, bool c
|
||||||
tri::UpdateTopology<MeshType>::EdgeEdge(m);
|
tri::UpdateTopology<MeshType>::EdgeEdge(m);
|
||||||
tri::UpdateFlags<MeshType>::EdgeClearV(m);
|
tri::UpdateFlags<MeshType>::EdgeClearV(m);
|
||||||
tri::MeshAssert<MeshType>::EEOneManifold(m);
|
tri::MeshAssert<MeshType>::EEOneManifold(m);
|
||||||
|
|
||||||
for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
|
for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
|
||||||
{
|
{
|
||||||
if (!ei->IsV())
|
if (!ei->IsV())
|
||||||
{
|
{
|
||||||
edge::Pos<EdgeType> ep(&*ei,0);
|
edge::Pos<EdgeType> ep(&*ei,0);
|
||||||
edge::Pos<EdgeType> startep = ep;
|
edge::Pos<EdgeType> startep = ep;
|
||||||
VertexPointer startVertex = 0;
|
|
||||||
do // first loop to search a boundary component.
|
do // first loop to search a boundary component.
|
||||||
{
|
{
|
||||||
ep.NextE();
|
ep.NextE();
|
||||||
|
|
@ -786,10 +787,33 @@ static void EdgeMeshUniform(MeshType &m, VertexSampler &ps, float radius, bool c
|
||||||
if (!ep.IsBorder())
|
if (!ep.IsBorder())
|
||||||
{
|
{
|
||||||
// it's a loop
|
// it's a loop
|
||||||
startVertex = ep.V();
|
assert(ep == startep);
|
||||||
|
|
||||||
|
// to keep the uniform resampling order-independent:
|
||||||
|
// 1) start from the 'lowest' point...
|
||||||
|
edge::Pos<EdgeType> altEp = ep;
|
||||||
|
altEp.NextE();
|
||||||
|
while (altEp != startep) {
|
||||||
|
if (altEp.V()->cP() < ep.V()->cP())
|
||||||
|
{
|
||||||
|
ep = altEp;
|
||||||
|
}
|
||||||
|
altEp.NextE();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) ... with consistent direction
|
||||||
|
const auto dir0 = ep.VFlip()->cP() - ep.V()->cP();
|
||||||
|
ep.FlipE();
|
||||||
|
const auto dir1 = ep.VFlip()->cP() - ep.V()->cP();
|
||||||
|
if (dir0 < dir1)
|
||||||
|
{
|
||||||
|
ep.FlipE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// not a loop
|
||||||
|
|
||||||
// to keep the uniform resampling order-independent
|
// to keep the uniform resampling order-independent
|
||||||
// start from the border with 'lowest' point
|
// start from the border with 'lowest' point
|
||||||
edge::Pos<EdgeType> altEp = ep;
|
edge::Pos<EdgeType> altEp = ep;
|
||||||
|
|
@ -805,17 +829,22 @@ static void EdgeMeshUniform(MeshType &m, VertexSampler &ps, float radius, bool c
|
||||||
|
|
||||||
ScalarType totalLen = 0;
|
ScalarType totalLen = 0;
|
||||||
ep.FlipV();
|
ep.FlipV();
|
||||||
// second loop to compute length of the chain.
|
// second loop to compute the length of the chain.
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ep.E()->SetV();
|
ep.E()->SetV();
|
||||||
totalLen += Distance(ep.V()->cP(), ep.VFlip()->cP());
|
totalLen += Distance(ep.V()->cP(), ep.VFlip()->cP());
|
||||||
ep.NextE();
|
ep.NextE();
|
||||||
} while (!ep.IsBorder() && ep.V() != startVertex);
|
} while (!ep.E()->IsV() && !ep.IsBorder());
|
||||||
|
if (ep.IsBorder())
|
||||||
|
{
|
||||||
ep.E()->SetV();
|
ep.E()->SetV();
|
||||||
totalLen += Distance(ep.V()->cP(), ep.VFlip()->cP());
|
totalLen += Distance(ep.V()->cP(), ep.VFlip()->cP());
|
||||||
|
}
|
||||||
|
|
||||||
// Third loop actually perform the sampling.
|
VertexPointer startVertex = ep.V();
|
||||||
|
|
||||||
|
// Third loop actually performs the sampling.
|
||||||
int sampleNum = conservative ? floor(totalLen / radius) : ceil(totalLen / radius);
|
int sampleNum = conservative ? floor(totalLen / radius) : ceil(totalLen / radius);
|
||||||
|
|
||||||
ScalarType sampleDist = totalLen / sampleNum;
|
ScalarType sampleDist = totalLen / sampleNum;
|
||||||
|
|
@ -824,11 +853,11 @@ static void EdgeMeshUniform(MeshType &m, VertexSampler &ps, float radius, bool c
|
||||||
ScalarType curLen = 0;
|
ScalarType curLen = 0;
|
||||||
int sampleCnt = 1;
|
int sampleCnt = 1;
|
||||||
ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 0.0 : 1.0);
|
ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 0.0 : 1.0);
|
||||||
do
|
|
||||||
{
|
do {
|
||||||
ep.NextE();
|
ep.NextE();
|
||||||
assert(ep.E()->IsV());
|
assert(ep.E()->IsV());
|
||||||
ScalarType edgeLen = Distance(ep.V()->cP(), ep.VFlip()->cP());
|
ScalarType edgeLen = Distance(ep.VFlip()->cP(), ep.V()->cP());
|
||||||
ScalarType d0 = curLen;
|
ScalarType d0 = curLen;
|
||||||
ScalarType d1 = d0 + edgeLen;
|
ScalarType d1 = d0 + edgeLen;
|
||||||
|
|
||||||
|
|
@ -843,10 +872,12 @@ static void EdgeMeshUniform(MeshType &m, VertexSampler &ps, float radius, bool c
|
||||||
} while(!ep.IsBorder() && ep.V() != startVertex);
|
} while(!ep.IsBorder() && ep.V() != startVertex);
|
||||||
|
|
||||||
if(ep.V() != startVertex)
|
if(ep.V() != startVertex)
|
||||||
|
{
|
||||||
ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 0.0 : 1.0);
|
ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 0.0 : 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Sample all the border corner vertices
|
/// \brief Sample all the border corner vertices
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,8 @@ protected:
|
||||||
// QElapsedTimer timer;
|
// QElapsedTimer timer;
|
||||||
// timer.start();
|
// timer.start();
|
||||||
|
|
||||||
|
(void)idx;
|
||||||
|
|
||||||
RequireCompactness(original);
|
RequireCompactness(original);
|
||||||
RequirePerFaceFlags(original);
|
RequirePerFaceFlags(original);
|
||||||
|
|
||||||
|
|
@ -295,9 +297,10 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const int manifoldSplits = vcg::tri::Clean<EdgeMeshType>::SplitSelectedVertexOnEdgeMesh(em);
|
const int manifoldSplits = vcg::tri::Clean<EdgeMeshType>::SplitSelectedVertexOnEdgeMesh(em);
|
||||||
// std::cout << manifoldSplits << " non-manifold splits" << std::endl;
|
(void)manifoldSplits;
|
||||||
|
|
||||||
#ifdef DEBUG_VORO
|
#ifdef DEBUG_VORO
|
||||||
|
std::cout << manifoldSplits << " non-manifold splits" << std::endl;
|
||||||
io::ExporterOBJ<EdgeMeshType>::Save(em, QString("edgeMesh_%1.obj").arg(idx).toStdString().c_str(), io::Mask::IOM_EDGEINDEX);
|
io::ExporterOBJ<EdgeMeshType>::Save(em, QString("edgeMesh_%1.obj").arg(idx).toStdString().c_str(), io::Mask::IOM_EDGEINDEX);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -309,11 +312,13 @@ protected:
|
||||||
UpdateFlags<EdgeMeshType>::VertexClearV(em);
|
UpdateFlags<EdgeMeshType>::VertexClearV(em);
|
||||||
Clean<EdgeMeshType>::SelectCreaseVertexOnEdgeMesh(em, vcg::math::ToRad(borderCreaseAngleDeg));
|
Clean<EdgeMeshType>::SelectCreaseVertexOnEdgeMesh(em, vcg::math::ToRad(borderCreaseAngleDeg));
|
||||||
const int splits = Clean<EdgeMeshType>::SplitSelectedVertexOnEdgeMesh(em);
|
const int splits = Clean<EdgeMeshType>::SplitSelectedVertexOnEdgeMesh(em);
|
||||||
// std::cout << splits << " splits" << std::endl;
|
(void)splits;
|
||||||
}
|
|
||||||
#ifdef DEBUG_VORO
|
#ifdef DEBUG_VORO
|
||||||
|
std::cout << splits << " splits" << std::endl;
|
||||||
io::ExporterOBJ<EdgeMeshType>::Save(em, QString("edgeMesh_split_%1.obj").arg(idx).toStdString().c_str(), io::Mask::IOM_EDGEINDEX);
|
io::ExporterOBJ<EdgeMeshType>::Save(em, QString("edgeMesh_split_%1.obj").arg(idx).toStdString().c_str(), io::Mask::IOM_EDGEINDEX);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Samples vector
|
// Samples vector
|
||||||
std::vector<Coord> borderSamples;
|
std::vector<Coord> borderSamples;
|
||||||
|
|
@ -321,7 +326,7 @@ protected:
|
||||||
|
|
||||||
// uniform edge sampling
|
// uniform edge sampling
|
||||||
UpdateTopology<EdgeMeshType>::EdgeEdge(em);
|
UpdateTopology<EdgeMeshType>::EdgeEdge(em);
|
||||||
SurfaceSampling<EdgeMeshType>::EdgeMeshUniform(em, ps, samplingRadius, true);
|
SurfaceSampling<EdgeMeshType>::EdgeMeshUniform(em, ps, samplingRadius, false);
|
||||||
BuildMeshFromCoordVector(poissonEdgeMesh, borderSamples);
|
BuildMeshFromCoordVector(poissonEdgeMesh, borderSamples);
|
||||||
UpdateBounding<Mesh>::Box(poissonEdgeMesh);
|
UpdateBounding<Mesh>::Box(poissonEdgeMesh);
|
||||||
|
|
||||||
|
|
@ -538,10 +543,13 @@ protected:
|
||||||
if (!vit->IsD() && vit->IsB())
|
if (!vit->IsD() && vit->IsB())
|
||||||
borderPts.push_back(vit->cP());
|
borderPts.push_back(vit->cP());
|
||||||
}
|
}
|
||||||
|
if (!borderPts.empty())
|
||||||
|
{
|
||||||
BuildMeshFromCoordVector(borderMesh,borderPts);
|
BuildMeshFromCoordVector(borderMesh,borderPts);
|
||||||
borderMesh.bbox = m.bbox;
|
borderMesh.bbox = m.bbox;
|
||||||
borderHG.Set(borderMesh.vert.begin(), borderMesh.vert.end(), bbox);
|
borderHG.Set(borderMesh.vert.begin(), borderMesh.vert.end(), bbox);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const ScalarType dist_upper_bound=samplingRadius*4;
|
const ScalarType dist_upper_bound=samplingRadius*4;
|
||||||
VertexType * vp = NULL;
|
VertexType * vp = NULL;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue