33 #ifndef OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
34 #define OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
36 #include <openvdb/Types.h>
37 #include <openvdb/Grid.h>
38 #include <openvdb/util/NullInterrupter.h>
39 #include <boost/random/uniform_01.hpp>
84 template<
typename PointAccessorType,
85 typename RandomGenerator,
86 typename InterruptType = openvdb::util::NullInterrupter>
92 RandomGenerator& randGen,
93 InterruptType* interrupt = NULL):
95 mInterrupter(interrupt),
96 mPointCount(pointCount),
97 mPointsPerVolume(0.0f),
103 float pointsPerVolume,
104 RandomGenerator& randGen,
105 InterruptType* interrupt = NULL):
107 mInterrupter(interrupt),
109 mPointsPerVolume(pointsPerVolume),
116 template<
typename Gr
idT>
119 mVoxelCount = grid.activeVoxelCount();
120 if (mVoxelCount == 0)
return;
123 if (mPointsPerVolume>0) {
124 if (mInterrupter) mInterrupter->start(
"Uniform scattering with fixed point density");
125 mPointCount = int(mPointsPerVolume * dim[0]*dim[1]*dim[2] * mVoxelCount);
126 }
else if (mPointCount>0) {
127 if (mInterrupter) mInterrupter->start(
"Uniform scattering with fixed point count");
128 mPointsPerVolume = mPointCount/float(dim[0]*dim[1]*dim[2] * mVoxelCount);
133 openvdb::CoordBBox bbox;
135 std::multiset<openvdb::Index64> mVoxelSet;
136 for (
int i=0, chunks=100000; i<mPointCount; i += chunks) {
141 for (
int j=i, end=
std::min(i+chunks, mPointCount); j<end; ++j) {
145 std::multiset<openvdb::Index64>::iterator voxelIter =
146 mVoxelSet.begin(), voxelEnd = mVoxelSet.end();
147 typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn();
149 size_t interruptCount = 0;
150 for (
openvdb::Index64 i=valueIter.getVoxelCount(); voxelIter != voxelEnd; ++voxelIter) {
153 while ( i <= *voxelIter ) {
155 i += valueIter.getVoxelCount();
157 if (valueIter.isVoxelValue()) {
158 const openvdb::Coord
min = valueIter.getCoord();
160 this->addPoint(grid, dmin);
162 valueIter.getBoundingBox(bbox);
163 const openvdb::Coord size(bbox.extents());
167 this->addPoint(grid, dmin, size);
170 if (mInterrupter) mInterrupter->end();
175 void print(
const std::string &name, std::ostream& os = std::cout)
const
177 os <<
"Uniformely scattered " << mPointCount <<
" points into " << mVoxelCount
178 <<
" active voxels in \"" << name <<
"\" corresponding to "
179 << mPointsPerVolume <<
" points per volume." << std::endl;
187 PointAccessorType& mPoints;
188 InterruptType* mInterrupter;
190 float mPointsPerVolume;
192 RandomGenerator& mRandomGen;
193 boost::uniform_01<double> mRandom;
195 double getRand() {
return mRandom(mRandomGen); }
197 template <
typename Gr
idT>
200 mPoints.add(grid.indexToWorld(pos + delta));
203 template <
typename Gr
idT>
204 inline void addPoint(
const GridT &grid,
const openvdb::Vec3R &dmin)
206 this->addPoint(grid, dmin,
openvdb::Vec3R(getRand(),getRand(),getRand()));
208 template <
typename Gr
idT>
209 inline void addPoint(
const GridT &grid,
const openvdb::Vec3R &dmin,
const openvdb::Coord &size)
211 const openvdb::Vec3R d(size.x()*getRand(),size.y()*getRand(),size.z()*getRand());
212 this->addPoint(grid, dmin, d);
224 template<
typename PointAccessorType,
225 typename RandomGenerator,
226 typename InterruptType = openvdb::util::NullInterrupter>
231 float pointsPerVolume,
232 RandomGenerator& randGen,
233 InterruptType* interrupt = NULL):
235 mInterrupter(interrupt),
237 mPointsPerVolume(pointsPerVolume),
244 template<
typename Gr
idT>
247 mVoxelCount = grid.activeVoxelCount();
248 if (mVoxelCount == 0)
return;
249 if (mInterrupter) mInterrupter->start(
"Non-uniform scattering with local point density");
251 const double volumePerVoxel = dim[0]*dim[1]*dim[2],
252 pointsPerVoxel = mPointsPerVolume * volumePerVoxel;
253 openvdb::CoordBBox bbox;
254 size_t interruptCount = 0;
255 for (
typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) {
258 const double d = (*iter) * pointsPerVoxel * iter.getVoxelCount();
259 const int n = int(d);
260 if (iter.isVoxelValue()) {
261 const openvdb::Coord
min = iter.getCoord();
263 for (
int i = 0; i < n; ++i) this->addPoint(grid, dmin);
264 if (getRand() < (d - n)) this->addPoint(grid, dmin);
266 iter.getBoundingBox(bbox);
267 const openvdb::Coord size(bbox.extents());
271 for (
int i = 0; i < n; ++i) this->addPoint(grid, dmin, size);
272 if (getRand() < (d - n)) this->addPoint(grid, dmin, size);
275 if (mInterrupter) mInterrupter->end();
280 void print(
const std::string &name, std::ostream& os = std::cout)
const
282 os <<
"Non-uniformely scattered " << mPointCount <<
" points into " << mVoxelCount
283 <<
" active voxels in \"" << name <<
"\"." << std::endl;
290 PointAccessorType& mPoints;
291 InterruptType* mInterrupter;
293 float mPointsPerVolume;
295 RandomGenerator& mRandomGen;
296 boost::uniform_01<double> mRandom;
298 double getRand() {
return mRandom(mRandomGen); }
300 template <
typename Gr
idT>
303 mPoints.add(grid.indexToWorld(pos + delta));
306 template <
typename Gr
idT>
307 inline void addPoint(
const GridT &grid,
const openvdb::Vec3R &dmin)
309 this->addPoint(grid, dmin,
openvdb::Vec3R(getRand(),getRand(),getRand()));
311 template <
typename Gr
idT>
312 inline void addPoint(
const GridT &grid,
const openvdb::Vec3R &dmin,
const openvdb::Coord &size)
314 const openvdb::Vec3R d(size.x()*getRand(),size.y()*getRand(),size.z()*getRand());
315 this->addPoint(grid, dmin, d);
324 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
#define OPENVDB_VERSION_NAME
Definition: version.h:45
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
Vec3< double > Vec3d
Definition: Vec3.h:605
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:56
uint64_t Index64
Definition: Types.h:55
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76