fix for voronoi remesher, again

This commit is contained in:
Luigi Malomo 2017-07-17 20:39:04 +02:00
parent 30dcc87c1a
commit 75eca5e231
3 changed files with 674 additions and 709 deletions

View File

@ -62,14 +62,23 @@ int main( int argc, char **argv )
return -1; return -1;
} }
printf("Reading %s \n",argv[1]); printf("Reading %s \n",argv[1]);
int ret= tri::io::Importer<MyMesh>::Open(startMesh,argv[1]); int ret = tri::io::Importer<MyMesh>::Open(startMesh,argv[1]);
if(ret!=0) if(ret!=0)
{ {
printf("Unable to open %s for '%s'\n",argv[1],tri::io::ImporterPLY<MyMesh>::ErrorMsg(ret)); printf("Unable to open %s: '%s'\n",argv[1],tri::io::ImporterPLY<MyMesh>::ErrorMsg(ret));
return -1; return -1;
} }
float samplingRadius = startMesh.bbox.Diag() *0.02f; tri::UpdateBounding<MyMesh>::Box(startMesh);
auto remeshed = Remesher<MyMesh>::Remesh(startMesh, samplingRadius, 50.0);
float samplingRadius = startMesh.bbox.Diag() * 0.01f;
if (argc == 3)
{
try {
samplingRadius = stof(string(argv[2]));
} catch (exception &) {}
}
std::cout << "using sampling radius: " << samplingRadius << std::endl;
auto remeshed = Remesher<MyMesh>::Remesh(startMesh, samplingRadius, 75.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 );

View File

