poissondisk sampling finished...

This commit is contained in:
Massimiliano Corsini 2009-01-16 15:01:46 +00:00
parent 7bd8b4f19b
commit 83350db29a
1 changed files with 90 additions and 65 deletions

View File

@ -665,29 +665,20 @@ static CoordType RandomBox(vcg::Box3<ScalarType> box)
return p; return p;
} }
static bool generatePoissonDiskSample(Point3i *cell, MontecarloSHT samplepool, vcg::Point3<ScalarType> & p) static bool generatePoissonDiskSample(Point3i *cell, MontecarloSHT & samplepool, vcg::Point3<ScalarType> & p)
{ {
MontecarloSHTIterator cellBegin; MontecarloSHTIterator cellBegin;
MontecarloSHTIterator cellEnd; MontecarloSHTIterator cellEnd;
MontecarloSHTIterator cellIt;
samplepool.Grid(*cell, cellBegin, cellEnd); samplepool.Grid(*cell, cellBegin, cellEnd);
std::vector<VertexType *> samples; assert(cellBegin != cellEnd);
for (cellIt = cellBegin; cellIt != cellEnd; cellIt++)
samples.push_back(*cellIt);
if (samples.size() >= 1) p = (*cellBegin)->P();
{ return true;
int index = RandomInt(samples.size());
p = samples[index]->P();
return true;
}
else
return false;
} }
// check the radius constrain // check the radius constrain
static bool checkPoissonDisk(SampleSHT sht, Point3<ScalarType> p, ScalarType radius) static bool checkPoissonDisk(SampleSHT & sht, Point3<ScalarType> p, ScalarType radius)
{ {
SampleSHTIterator itBegin; SampleSHTIterator itBegin;
SampleSHTIterator itEnd; SampleSHTIterator itEnd;
@ -719,12 +710,24 @@ static bool checkPoissonDisk(SampleSHT sht, Point3<ScalarType> p, ScalarType rad
* IEEE Symposium on Interactive Ray Tracing, 2007, * IEEE Symposium on Interactive Ray Tracing, 2007,
* 10-12 Sept. 2007, pp. 129-132. * 10-12 Sept. 2007, pp. 129-132.
*/ */
static void Poissondisk(MetroMesh &m, VertexSampler &ps, MetroMesh & montecarloMesh, int sampleNum) static void Poissondisk(MetroMesh &origMesh, VertexSampler &ps, MetroMesh &montecarloMesh, int sampleNum)
{ {
const int MAXLEVELS = 10; // maximum level of subdivision int cellusedcounter[20]; // cells used for each level
int cellstosubdividecounter[20]; // cells to subdivide for each level
int samplesgenerated[20]; // samples generated for each level
int samplesaccepted[20]; // samples accepted for each level
int verticescounter[20]; // vertices added to the spatial hash table
// spatial index of mesh face - used to search where to place the samples for (int i = 0; i < 20; i++)
//MeshSHT searchSHT; {
cellusedcounter[i] = 0;
cellstosubdividecounter[i] = 0;
samplesgenerated[i] = 0;
samplesaccepted[i] = 0;
verticescounter[i] = 0;
}
const int MAXLEVELS = 5; // maximum level of subdivision
// 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 montecarloSHT; MontecarloSHT montecarloSHT;
@ -733,29 +736,27 @@ static void Poissondisk(MetroMesh &m, VertexSampler &ps, MetroMesh & montecarloM
SampleSHT checkSHT; SampleSHT checkSHT;
// initialize spatial hash table for searching // initialize spatial hash table for searching
ScalarType meshArea = Stat<MetroMesh>::ComputeMeshArea(m); ScalarType meshArea = Stat<MetroMesh>::ComputeMeshArea(origMesh);
ScalarType r = sqrt(meshArea / (0.7 * 3.1415 * sampleNum)); // 0.7 is a density factor ScalarType r = sqrt(meshArea / (0.7 * 3.1415 * sampleNum)); // 0.7 is a density factor
ScalarType cellsize = r / sqrt(2.0); ScalarType cellsize = r / (2.0 * sqrt(2.0));
int sizeX = m.bbox.DimX() / r; int sizeX = origMesh.bbox.DimX() / cellsize;
int sizeY = m.bbox.DimY() / r; int sizeY = origMesh.bbox.DimY() / cellsize;
int sizeZ = m.bbox.DimZ() / r; int sizeZ = origMesh.bbox.DimZ() / cellsize;
Point3i gridsize(sizeX, sizeY, sizeZ); Point3i gridsize(sizeX, sizeY, sizeZ);
/*
searchSHT.InitEmpty(m.bbox, gridsize);
FaceIterator fi;
for (fi = m.face.begin(); fi != m.face.end(); fi++)
searchSHT.Add(&(*fi));
*/
// initialize spatial hash to index pre-generated samples // initialize spatial hash to index pre-generated samples
VertexIterator vi; VertexIterator vi;
montecarloSHT.InitEmpty(m.bbox, gridsize); montecarloSHT.InitEmpty(origMesh.bbox, gridsize);
for (vi = m.vert.begin(); vi != m.vert.end(); vi++) for (vi = montecarloMesh.vert.begin(); vi != montecarloMesh.vert.end(); vi++)
{
montecarloSHT.Add(&(*vi)); montecarloSHT.Add(&(*vi));
verticescounter[0]++;
}
// initialize spatial hash table for check poisson-disk radius constrain // initialize spatial hash table for check poisson-disk radius constrain
checkSHT.InitEmpty(m.bbox, gridsize); checkSHT.InitEmpty(origMesh.bbox, gridsize);
// sampling algorithm // sampling algorithm
// ------------------ // ------------------
@ -769,11 +770,9 @@ static void Poissondisk(MetroMesh &m, VertexSampler &ps, MetroMesh & montecarloM
// //
std::vector<Point3i *> activeCells; std::vector<Point3i *> activeCells;
std::vector<Point3i *> cellsToSubdivide; std::vector<VertexType *> nextPoints;
typename std::vector<Point3i *>::iterator cellIt; typename std::vector<VertexType *>::iterator nextPointsIt;
std::set<FaceType *> nextFaces; // faces to add to the next level of subdivision
typename std::set<FaceType *>::iterator nextFacesIt;
typename std::vector<Point3i>::iterator it; typename std::vector<Point3i>::iterator it;
Point3i *currentCell; Point3i *currentCell;
vcg::Box3<ScalarType> currentBox; vcg::Box3<ScalarType> currentBox;
@ -781,7 +780,6 @@ static void Poissondisk(MetroMesh &m, VertexSampler &ps, MetroMesh & montecarloM
int level = 0; int level = 0;
bool validsample; bool validsample;
bool acceptedsample; bool acceptedsample;
int counter[10]; // cells used for each level
do do
{ {
@ -794,10 +792,9 @@ static void Poissondisk(MetroMesh &m, VertexSampler &ps, MetroMesh & montecarloM
activeCells.push_back(&(*it)); activeCells.push_back(&(*it));
} }
nextFaces.clear();
// shuffle active cells // shuffle active cells
int ncell = static_cast<int>(activeCells.size()); int ncell = static_cast<int>(activeCells.size());
cellusedcounter[level] = ncell;
int index,index2; int index,index2;
Point3i *temp; Point3i *temp;
for (int i = 0; i < ncell/2; i++) for (int i = 0; i < ncell/2; i++)
@ -805,7 +802,7 @@ static void Poissondisk(MetroMesh &m, VertexSampler &ps, MetroMesh & montecarloM
index = RandomInt(ncell); index = RandomInt(ncell);
index2 = RandomInt(ncell); index2 = RandomInt(ncell);
temp = activeCells[index]; temp = activeCells[index];
activeCells[index] = temp; activeCells[index] = activeCells[index2];
activeCells[index2] = temp; activeCells[index2] = temp;
} }
@ -813,22 +810,23 @@ static void Poissondisk(MetroMesh &m, VertexSampler &ps, MetroMesh & montecarloM
// generate a sample inside C and project it on the mesh // generate a sample inside C and project it on the mesh
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
std::vector<FaceType *> faces;
typename std::vector<FaceType *>::iterator facesIt;
for (int i = 0; i < ncell; i++) for (int i = 0; i < ncell; i++)
{ {
currentCell = activeCells[i]; currentCell = activeCells[i];
// generate a sample chosen from the pre-generated one // generate a sample chosen from the pre-generated one
validsample = generatePoissonDiskSample(currentCell, montecarloSHT, s); validsample = generatePoissonDiskSample(currentCell, montecarloSHT, s);
samplesgenerated[level]++;
if (validsample) if (validsample)
{ {
// sample is valid // sample is valid
acceptedsample = checkPoissonDisk(checkSHT, s, r); acceptedsample = checkPoissonDisk(checkSHT, s, r);
} }
else else
{
acceptedsample = false; acceptedsample = false;
}
if (acceptedsample) if (acceptedsample)
{ {
@ -839,11 +837,27 @@ static void Poissondisk(MetroMesh &m, VertexSampler &ps, MetroMesh & montecarloM
// add to control spatial index // add to control spatial index
checkSHT.Add(v); checkSHT.Add(v);
samplesaccepted[level]++;
} }
else else
{ {
// subdivide this cell // subdivide this cell
cellsToSubdivide.push_back(currentCell); ///////////////////////////////////////////////////////////////////////
// pre-generated samples for the next level of subdivision
MontecarloSHTIterator ptBegin;
MontecarloSHTIterator ptEnd;
MontecarloSHTIterator ptIt;
montecarloSHT.Grid(*currentCell, ptBegin, ptEnd);
for (ptIt = ptBegin; ptIt != ptEnd; ptIt++)
{
nextPoints.push_back(*ptIt);
}
cellstosubdividecounter[level]++;
} }
} }
@ -853,7 +867,6 @@ static void Poissondisk(MetroMesh &m, VertexSampler &ps, MetroMesh & montecarloM
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// cleaning spatial index data structures // cleaning spatial index data structures
//searchSHT.Clear();
montecarloSHT.Clear(); montecarloSHT.Clear();
// increase grid resolution // increase grid resolution
@ -861,32 +874,44 @@ static void Poissondisk(MetroMesh &m, VertexSampler &ps, MetroMesh & montecarloM
gridsize[1] *= 2; gridsize[1] *= 2;
gridsize[2] *= 2; gridsize[2] *= 2;
//searchSHT.InitEmpty(m.bbox, gridsize); montecarloSHT.InitEmpty(montecarloMesh.bbox, gridsize);
montecarloSHT.InitEmpty(m.bbox, gridsize);
for (cellIt = cellsToSubdivide.begin(); cellIt != cellsToSubdivide.end(); cellIt++) for (nextPointsIt = nextPoints.begin(); nextPointsIt != nextPoints.end(); nextPointsIt++)
{ {
MeshSHTIterator faceBegin,faceEnd,faceIt; montecarloSHT.Add(*nextPointsIt);
MontecarloSHTIterator ptBegin,ptEnd,ptIt; verticescounter[level+1]++;
Point3i *cell = *cellIt;
// pre-generated samples for the next level of subdivision
montecarloSHT.Grid(*cell, ptBegin, ptEnd);
for (ptIt = ptBegin; ptIt != ptEnd; ptIt++)
montecarloSHT.Add(*ptIt);
/*
// faces of the mesh for the next level of subdivision
searchSHT.Grid(*cell, faceBegin, faceEnd);
for (faceIt = faceBegin; faceIt != faceEnd; faceIt++)
searchSHT.Add(*faceIt);
*/
} }
nextPoints.clear();
level++; level++;
} while(level < 1); } while(level < MAXLEVELS);
// write some statistics
QFile data("C:/temp/poissondisk_statistics.txt");
if (data.open(QFile::WriteOnly | QFile::Truncate))
{
QTextStream out(&data);
for (int k = 0; k < MAXLEVELS; k++)
out << "Cells used for level " << k << ": " << cellusedcounter[k] << endl;
for (int k = 0; k < MAXLEVELS; k++)
out << "Cells to subdivide for level " << k << ": " << cellstosubdividecounter[k] << endl;
for (int k = 0; k < MAXLEVELS; k++)
out << "Vertices counter for level " << k << ": " << verticescounter[k] << endl;
for (int k = 0; k < MAXLEVELS; k++)
out << "Samples generated for level " << k << ": " << samplesgenerated[k] << endl;
for (int k = 0; k < MAXLEVELS; k++)
out << "Samples accepted for level " << k << ": " << samplesaccepted[k] << endl;
}
} }