From c5fcfd94c1182f141d72637e1432c568ef174e26 Mon Sep 17 00:00:00 2001 From: cignoni Date: Tue, 23 Jul 2013 07:32:12 +0000 Subject: [PATCH] Added a MeshSampler Class to the framework as a simple example of the sampling procedure Added another wrapper for montecarlo sampling of points Improved the basic wrapper of poisson disk sampling to include variable disk radius sampling --- vcg/complex/algorithms/point_sampling.h | 71 +++++++++++++++++++++---- 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/vcg/complex/algorithms/point_sampling.h b/vcg/complex/algorithms/point_sampling.h index 0daf2e00..a3811672 100644 --- a/vcg/complex/algorithms/point_sampling.h +++ b/vcg/complex/algorithms/point_sampling.h @@ -40,6 +40,7 @@ sampling strategies (montecarlo, stratified etc). #include #include #include +#include #include #include #include @@ -56,7 +57,6 @@ namespace tri /** \brief An basic sampler class that show the required interface used by the SurfaceSampling class. - Most of the methods of sampling classes call the AddFace method of this class with the face containing the sample and its barycentric coord. Beside being an example of how to write a sampler it provides a simple way to use the various sampling classes. For example if you just want to get a vector with positions over the surface You have just to write @@ -116,6 +116,39 @@ public: }; // end class TrivialSampler + + + +template +class MeshSampler +{ +public: + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::CoordType CoordType; + + MeshSampler(MeshType &_m):m(_m){} + MeshType &m; + + void AddVert(const VertexType &p) + { + tri::Allocator::AddVertices(m,1); + m.vert.back().ImportData(p); + } + + void AddFace(const FaceType &f, CoordType p) + { + tri::Allocator::AddVertices(m,1); + m.vert.back().P() = f.cP(0)*p[0] + f.cP(1)*p[1] +f.cP(2)*p[2]; + m.vert.back().N() = f.cV(0)->N()*p[0] + f.cV(1)->N()*p[1] + f.cV(2)->N()*p[2]; + m.vert.back().Q() = f.cV(0)->Q()*p[0] + f.cV(1)->Q()*p[1] + f.cV(2)->Q()*p[2]; + } +}; // end class BaseSampler + + + + + /** \brief Main Class of the Sampling framework. @@ -1232,6 +1265,9 @@ static int ComputePoissonSampleNum(MetroMesh &origMesh, ScalarType diskRadius) return sampleNum; } +// Note that this function actually CHANGE the quality of the montecarlo samples so that it represents the expected radius of each sample +// the expected radius of the sample is computed so that it linearly maps the quality between diskradius / variance and diskradius*variance + static void ComputePoissonSampleRadii(MetroMesh &sampleMesh, ScalarType diskRadius, ScalarType radiusVariance, bool invert) { VertexIterator vi; @@ -1270,6 +1306,7 @@ static void PoissonDiskPruning(VertexSampler &ps, MetroMesh &montecarloMesh, if(pp.pds) pp.pds->gridSize = gridsize; // if we are doing variable density sampling we have to prepare the random samples quality with the correct expected radii. + // At this point we just assume that there is the quality values as sampled from the base mesh if(pp.adaptiveRadiusFlag) ComputePoissonSampleRadii(montecarloMesh, diskRadius, pp.radiusVariance, pp.invertQuality); @@ -1542,6 +1579,16 @@ static void SubdivideAndSample(MetroMesh & m, std::vector &pvec, const }; // end class +template +void MontecarloSampling(MeshType &m, // the mesh that has to be sampled + MeshType &mm, // the mesh that will contain the samples + int sampleNum) // the desired number sample, if zero you must set the radius to the wanted value +{ + typedef tri::MeshSampler BaseSampler; + MeshSampler mcSampler(&mm); + tri::SurfaceSampling::Montecarlo(m, mcSampler, sampleNum); +} + template void MontecarloSampling(MeshType &m, // the mesh that has to be sampled @@ -1559,9 +1606,13 @@ template void PoissonSampling(MeshType &m, // the mesh that has to be sampled std::vector &poissonSamples, // the vector that will contain the set of points int sampleNum, // the desired number sample, if zero you must set the radius to the wanted value - float &radius) // the Poisson Disk Radius (used if sampleNum==0, setted if sampleNum!=0) + float &radius, // the Poisson Disk Radius (used if sampleNum==0, setted if sampleNum!=0) + float radiusVariance=1) + { typedef tri::TrivialSampler BaseSampler; + typedef tri::MeshSampler MontecarloSampler; + typename tri::SurfaceSampling::PoissonDiskParam pp; typename tri::SurfaceSampling::PoissonDiskParam::Stat stat; pp.pds = &stat; @@ -1572,22 +1623,24 @@ void PoissonSampling(MeshType &m, // the mesh that has to be sampled pp.pds->sampleNum = sampleNum; poissonSamples.clear(); - std::vector MontecarloSamples; +// std::vector MontecarloSamples; MeshType MontecarloMesh; // First step build the sampling - BaseSampler mcSampler(MontecarloSamples); + MontecarloSampler mcSampler(MontecarloMesh); BaseSampler pdSampler(poissonSamples); - tri::SurfaceSampling::Montecarlo(m, mcSampler, std::max(10000,sampleNum*40)); - - tri::Allocator::AddVertices(MontecarloMesh,MontecarloSamples.size()); - for(size_t i=0;i::Montecarlo(m, mcSampler, std::max(10000,sampleNum*40)); tri::UpdateBounding::Box(MontecarloMesh); +// tri::Build(MontecarloMesh, MontecarloSamples); int t1=clock(); pp.pds->montecarloTime = t1-t0; + if(radiusVariance !=1) + { + pp.adaptiveRadiusFlag=true; + pp.radiusVariance=radiusVariance; + } tri::SurfaceSampling::PoissonDiskPruning(pdSampler, MontecarloMesh, radius,pp); int t2=clock(); pp.pds->totalTime = t2-t0;