@ -1260,7 +1260,7 @@ static int RestrictedVoronoiRelaxing(MeshType &m, std::vector<CoordType> &seedPo
if(sumVec[i].first != 0) if(sumVec[i].first != 0)
{ {
newseedVec.push_back(sumVec[i].second /ScalarType(sumVec[i].first)); newseedVec.push_back(sumVec[i].second /ScalarType(sumVec[i].first));
if(vpp.seedPerturbationProbability > RandomGenerator().generate01()) if(vpp.seedPerturbationProbability > 0 && (vpp.seedPerturbationProbability > RandomGenerator().generate01()))
newseedVec.back()+=math::GeneratePointInUnitBallUniform<ScalarType,math::MarsenneTwisterRNG>( RandomGenerator())*perturb; newseedVec.back()+=math::GeneratePointInUnitBallUniform<ScalarType,math::MarsenneTwisterRNG>( RandomGenerator())*perturb;
newfixedVec.push_back(false); newfixedVec.push_back(false);
} }

View File

@ -2,7 +2,7 @@
* VCGLib o o * * VCGLib o o *
* Visual and Computer Graphics Library o o * * Visual and Computer Graphics Library o o *
* _ O _ * * _ O _ *
* Copyright(C) 2004-2016 \/)\/ * * Copyright(C) 2004-2017 \/)\/ *
* Visual Computing Lab /\/| * * Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | * * ISTI - Italian National Research Council | *
* \ * * \ *
@ -43,9 +43,14 @@
#include <array> #include <array>
#include <utility> #include <utility>
#define DEBUG_VORO 1
//#define DEBUG_VORO 1
//#include <QElapsedTimer>
#ifdef DEBUG_VORO
#include <wrap/io_trimesh/export.h> #include <wrap/io_trimesh/export.h>
#include <QString> #include <QString>
#endif
namespace vcg { namespace vcg {
namespace tri { namespace tri {
@ -139,13 +144,13 @@ public:
/// ///
static inline MeshPtr Remesh(Mesh & original, const ScalarType samplingRadius, const ScalarType borderCreaseAngleDeg = 0.0) static inline MeshPtr Remesh(Mesh & original, const ScalarType samplingRadius, const ScalarType borderCreaseAngleDeg = 0.0)
{ {
RequireFFAdjacency(original);
RequireVFAdjacency(original);
UpdateTopology<Mesh>::FaceFace(original); UpdateTopology<Mesh>::FaceFace(original);
UpdateFlags<Mesh>::FaceBorderFromFF(original); UpdateFlags<Mesh>::FaceBorderFromFF(original);
UpdateFlags<Mesh>::VertexBorderFromFaceAdj(original); UpdateFlags<Mesh>::VertexBorderFromFaceAdj(original);
RequireFFAdjacency(original);
RequireVFAdjacency(original);
if (Clean<Mesh>::CountNonManifoldEdgeFF(original) > 0) if (Clean<Mesh>::CountNonManifoldEdgeFF(original) > 0)
{ {
std::cout << "Input mesh has non manifold edges" << std::endl; std::cout << "Input mesh has non manifold edges" << std::endl;
@ -159,8 +164,8 @@ public:
UpdateFlags<Mesh>::FaceBorderFromFF(original); UpdateFlags<Mesh>::FaceBorderFromFF(original);
UpdateFlags<Mesh>::VertexBorderFromFaceAdj(original); UpdateFlags<Mesh>::VertexBorderFromFaceAdj(original);
// Mark the non manifold border vertices as visited on the original mesh // Mark the non manifold border vertices as visited on the input mesh
// tri::UpdateColor<Mesh>::PerVertexConstant(original); // TODO maybe optimize this
{ {
// extract border mesh // extract border mesh
EdgeMeshType em; EdgeMeshType em;
@ -186,13 +191,13 @@ public:
// iterate over the mesh and mark as visited all the matching vertices with the non manifold border // iterate over the mesh and mark as visited all the matching vertices with the non manifold border
tri::UpdateBounding<EdgeMeshType>::Box(em); tri::UpdateBounding<EdgeMeshType>::Box(em);
EdgeMeshType::BoxType bbox = em.bbox; EdgeMeshType::BoxType bbox = em.bbox;
bbox.Offset(bbox.Diag()/4.0); bbox.Offset(bbox.Diag()/1000.0);
typedef SpatialHashTable<EdgeMeshType::VertexType, EdgeMeshType::ScalarType> HashVertexGrid; typedef SpatialHashTable<EdgeMeshType::VertexType, EdgeMeshType::ScalarType> HashVertexGrid;
HashVertexGrid HG; HashVertexGrid HG;
HG.Set(em.vert.begin(), em.vert.end(), bbox); HG.Set(em.vert.begin(), em.vert.end(), bbox);
typedef EdgeMeshType::CoordType Coord; typedef EdgeMeshType::CoordType Coord;
EdgeMeshType::ScalarType dist_upper_bound = bbox.Diag()/100.0; EdgeMeshType::ScalarType dist_upper_bound = bbox.Diag()/1000.0;
for (VertexType & v : original.vert) for (VertexType & v : original.vert)
{ {
EdgeMeshType::ScalarType dist; EdgeMeshType::ScalarType dist;
@ -200,29 +205,27 @@ public:
if (nonManifoldVertex != NULL && dist == 0) if (nonManifoldVertex != NULL && dist == 0)
{ {
v.SetV(); v.SetV();
// v.C() = vcg::Color4b::Black;
} }
} }
} }
} }
#ifdef DEBUG_VORO #ifdef DEBUG_VORO
io::Exporter<Mesh>::Save(original, "creaseSplit.ply", io::Mask::IOM_VERTCOLOR); io::Exporter<Mesh>::Save(original, "creaseSplit.ply", io::Mask::IOM_VERTCOLOR);
#endif #endif
// }
// One CC // One CC
std::vector<MeshPtr> ccs = splitCC(original); std::vector<MeshPtr> ccs = splitCC(original);
if (ccs.empty()) if (ccs.empty())
{
return RemeshOneCC(original, samplingRadius, borderCreaseAngleDeg); return RemeshOneCC(original, samplingRadius, borderCreaseAngleDeg);
}
// Multiple CCs // Multiple CCs
std::cout << "Remeshing " << ccs.size() << " components" << std::endl; // std::cout << "Remeshing " << ccs.size() << " components" << std::endl;
for (size_t i=0; i<ccs.size(); i++) for (size_t i=0; i<ccs.size(); i++)
{ {
std::cout << "Remeshing component " << (i+1) << "/" << ccs.size() << std::endl; // std::cout << "Remeshing component " << (i+1) << "/" << ccs.size() << std::endl;
ccs[i] = RemeshOneCC(*ccs[i], samplingRadius, borderCreaseAngleDeg, i); ccs[i] = RemeshOneCC(*ccs[i], samplingRadius, borderCreaseAngleDeg, i);
} }
@ -238,12 +241,21 @@ public:
/// ///
/// \brief RemeshOneCC the function that remeshes a single connected component mesh preserving its boundary (consistently for eventually adjacent meshes). /// \brief RemeshOneCC the function that remeshes a single connected component mesh preserving its boundary (consistently for eventually adjacent meshes).
/// \param original the mesh /// \param original the mesh
/// \param samplingRadius is the sampling ragius for remeshing /// \param samplingRadius is the sampling radius for remeshing
/// \param borderCreaseAngleDeg is the angle treshold for preserving corner points on the mesh boundary /// \param borderCreaseAngleDeg is the angle treshold for preserving corner points on the mesh boundary
/// \return the remeshed mesh /// \return the remeshed mesh
/// ///
static inline MeshPtr RemeshOneCC(Mesh & original, const ScalarType samplingRadius, const ScalarType borderCreaseAngleDeg = 0.0, int idx = 0) static inline MeshPtr RemeshOneCC(Mesh & original, const ScalarType samplingRadius, const ScalarType borderCreaseAngleDeg = 0.0, int idx = 0)
{ {
// double timeBorders = 0;
// double timePoisson = 0;
// double timeRelax = 0;
// double timeSeed = 0;
// double timeSources = 0;
// double timeDelaunay = 0;
// QElapsedTimer timer;
// timer.start();
RequireCompactness(original); RequireCompactness(original);
RequirePerFaceFlags(original); RequirePerFaceFlags(original);
@ -251,6 +263,9 @@ public:
UpdateFlags<Mesh>::FaceBorderFromFF(original); UpdateFlags<Mesh>::FaceBorderFromFF(original);
UpdateFlags<Mesh>::VertexBorderFromFaceAdj(original); UpdateFlags<Mesh>::VertexBorderFromFaceAdj(original);
#ifdef DEBUG_VORO
io::ExporterPLY<MeshType>::Save(original, QString("cc_%1.ply").arg(idx).toStdString().c_str(), io::Mask::IOM_VERTCOLOR);
#endif
// Resample border // Resample border
Mesh poissonEdgeMesh; Mesh poissonEdgeMesh;
@ -270,7 +285,8 @@ public:
if (v.IsV()) { v.SetS(); } if (v.IsV()) { v.SetS(); }
} }
} }
std::cout << vcg::tri::Clean<EdgeMeshType>::SplitSelectedVertexOnEdgeMesh(em) << " non-manifold splits" << std::endl; const int manifoldSplits = vcg::tri::Clean<EdgeMeshType>::SplitSelectedVertexOnEdgeMesh(em);
// std::cout << manifoldSplits << " non-manifold splits" << std::endl;
#ifdef DEBUG_VORO #ifdef DEBUG_VORO
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);
@ -283,7 +299,8 @@ public:
UpdateFlags<EdgeMeshType>::VertexClearS(em); UpdateFlags<EdgeMeshType>::VertexClearS(em);
UpdateFlags<EdgeMeshType>::VertexClearV(em); UpdateFlags<EdgeMeshType>::VertexClearV(em);
Clean<EdgeMeshType>::SelectCreaseVertexOnEdgeMesh(em, vcg::math::ToRad(borderCreaseAngleDeg)); Clean<EdgeMeshType>::SelectCreaseVertexOnEdgeMesh(em, vcg::math::ToRad(borderCreaseAngleDeg));
std::cout << Clean<EdgeMeshType>::SplitSelectedVertexOnEdgeMesh(em) << " splits" << std::endl; const int splits = Clean<EdgeMeshType>::SplitSelectedVertexOnEdgeMesh(em);
// std::cout << splits << " splits" << std::endl;
} }
#ifdef DEBUG_VORO #ifdef DEBUG_VORO
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);
@ -293,7 +310,7 @@ public:
std::vector<Coord> borderSamples; std::vector<Coord> borderSamples;
TrivialSampler<EdgeMeshType> ps(borderSamples); TrivialSampler<EdgeMeshType> ps(borderSamples);
// uniform 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, true);
BuildMeshFromCoordVector(poissonEdgeMesh, borderSamples); BuildMeshFromCoordVector(poissonEdgeMesh, borderSamples);
@ -311,6 +328,8 @@ public:
#endif #endif
} }
// timeBorders = timer.restart() / 1000.0;
typedef VoronoiProcessing<Mesh> Voronoi; typedef VoronoiProcessing<Mesh> Voronoi;
typedef TrivialSampler<Mesh> BaseSampler; typedef TrivialSampler<Mesh> BaseSampler;
typedef SurfaceSampling<Mesh, BaseSampler> SurfaceSampler; typedef SurfaceSampling<Mesh, BaseSampler> SurfaceSampler;
@ -326,7 +345,6 @@ public:
Voronoi::PreprocessForVoronoi(baseMesh, samplingRadius, vpp); Voronoi::PreprocessForVoronoi(baseMesh, samplingRadius, vpp);
// Poisson sampling preserving border // Poisson sampling preserving border
Mesh poissonMesh;
std::vector<CoordType> seedPointVec; std::vector<CoordType> seedPointVec;
std::vector<bool> seedFixedVec; std::vector<bool> seedFixedVec;
FixSampler fix_sampler(seedPointVec, seedFixedVec); FixSampler fix_sampler(seedPointVec, seedFixedVec);
@ -335,19 +353,17 @@ public:
std::vector<CoordType> sampleVec; std::vector<CoordType> sampleVec;
BaseSampler mps(sampleVec); BaseSampler mps(sampleVec);
// NOTE in order to make results always the same the random sampling generator is reinitialized for // NOTE in order to make the results consistent the random sampling generator is initialized with the same value
// for each patch resampling
SurfaceSampler::SamplingRandomGenerator().initialize(5489u); SurfaceSampler::SamplingRandomGenerator().initialize(5489u);
// Montecarlo oversampling // Montecarlo oversampling
Mesh montecarloMesh; Mesh montecarloMesh;
int poissonCount = SurfaceSampler::ComputePoissonSampleNum(original, samplingRadius) * 0.7; int poissonCount = SurfaceSampler::ComputePoissonSampleNum(original, samplingRadius) * 0.7;
std::cout << "poisson Count: " << poissonCount << std::endl; // std::cout << "poisson Count: " << poissonCount << std::endl;
if (poissonCount <= 0) if (poissonCount <= 0)
{ {
// no need for internal sampling // no need for internal sampling
Append<Mesh, Mesh>::MeshCopy(poissonMesh, poissonEdgeMesh);
for (auto vi = poissonEdgeMesh.vert.begin(); vi != poissonEdgeMesh.vert.end(); vi++) for (auto vi = poissonEdgeMesh.vert.begin(); vi != poissonEdgeMesh.vert.end(); vi++)
{ {
fix_sampler.AddVert(*vi); fix_sampler.AddVert(*vi);
@ -369,18 +385,26 @@ public:
pp.preGenFlag = true; pp.preGenFlag = true;
SurfaceFixSampler::PoissonDiskPruning(fix_sampler, montecarloMesh, samplingRadius, pp); SurfaceFixSampler::PoissonDiskPruning(fix_sampler, montecarloMesh, samplingRadius, pp);
}
#ifdef DEBUG_VORO #ifdef DEBUG_VORO
Mesh poissonMesh;
BuildMeshFromCoordVector(poissonMesh,seedPointVec); BuildMeshFromCoordVector(poissonMesh,seedPointVec);
io::ExporterPLY<MeshType>::Save(poissonMesh, QString("poissonMesh_%1.ply").arg(idx).toStdString().c_str()); io::ExporterPLY<MeshType>::Save(poissonMesh, QString("poissonMesh_%1.ply").arg(idx).toStdString().c_str());
#endif #endif
// timePoisson = timer.restart() / 1000.0;
// std::cout << "poisson samples " << seedPointVec.size() << std::endl;
// not enough points
if (seedPointVec.size() < 3)
{
return std::make_shared<Mesh>();
} }
std::cout << "poisson samples " << seedPointVec.size() << std::endl;
// restricted relaxation with fixed points // restricted relaxation with fixed points
vpp.seedPerturbationProbability = 0.0f; vpp.seedPerturbationProbability = 0.0f;
// TODO check preserveFixedSeed flag (NO)
Voronoi::RestrictedVoronoiRelaxing(baseMesh, seedPointVec, seedFixedVec, VoroRelaxationStep, vpp); Voronoi::RestrictedVoronoiRelaxing(baseMesh, seedPointVec, seedFixedVec, VoroRelaxationStep, vpp);
#ifdef DEBUG_VORO #ifdef DEBUG_VORO
@ -388,24 +412,39 @@ public:
io::ExporterPLY<MeshType>::Save(poissonMesh, QString("relaxedMesh_%1.ply").arg(idx).toStdString().c_str()); io::ExporterPLY<MeshType>::Save(poissonMesh, QString("relaxedMesh_%1.ply").arg(idx).toStdString().c_str());
#endif #endif
// timeRelax = timer.restart() / 1000.0;
// FAIL? // FAIL?
MeshPtr finalMeshPtr = std::make_shared<Mesh>(); MeshPtr finalMeshPtr = std::make_shared<Mesh>();
std::vector<VertexType *> seedVertexVec; std::vector<VertexType *> seedVertexVec;
// Voronoi::SeedToVertexConversion(baseMesh, seedPointVec, seedVertexVec, false); // Voronoi::SeedToVertexConversion(baseMesh, seedPointVec, seedVertexVec, false);
ThisType::SeedToFixedBorderVertexConversion(baseMesh, seedPointVec, seedFixedVec, seedVertexVec); ThisType::SeedToFixedBorderVertexConversion(baseMesh, samplingRadius, seedPointVec, seedFixedVec, seedVertexVec);
EuclideanDistance<Mesh> dd; EuclideanDistance<Mesh> dd;
std::cout << "BEGIN compute vertex sources (basemesh vn:" << baseMesh.VN() << " fn:" << baseMesh.FN() << ")" << std::endl; // timeSeed = timer.restart() / 1000.0;
// std::cout << "BEGIN compute vertex sources (basemesh vn:" << baseMesh.VN() << " fn:" << baseMesh.FN() << ")" << std::endl;
Voronoi::ComputePerVertexSources(baseMesh, seedVertexVec, dd); Voronoi::ComputePerVertexSources(baseMesh, seedVertexVec, dd);
std::cout << "END compute vertex sources" << std::endl; // std::cout << "END compute vertex sources" << std::endl;
// Voronoi::ConvertDelaunayTriangulationToMesh(baseMesh, *finalMeshPtr, seedVertexVec, false); // traditional // timeSources = timer.restart() / 1000.0;
ThisType::ConvertDelaunayTriangulationExtendedToMesh(baseMesh, *finalMeshPtr, seedVertexVec); // border-preserving // traditional
// Voronoi::ConvertDelaunayTriangulationToMesh(baseMesh, *finalMeshPtr, seedVertexVec, false);
// border-preserving
ThisType::ConvertDelaunayTriangulationExtendedToMesh(baseMesh, *finalMeshPtr, seedVertexVec);
#ifdef DEBUG_VORO #ifdef DEBUG_VORO
io::ExporterPLY<MeshType>::Save(*finalMeshPtr, QString("voroMesh_%1.ply").arg(idx).toStdString().c_str()); io::ExporterPLY<MeshType>::Save(*finalMeshPtr, QString("voroMesh_%1.ply").arg(idx).toStdString().c_str());
io::ExporterPLY<MeshType>::Save(baseMesh, QString("baseMesh_%1.ply").arg(idx).toStdString().c_str(), io::Mask::IOM_VERTCOLOR); io::ExporterPLY<MeshType>::Save(baseMesh, QString("baseMesh_%1.ply").arg(idx).toStdString().c_str(), io::Mask::IOM_VERTCOLOR);
#endif #endif
// timeDelaunay = timer.elapsed() / 1000.0;
// std::cout << "border: " << timeBorders << std::endl
// << "poisson: " << timePoisson << std::endl
// << "relax: " << timeRelax << std::endl
// << "seed: " << timeSeed << std::endl
// << "sources: " << timeSources << std::endl
// << "delaunay: " << timeDelaunay << std::endl;
return finalMeshPtr; return finalMeshPtr;
} }
@ -461,89 +500,8 @@ protected:
Clean<EdgeMeshType>::RemoveDuplicateVertex(sides); Clean<EdgeMeshType>::RemoveDuplicateVertex(sides);
} }
///
/// \brief ExtractMeshSides
/// \param mesh the mesh (topology already computed)
/// \param sides the edge mesh filled with the extracted borders
///
static inline void ExtractMeshSides(Mesh & mesh, EdgeMeshType & sides)
{
// TODO change this.... maybe wrong
RequireFFAdjacency(mesh);
RequireVFAdjacency(mesh);
// clean the edge mesh containing the borders
sides.Clear();
// find a border edge
assert(Clean<Mesh>::CountHoles(mesh) >= 1);
PosType pos;
for (auto fi = mesh.face.begin(); fi != mesh.face.end() && pos.IsNull(); fi++)
{
for (int e=0; e<fi->VN(); e++)
{
if (vcg::face::IsBorder(*fi, e))
{
pos = PosType(&(*fi), e);
break;
}
}
}
assert(!pos.IsNull());
assert(pos.IsBorder());
// navigate to a corner
VertexType * v = pos.V();
do
{
pos.NextB();
} while(!pos.V()->IsV() && pos.V() != v);
// if it's a loop mark the initial point as a corner
pos.V()->SetV();
v = pos.V();
// gather into separate vertices lists
std::vector<std::vector<VertexType *> > edges;
std::vector<VertexType *> edgePtrVec;
do
{
edgePtrVec.push_back(pos.V());
pos.NextB();
if (pos.V()->IsV())
{
edgePtrVec.push_back(pos.V());
edges.push_back(edgePtrVec);
edgePtrVec.clear();
}
} while (pos.V() != v);
// convert to edge mesh
for (auto & e : edges)
{
assert(e.size() >= 2);
std::vector<typename EdgeMeshType::VertexType *> newVtx;
// insert new vertices and store their pointer
auto vi = Allocator<EdgeMeshType>::AddVertices(sides, e.size());
for (const auto & v : e)
{
vi->ImportData(*v);
newVtx.push_back(&(*vi++));
}
auto ei = Allocator<EdgeMeshType>::AddEdges(sides, e.size() - 1);
for (int i=0; i<static_cast<int>(e.size() - 1); i++)
{
ei->V(0) = newVtx[i];
ei->V(1) = newVtx[i+1];
ei++;
}
}
}
static void SeedToFixedBorderVertexConversion(MeshType & m, static void SeedToFixedBorderVertexConversion(MeshType & m,
const ScalarType samplingRadius,
const std::vector<CoordType> & seedPVec, const std::vector<CoordType> & seedPVec,
const std::vector<bool> & seedFixed, const std::vector<bool> & seedFixed,
std::vector<VertexType *> & seedVVec) std::vector<VertexType *> & seedVVec)
@ -555,7 +513,7 @@ protected:
UpdateFlags<MeshType>::VertexBorderFromFaceAdj(m); UpdateFlags<MeshType>::VertexBorderFromFaceAdj(m);
typename MeshType::BoxType bbox = m.bbox; typename MeshType::BoxType bbox = m.bbox;
bbox.Offset(bbox.Diag()/4.0); bbox.Offset(bbox.Diag()/100.0);
// internal vertices grid // internal vertices grid
HashVertexGrid HG; HashVertexGrid HG;
@ -577,7 +535,7 @@ protected:
borderHG.Set(borderMesh.vert.begin(), borderMesh.vert.end(), bbox); borderHG.Set(borderMesh.vert.begin(), borderMesh.vert.end(), bbox);
} }
const float dist_upper_bound=m.bbox.Diag()/4.0; const ScalarType dist_upper_bound=samplingRadius*4;
VertexType * vp = NULL; VertexType * vp = NULL;
for( size_t i = 0; i < seedPVec.size(); i++) for( size_t i = 0; i < seedPVec.size(); i++)
@ -606,7 +564,7 @@ protected:
std::vector<VertexType *> vps; std::vector<VertexType *> vps;
std::vector<CoordType> pts; std::vector<CoordType> pts;
// vp = GetClosestVertex<MeshType,HashVertexGrid>(m, HG, borderVp->cP(), dist_upper_bound, dist); // vp = GetClosestVertex<MeshType,HashVertexGrid>(m, HG, borderVp->cP(), dist_upper_bound, dist);
unsigned int n = GetKClosestVertex<MeshType,HashVertexGrid>(m, HG, 16, borderVp->cP(), dist_upper_bound, vps, dist, pts); unsigned int n = GetKClosestVertex<MeshType,HashVertexGrid>(m, HG, 16, borderVp->cP(), dist_upper_bound, vps, dist, pts);
if (n>0) if (n>0)
{ {
@ -662,6 +620,7 @@ protected:
} }
// Now just add one face for each inner corner // Now just add one face for each inner corner
std::vector<std::array<VertexPointer, 3> > toAdd;
for(size_t i=0; i<innerCornerVec.size(); ++i) for(size_t i=0; i<innerCornerVec.size(); ++i)
{ {
VertexPointer s0 = sources[innerCornerVec[i]->V(0)]; VertexPointer s0 = sources[innerCornerVec[i]->V(0)];
@ -671,7 +630,7 @@ protected:
VertexPointer v0 = & outMesh.vert[seedMap[s0]]; VertexPointer v0 = & outMesh.vert[seedMap[s0]];
VertexPointer v1 = & outMesh.vert[seedMap[s1]]; VertexPointer v1 = & outMesh.vert[seedMap[s1]];
VertexPointer v2 = & outMesh.vert[seedMap[s2]]; VertexPointer v2 = & outMesh.vert[seedMap[s2]];
Allocator<MeshType>::AddFace(outMesh, v0, v1, v2 ); Allocator<MeshType>::AddFace(outMesh, v0, v1, v2);
} }
// Now loop around the borders and find the missing delaunay triangles // Now loop around the borders and find the missing delaunay triangles
@ -720,10 +679,7 @@ protected:
pos.V()->SetV(); pos.V()->SetV();
// assert(edgeVoroVertices.size() >= 2); // assert(edgeVoroVertices.size() >= 2);
// TODO
// 1) handle 5 vertices holes
// 2) make coherent split/border-sampling on different connected components (e.g., left eye raptor50k)
if (edgeVoroVertices.size() >= 3) if (edgeVoroVertices.size() >= 3)
@ -733,14 +689,15 @@ protected:
{ {
v.push_back(&outMesh.vert[seedMap[edgeVoroVertices[i]]]); v.push_back(&outMesh.vert[seedMap[edgeVoroVertices[i]]]);
} }
// also handles N>3 vertices holes
for (size_t i=0; i<edgeVoroVertices.size()-2; i++) for (size_t i=0; i<edgeVoroVertices.size()-2; i++)
{ {
Allocator<MeshType>::AddFace(outMesh, v[0],v[i+1],v[i+2]); Allocator<MeshType>::AddFace(outMesh, v[0],v[i+1],v[i+2]);
} }
if (edgeVoroVertices.size() > 3) // if (edgeVoroVertices.size() > 3)
{ // {
std::cout << "Weird case!! " << edgeVoroVertices.size() << " voroseeds on one border" << std::endl; // std::cout << "Weird case: " << edgeVoroVertices.size() << " voroseeds on one border" << std::endl;
} // }
} }
// // add face if 3 different voronoi regions are crossed by the edge // // add face if 3 different voronoi regions are crossed by the edge
// if (edgeVoroVertices.size() == 3) // if (edgeVoroVertices.size() == 3)
@ -782,8 +739,7 @@ protected:
typedef typename MeshType::CoordType CoordType; typedef typename MeshType::CoordType CoordType;
typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexType VertexType;
FixSampler(std::vector<CoordType> & samples, FixSampler(std::vector<CoordType> & samples, std::vector<bool> & fixed)
std::vector<bool> & fixed)
: sampleVec(samples) : sampleVec(samples)
, fixedVec (fixed) , fixedVec (fixed)
{ {