Slight change of the PoissonDiskPruning interface. Removed a useless parameter (the original surface mesh)

This commit is contained in:
Paolo Cignoni 2013-03-01 08:34:33 +00:00
parent 0f34456c92
commit d61c5c24a1
1 changed files with 223 additions and 222 deletions

View File

@ -67,7 +67,7 @@ class TrivialSampler
public: public:
typedef typename MeshType::CoordType CoordType; typedef typename MeshType::CoordType CoordType;
typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexType VertexType;
typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FaceType FaceType;
TrivialSampler() TrivialSampler()
{ {
@ -101,11 +101,11 @@ class TrivialSampler
sampleVec->push_back(f.cP(0)*p[0] + f.cP(1)*p[1] +f.cP(2)*p[2] ); sampleVec->push_back(f.cP(0)*p[0] + f.cP(1)*p[1] +f.cP(2)*p[2] );
} }
void AddTextureSample(const FaceType &, const CoordType &, const Point2i &, float ) void AddTextureSample(const FaceType &, const CoordType &, const Point2i &, float )
{ {
// Retrieve the color of the sample from the face f using the barycentric coord p // Retrieve the color of the sample from the face f using the barycentric coord p
// and write that color in a texture image at position <tp[0], texHeight-tp[1]> // and write that color in a texture image at position <tp[0], texHeight-tp[1]>
// if edgeDist is > 0 then the corrisponding point is affecting face color even if outside the face area (in texture space) // if edgeDist is > 0 then the corrisponding point is affecting face color even if outside the face area (in texture space)
} }
}; // end class TrivialSampler }; // end class TrivialSampler
@ -147,7 +147,7 @@ static unsigned int RandomInt(unsigned int i)
// Returns a random number in the [0,1) real interval using the improved Marsenne-Twister method. // Returns a random number in the [0,1) real interval using the improved Marsenne-Twister method.
static double RandomDouble01() static double RandomDouble01()
{ {
return SamplingRandomGenerator().generate01(); return SamplingRandomGenerator().generate01();
} }
static Point3f RandomPoint3fBall01() static Point3f RandomPoint3fBall01()
@ -419,11 +419,11 @@ static void AllFace(MetroMesh & m, VertexSampler &ps)
static void AllEdge(MetroMesh & m, VertexSampler &ps) static void AllEdge(MetroMesh & m, VertexSampler &ps)
{ {
// Edge sampling. // Edge sampling.
typedef typename UpdateTopology<MetroMesh>::PEdge SimpleEdge; typedef typename UpdateTopology<MetroMesh>::PEdge SimpleEdge;
std::vector< SimpleEdge > Edges; std::vector< SimpleEdge > Edges;
typename std::vector< SimpleEdge >::iterator ei; typename std::vector< SimpleEdge >::iterator ei;
UpdateTopology<MetroMesh>::FillUniqueEdgeVector(m,Edges); UpdateTopology<MetroMesh>::FillUniqueEdgeVector(m,Edges);
for(ei=Edges.begin(); ei!=Edges.end(); ++ei) for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
{ {
@ -442,7 +442,7 @@ static void EdgeUniform(MetroMesh & m, VertexSampler &ps,int sampleNum, bool sam
{ {
typedef typename UpdateTopology<MetroMesh>::PEdge SimpleEdge; typedef typename UpdateTopology<MetroMesh>::PEdge SimpleEdge;
std::vector< SimpleEdge > Edges; std::vector< SimpleEdge > Edges;
UpdateTopology<MetroMesh>::FillUniqueEdgeVector(m,Edges,sampleFauxEdge); UpdateTopology<MetroMesh>::FillUniqueEdgeVector(m,Edges,sampleFauxEdge);
// First loop compute total edge length; // First loop compute total edge length;
float edgeSum=0; float edgeSum=0;
typename std::vector< SimpleEdge >::iterator ei; typename std::vector< SimpleEdge >::iterator ei;
@ -606,7 +606,7 @@ static void WeightedMontecarlo(MetroMesh & m, VertexSampler &ps, int sampleNum)
double floatSampleNum = 0.0; double floatSampleNum = 0.0;
for(fi=m.face.begin(); fi != m.face.end(); fi++) for(fi=m.face.begin(); fi != m.face.end(); fi++)
if(!(*fi).IsD()) if(!(*fi).IsD())
{ {
// compute # samples in the current face (taking into account of the remainders) // compute # samples in the current face (taking into account of the remainders)
floatSampleNum += WeightedArea(*fi) * samplePerAreaUnit; floatSampleNum += WeightedArea(*fi) * samplePerAreaUnit;
int faceSampleNum = (int) floatSampleNum; int faceSampleNum = (int) floatSampleNum;
@ -615,7 +615,7 @@ static void WeightedMontecarlo(MetroMesh & m, VertexSampler &ps, int sampleNum)
for(int i=0; i < faceSampleNum; i++) for(int i=0; i < faceSampleNum; i++)
ps.AddFace(*fi,RandomBarycentric()); ps.AddFace(*fi,RandomBarycentric());
floatSampleNum -= (double) faceSampleNum; floatSampleNum -= (double) faceSampleNum;
} }
} }
@ -693,20 +693,20 @@ static void FaceSubdivision(MetroMesh & m, VertexSampler &ps,int sampleNum, bool
vcg::tri::UpdateNormal<MetroMesh>::PerFaceNormalized(m); vcg::tri::UpdateNormal<MetroMesh>::PerFaceNormalized(m);
double floatSampleNum = 0.0; double floatSampleNum = 0.0;
int faceSampleNum; int faceSampleNum;
// Subdivision sampling. // Subdivision sampling.
typename std::vector<FacePointer>::iterator fi; typename std::vector<FacePointer>::iterator fi;
for(fi=faceVec.begin(); fi!=faceVec.end(); fi++) for(fi=faceVec.begin(); fi!=faceVec.end(); fi++)
{ {
const CoordType b0(1.0, 0.0, 0.0); const CoordType b0(1.0, 0.0, 0.0);
const CoordType b1(0.0, 1.0, 0.0); const CoordType b1(0.0, 1.0, 0.0);
const CoordType b2(0.0, 0.0, 1.0); const CoordType b2(0.0, 0.0, 1.0);
// compute # samples in the current face. // compute # samples in the current face.
floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit; floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit;
faceSampleNum = (int) floatSampleNum; faceSampleNum = (int) floatSampleNum;
if(faceSampleNum>0) if(faceSampleNum>0)
faceSampleNum = SingleFaceSubdivision(faceSampleNum,b0,b1,b2,ps,*fi,randSample); faceSampleNum = SingleFaceSubdivision(faceSampleNum,b0,b1,b2,ps,*fi,randSample);
floatSampleNum -= (double) faceSampleNum; floatSampleNum -= (double) faceSampleNum;
} }
} }
//--------- //---------
// Subdivision sampling of a single face. // Subdivision sampling of a single face.
@ -806,40 +806,40 @@ static void FaceSubdivisionOld(MetroMesh & m, VertexSampler &ps,int sampleNum, b
static int SingleFaceSimilar(FacePointer fp, VertexSampler &ps, int n_samples_per_edge) static int SingleFaceSimilar(FacePointer fp, VertexSampler &ps, int n_samples_per_edge)
{ {
int n_samples=0; int n_samples=0;
int i, j; int i, j;
float segmentNum=n_samples_per_edge -1 ; float segmentNum=n_samples_per_edge -1 ;
float segmentLen = 1.0/segmentNum; float segmentLen = 1.0/segmentNum;
// face sampling. // face sampling.
for(i=1; i < n_samples_per_edge-1; i++) for(i=1; i < n_samples_per_edge-1; i++)
for(j=1; j < n_samples_per_edge-1-i; j++) for(j=1; j < n_samples_per_edge-1-i; j++)
{ {
//AddSample( v0 + (V1*(double)i + V2*(double)j) ); //AddSample( v0 + (V1*(double)i + V2*(double)j) );
CoordType sampleBary(i*segmentLen,j*segmentLen, 1.0 - (i*segmentLen+j*segmentLen) ) ; CoordType sampleBary(i*segmentLen,j*segmentLen, 1.0 - (i*segmentLen+j*segmentLen) ) ;
n_samples++; n_samples++;
ps.AddFace(*fp,sampleBary); ps.AddFace(*fp,sampleBary);
} }
return n_samples; return n_samples;
} }
static int SingleFaceSimilarDual(FacePointer fp, VertexSampler &ps, int n_samples_per_edge, bool randomFlag) static int SingleFaceSimilarDual(FacePointer fp, VertexSampler &ps, int n_samples_per_edge, bool randomFlag)
{ {
int n_samples=0; int n_samples=0;
float i, j; float i, j;
float segmentNum=n_samples_per_edge -1 ; float segmentNum=n_samples_per_edge -1 ;
float segmentLen = 1.0/segmentNum; float segmentLen = 1.0/segmentNum;
// face sampling. // face sampling.
for(i=0; i < n_samples_per_edge-1; i++) for(i=0; i < n_samples_per_edge-1; i++)
for(j=0; j < n_samples_per_edge-1-i; j++) for(j=0; j < n_samples_per_edge-1-i; j++)
{ {
//AddSample( v0 + (V1*(double)i + V2*(double)j) ); //AddSample( v0 + (V1*(double)i + V2*(double)j) );
CoordType V0((i+0)*segmentLen,(j+0)*segmentLen, 1.0 - ((i+0)*segmentLen+(j+0)*segmentLen) ) ; CoordType V0((i+0)*segmentLen,(j+0)*segmentLen, 1.0 - ((i+0)*segmentLen+(j+0)*segmentLen) ) ;
CoordType V1((i+1)*segmentLen,(j+0)*segmentLen, 1.0 - ((i+1)*segmentLen+(j+0)*segmentLen) ) ; CoordType V1((i+1)*segmentLen,(j+0)*segmentLen, 1.0 - ((i+1)*segmentLen+(j+0)*segmentLen) ) ;
CoordType V2((i+0)*segmentLen,(j+1)*segmentLen, 1.0 - ((i+0)*segmentLen+(j+1)*segmentLen) ) ; CoordType V2((i+0)*segmentLen,(j+1)*segmentLen, 1.0 - ((i+0)*segmentLen+(j+1)*segmentLen) ) ;
n_samples++; n_samples++;
if(randomFlag) { if(randomFlag) {
CoordType rb=RandomBarycentric(); CoordType rb=RandomBarycentric();
ps.AddFace(*fp, V0*rb[0]+V1*rb[1]+V2*rb[2]); ps.AddFace(*fp, V0*rb[0]+V1*rb[1]+V2*rb[2]);
} else ps.AddFace(*fp,(V0+V1+V2)/3.0); } else ps.AddFace(*fp,(V0+V1+V2)/3.0);
if( j < n_samples_per_edge-i-2 ) if( j < n_samples_per_edge-i-2 )
{ {
@ -850,7 +850,7 @@ static int SingleFaceSimilarDual(FacePointer fp, VertexSampler &ps, int n_sample
ps.AddFace(*fp, V3*rb[0]+V1*rb[1]+V2*rb[2]); ps.AddFace(*fp, V3*rb[0]+V1*rb[1]+V2*rb[2]);
} else ps.AddFace(*fp,(V3+V1+V2)/3.0); } else ps.AddFace(*fp,(V3+V1+V2)/3.0);
} }
} }
return n_samples; return n_samples;
} }
@ -888,7 +888,7 @@ static void FaceSimilar(MetroMesh & m, VertexSampler &ps,int sampleNum, bool dua
ScalarType area = Stat<MetroMesh>::ComputeMeshArea(m); ScalarType area = Stat<MetroMesh>::ComputeMeshArea(m);
ScalarType samplePerAreaUnit = sampleNum/area; ScalarType samplePerAreaUnit = sampleNum/area;
// Similar Triangles sampling. // Similar Triangles sampling.
int n_samples_per_edge; int n_samples_per_edge;
double n_samples_decimal = 0.0; double n_samples_decimal = 0.0;
FaceIterator fi; FaceIterator fi;
@ -902,13 +902,13 @@ static void FaceSimilar(MetroMesh & m, VertexSampler &ps,int sampleNum, bool dua
{ {
// face sampling. // face sampling.
if(dualFlag) if(dualFlag)
{ {
n_samples_per_edge = (int)((sqrt(1.0+8.0*(double)n_samples) +5.0)/2.0); // original for non dual case n_samples_per_edge = (int)((sqrt(1.0+8.0*(double)n_samples) +5.0)/2.0); // original for non dual case
n_samples = SingleFaceSimilar(&*fi,ps, n_samples_per_edge); n_samples = SingleFaceSimilar(&*fi,ps, n_samples_per_edge);
} else { } else {
n_samples_per_edge = (int)(sqrt((double)n_samples) +1.0); n_samples_per_edge = (int)(sqrt((double)n_samples) +1.0);
n_samples = SingleFaceSimilarDual(&*fi,ps, n_samples_per_edge,randomFlag); n_samples = SingleFaceSimilarDual(&*fi,ps, n_samples_per_edge,randomFlag);
} }
} }
n_samples_decimal -= (double) n_samples; n_samples_decimal -= (double) n_samples;
} }
@ -933,10 +933,10 @@ static void FaceSimilar(MetroMesh & m, VertexSampler &ps,int sampleNum, bool dua
typedef typename MetroMesh::ScalarType S; typedef typename MetroMesh::ScalarType S;
// Calcolo bounding box // Calcolo bounding box
Box2i bbox; Box2i bbox;
Box2<S> bboxf; Box2<S> bboxf;
bboxf.Add(v0); bboxf.Add(v0);
bboxf.Add(v1); bboxf.Add(v1);
bboxf.Add(v2); bboxf.Add(v2);
bbox.min[0] = floor(bboxf.min[0]); bbox.min[0] = floor(bboxf.min[0]);
bbox.min[1] = floor(bboxf.min[1]); bbox.min[1] = floor(bboxf.min[1]);
@ -974,7 +974,7 @@ static void FaceSimilar(MetroMesh & m, VertexSampler &ps,int sampleNum, bool dua
edgeLength[0] = borderEdges[0].Length(); edgeLength[0] = borderEdges[0].Length();
edgeMask |= 1; edgeMask |= 1;
} }
if (f.IsB(1)) { if (f.IsB(1)) {
borderEdges[1] = Segment2<S>(v1, v2); borderEdges[1] = Segment2<S>(v1, v2);
edgeLength[1] = borderEdges[1].Length(); edgeLength[1] = borderEdges[1].Length();
edgeMask |= 2; edgeMask |= 2;
@ -991,7 +991,7 @@ static void FaceSimilar(MetroMesh & m, VertexSampler &ps,int sampleNum, bool dua
for(int x=bbox.min[0]-1;x<=bbox.max[0]+1;++x) for(int x=bbox.min[0]-1;x<=bbox.max[0]+1;++x)
{ {
bool in = false; bool in = false;
S n[3] = { b0-db0-dn0, b1-db1-dn1, b2-db2-dn2}; S n[3] = { b0-db0-dn0, b1-db1-dn1, b2-db2-dn2};
for(int y=bbox.min[1]-1;y<=bbox.max[1]+1;++y) for(int y=bbox.min[1]-1;y<=bbox.max[1]+1;++y)
{ {
if( ((n[0]>=0 && n[1]>=0 && n[2]>=0) || (n[0]<=0 && n[1]<=0 && n[2]<=0)) && (de != 0)) if( ((n[0]>=0 && n[1]>=0 && n[2]>=0) || (n[0]<=0 && n[1]<=0 && n[2]<=0)) && (de != 0))
@ -1013,10 +1013,10 @@ static void FaceSimilar(MetroMesh & m, VertexSampler &ps,int sampleNum, bool dua
// find the closest point (on some edge) that lies on the 2x2 squared neighborhood of the considered point // find the closest point (on some edge) that lies on the 2x2 squared neighborhood of the considered point
for (int i=0; i<3; ++i) for (int i=0; i<3; ++i)
{ {
if (edgeMask & (1 << i)) if (edgeMask & (1 << i))
{ {
Point2<S> close; Point2<S> close;
S dst; S dst;
if ( ((!flipped) && (n[i]<0)) || if ( ((!flipped) && (n[i]<0)) ||
( flipped && (n[i]>0)) ) ( flipped && (n[i]>0)) )
{ {
@ -1030,7 +1030,7 @@ static void FaceSimilar(MetroMesh & m, VertexSampler &ps,int sampleNum, bool dua
closeEdge = i; closeEdge = i;
} }
} }
} }
} }
if (closeEdge >= 0) if (closeEdge >= 0)
@ -1094,11 +1094,11 @@ static bool checkPoissonDisk(SampleSHT & sht, const Point3<ScalarType> & p, Scal
GridGetInBox(sht, mv, bb, closests); GridGetInBox(sht, mv, bb, closests);
ScalarType r2 = radius*radius; ScalarType r2 = radius*radius;
for(int i=0; i<closests.size(); ++i) for(int i=0; i<closests.size(); ++i)
if(SquaredDistance(p,closests[i]->cP()) < r2) if(SquaredDistance(p,closests[i]->cP()) < r2)
return false; return false;
return true; return true;
} }
struct PoissonDiskParam struct PoissonDiskParam
@ -1175,7 +1175,7 @@ static void ComputePoissonSampleRadii(MetroMesh &sampleMesh, ScalarType diskRadi
} }
// Trivial approach that puts all the samples in a UG and removes all the ones that surely do not fit the // Trivial approach that puts all the samples in a UG and removes all the ones that surely do not fit the
static void PoissonDiskPruning(MetroMesh &origMesh, VertexSampler &ps, MetroMesh &montecarloMesh, static void PoissonDiskPruning(VertexSampler &ps, MetroMesh &montecarloMesh,
ScalarType diskRadius, const struct PoissonDiskParam pp=PoissonDiskParam()) ScalarType diskRadius, const struct PoissonDiskParam pp=PoissonDiskParam())
{ {
// spatial index of montecarlo samples - used to choose a new sample to insert // spatial index of montecarlo samples - used to choose a new sample to insert
@ -1187,7 +1187,8 @@ static void PoissonDiskPruning(MetroMesh &origMesh, VertexSampler &ps, MetroMesh
int t0 = clock(); int t0 = clock();
// inflating // inflating
BoxType bb=origMesh.bbox; BoxType bb=montecarloMesh.bbox;
assert(!bb.IsNull());
bb.Offset(cellsize); bb.Offset(cellsize);
int sizeX = std::max(1.0f,bb.DimX() / cellsize); int sizeX = std::max(1.0f,bb.DimX() / cellsize);
@ -1263,12 +1264,12 @@ static void PoissonDiskPruning(MetroMesh &origMesh, VertexSampler &ps, MetroMesh
static void PoissonDisk(MetroMesh &origMesh, VertexSampler &ps, MetroMesh &montecarloMesh, ScalarType diskRadius, const struct PoissonDiskParam pp=PoissonDiskParam()) static void PoissonDisk(MetroMesh &origMesh, VertexSampler &ps, MetroMesh &montecarloMesh, ScalarType diskRadius, const struct PoissonDiskParam pp=PoissonDiskParam())
{ {
// int t0=clock(); // int t0=clock();
// spatial index of montecarlo samples - used to choose a new sample to insert // spatial index of montecarlo samples - used to choose a new sample to insert
MontecarloSHT montecarloSHTVec[5]; MontecarloSHT montecarloSHTVec[5];
// initialize spatial hash table for searching // initialize spatial hash table for searching
// radius is the radius of empty disk centered over the samples (e.g. twice of the empty space disk) // radius is the radius of empty disk centered over the samples (e.g. twice of the empty space disk)
// This radius implies that when we pick a sample in a cell all that cell will not be touched again. // This radius implies that when we pick a sample in a cell all that cell will not be touched again.
ScalarType cellsize = 2.0f* diskRadius / sqrt(3.0); ScalarType cellsize = 2.0f* diskRadius / sqrt(3.0);
@ -1280,7 +1281,7 @@ static void PoissonDisk(MetroMesh &origMesh, VertexSampler &ps, MetroMesh &monte
int sizeX = std::max(1.0f,bb.DimX() / cellsize); int sizeX = std::max(1.0f,bb.DimX() / cellsize);
int sizeY = std::max(1.0f,bb.DimY() / cellsize); int sizeY = std::max(1.0f,bb.DimY() / cellsize);
int sizeZ = std::max(1.0f,bb.DimZ() / cellsize); int sizeZ = std::max(1.0f,bb.DimZ() / cellsize);
Point3i gridsize(sizeX, sizeY, sizeZ); Point3i gridsize(sizeX, sizeY, sizeZ);
// spatial hash table of the generated samples - used to check the radius constrain // spatial hash table of the generated samples - used to check the radius constrain
SampleSHT checkSHT; SampleSHT checkSHT;
@ -1307,12 +1308,12 @@ static void PoissonDisk(MetroMesh &origMesh, VertexSampler &ps, MetroMesh &monte
montecarloSHTVec[0].UpdateAllocatedCells(); montecarloSHTVec[0].UpdateAllocatedCells();
// if we are doing variable density sampling we have to prepare the random samples quality with the correct expected radii. // if we are doing variable density sampling we have to prepare the random samples quality with the correct expected radii.
if(pp.adaptiveRadiusFlag) if(pp.adaptiveRadiusFlag)
ComputePoissonSampleRadii(montecarloMesh, diskRadius, pp.radiusVariance, pp.invertQuality); ComputePoissonSampleRadii(montecarloMesh, diskRadius, pp.radiusVariance, pp.invertQuality);
do do
{ {
MontecarloSHT &montecarloSHT = montecarloSHTVec[level]; MontecarloSHT &montecarloSHT = montecarloSHTVec[level];
if(level>0) if(level>0)
{// initialize spatial hash with the remaining points {// initialize spatial hash with the remaining points
@ -1322,29 +1323,29 @@ static void PoissonDisk(MetroMesh &origMesh, VertexSampler &ps, MetroMesh &monte
montecarloSHT.Add((*hi).second); montecarloSHT.Add((*hi).second);
montecarloSHT.UpdateAllocatedCells(); montecarloSHT.UpdateAllocatedCells();
} }
// shuffle active cells // shuffle active cells
unsigned int (*p_myrandom)(unsigned int) = RandomInt; unsigned int (*p_myrandom)(unsigned int) = RandomInt;
std::random_shuffle(montecarloSHT.AllocatedCells.begin(),montecarloSHT.AllocatedCells.end(), p_myrandom); std::random_shuffle(montecarloSHT.AllocatedCells.begin(),montecarloSHT.AllocatedCells.end(), p_myrandom);
// generate a sample inside C by choosing one of the contained pre-generated samples // generate a sample inside C by choosing one of the contained pre-generated samples
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
int removedCnt=montecarloSHT.hash_table.size(); int removedCnt=montecarloSHT.hash_table.size();
int addedCnt=checkSHT.hash_table.size(); int addedCnt=checkSHT.hash_table.size();
for (int i = 0; i < montecarloSHT.AllocatedCells.size(); i++) for (int i = 0; i < montecarloSHT.AllocatedCells.size(); i++)
{ {
for(int j=0;j<4;j++) for(int j=0;j<4;j++)
{ {
if( montecarloSHT.EmptyCell(montecarloSHT.AllocatedCells[i]) ) continue; if( montecarloSHT.EmptyCell(montecarloSHT.AllocatedCells[i]) ) continue;
// generate a sample chosen from the pre-generated one // generate a sample chosen from the pre-generated one
typename MontecarloSHT::HashIterator hi = montecarloSHT.hash_table.find(montecarloSHT.AllocatedCells[i]); typename MontecarloSHT::HashIterator hi = montecarloSHT.hash_table.find(montecarloSHT.AllocatedCells[i]);
if(hi==montecarloSHT.hash_table.end()) {break;} if(hi==montecarloSHT.hash_table.end()) {break;}
VertexPointer sp = (*hi).second; VertexPointer sp = (*hi).second;
// vr spans between 3.0*r and r / 4.0 according to vertex quality // vr spans between 3.0*r and r / 4.0 according to vertex quality
ScalarType sampleRadius = diskRadius; ScalarType sampleRadius = diskRadius;
if(pp.adaptiveRadiusFlag) sampleRadius = sp->Q(); if(pp.adaptiveRadiusFlag) sampleRadius = sp->Q();
if (checkPoissonDisk(checkSHT, sp->cP(), sampleRadius)) if (checkPoissonDisk(checkSHT, sp->cP(), sampleRadius))
{ {
ps.AddVert(*sp); ps.AddVert(*sp);
montecarloSHT.RemoveCell(sp); montecarloSHT.RemoveCell(sp);
@ -1354,17 +1355,17 @@ static void PoissonDisk(MetroMesh &origMesh, VertexSampler &ps, MetroMesh &monte
else else
montecarloSHT.RemovePunctual(sp); montecarloSHT.RemovePunctual(sp);
} }
} }
addedCnt = checkSHT.hash_table.size()-addedCnt; addedCnt = checkSHT.hash_table.size()-addedCnt;
removedCnt = removedCnt-montecarloSHT.hash_table.size(); removedCnt = removedCnt-montecarloSHT.hash_table.size();
// proceed to the next level of subdivision // proceed to the next level of subdivision
// increase grid resolution // increase grid resolution
gridsize *= 2; gridsize *= 2;
// //
level++; level++;
} while(level < 5); } while(level < 5);
} }
//template <class MetroMesh> //template <class MetroMesh>
@ -1386,12 +1387,12 @@ static void Texture(MetroMesh & m, VertexSampler &ps, int textureWidth, int text
printf("Similar Triangles face sampling\n"); printf("Similar Triangles face sampling\n");
for(fi=m.face.begin(); fi != m.face.end(); fi++) for(fi=m.face.begin(); fi != m.face.end(); fi++)
if (!fi->IsD()) if (!fi->IsD())
{ {
Point2f ti[3]; Point2f ti[3];
for(int i=0;i<3;++i) for(int i=0;i<3;++i)
ti[i]=Point2f((*fi).WT(i).U() * textureWidth - 0.5, (*fi).WT(i).V() * textureHeight - 0.5); ti[i]=Point2f((*fi).WT(i).U() * textureWidth - 0.5, (*fi).WT(i).V() * textureHeight - 0.5);
// - 0.5 constants are used to obtain correct texture mapping // - 0.5 constants are used to obtain correct texture mapping
SingleFaceRaster(*fi, ps, ti[0],ti[1],ti[2], correctSafePointsBaryCoords); SingleFaceRaster(*fi, ps, ti[0],ti[1],ti[2], correctSafePointsBaryCoords);
} }
@ -1438,31 +1439,31 @@ static void SubdivideAndSample(MetroMesh & m, std::vector<Point3f> &pvec, const
dist=dist_upper_bound; dist=dist_upper_bound;
nearestF = rrp.gM.GetClosest(PDistFunct,rrp.markerFunctor,startPt,dist_upper_bound,dist,closestPt); nearestF = rrp.gM.GetClosest(PDistFunct,rrp.markerFunctor,startPt,dist_upper_bound,dist,closestPt);
curDiag /=2; curDiag /=2;
if(dist < dist_upper_bound) if(dist < dist_upper_bound)
{ {
if(curDiag/3 < rrp.minDiag) //store points only for the last level of recursion (?) if(curDiag/3 < rrp.minDiag) //store points only for the last level of recursion (?)
{ {
if(rrp.offset==0) if(rrp.offset==0)
pvec.push_back(closestPt); pvec.push_back(closestPt);
else else
{ {
if(dist>rrp.offset) // points below the offset threshold cannot be displaced at the right offset distance, we can only make points nearer. if(dist>rrp.offset) // points below the offset threshold cannot be displaced at the right offset distance, we can only make points nearer.
{ {
Point3f delta = startPt-closestPt; Point3f delta = startPt-closestPt;
pvec.push_back(closestPt+delta*(rrp.offset/dist)); pvec.push_back(closestPt+delta*(rrp.offset/dist));
} }
} }
} }
if(curDiag < rrp.minDiag) return; if(curDiag < rrp.minDiag) return;
Point3f hs = (bb.max-bb.min)/2; Point3f hs = (bb.max-bb.min)/2;
for(int i=0;i<2;i++) for(int i=0;i<2;i++)
for(int j=0;j<2;j++) for(int j=0;j<2;j++)
for(int k=0;k<2;k++) for(int k=0;k<2;k++)
SubdivideAndSample(m,pvec, SubdivideAndSample(m,pvec,
Box3f(Point3f( bb.min[0]+i*hs[0], bb.min[1]+j*hs[1], bb.min[2]+k*hs[2]), Box3f(Point3f( bb.min[0]+i*hs[0], bb.min[1]+j*hs[1], bb.min[2]+k*hs[2]),
Point3f(startPt[0]+i*hs[0],startPt[1]+j*hs[1],startPt[2]+k*hs[2])),rrp,curDiag); Point3f(startPt[0]+i*hs[0],startPt[1]+j*hs[1],startPt[2]+k*hs[2])),rrp,curDiag);
} }
} }
}; // end class }; // end class