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);
132 openvdb::CoordBBox bbox;
134 std::multiset<openvdb::Index64> mVoxelSet;
135 const double maxId =
static_cast<double>(voxelId);
136 for (
int i=0, chunks=100000; i<mPointCount; i += chunks) {
139 for (
int j=i, end=
std::min(i+chunks, mPointCount); j<end; ++j) {
143 std::multiset<openvdb::Index64>::iterator voxelIter =
144 mVoxelSet.begin(), voxelEnd = mVoxelSet.end();
145 typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn();
147 size_t interruptCount = 0;
148 for (
openvdb::Index64 n=valueIter.getVoxelCount(); voxelIter != voxelEnd; ++voxelIter) {
151 while ( n <= *voxelIter ) {
153 n += valueIter.getVoxelCount();
155 if (valueIter.isVoxelValue()) {
156 const openvdb::Coord
min = valueIter.getCoord();
158 this->addPoint(grid, dmin);
160 valueIter.getBoundingBox(bbox);
161 const openvdb::Coord size(bbox.extents());
165 this->addPoint(grid, dmin, size);
168 if (mInterrupter) mInterrupter->end();
173 void print(
const std::string &name, std::ostream& os = std::cout)
const
175 os <<
"Uniformely scattered " << mPointCount <<
" points into " << mVoxelCount
176 <<
" active voxels in \"" << name <<
"\" corresponding to "
177 << mPointsPerVolume <<
" points per volume." << std::endl;
185 PointAccessorType& mPoints;
186 InterruptType* mInterrupter;
188 float mPointsPerVolume;
190 RandomGenerator& mRandomGen;
191 boost::uniform_01<double> mRandom;
193 double getRand() {
return mRandom(mRandomGen); }
195 template <
typename Gr
idT>
198 mPoints.add(grid.indexToWorld(pos + delta));
201 template <
typename Gr
idT>
202 inline void addPoint(
const GridT &grid,
const openvdb::Vec3R &dmin)
204 this->addPoint(grid, dmin,
openvdb::Vec3R(getRand(),getRand(),getRand()));
206 template <
typename Gr
idT>
207 inline void addPoint(
const GridT &grid,
const openvdb::Vec3R &dmin,
const openvdb::Coord &size)
209 const openvdb::Vec3R d(size.x()*getRand(),size.y()*getRand(),size.z()*getRand());
210 this->addPoint(grid, dmin, d);
222 template<
typename PointAccessorType,
223 typename RandomGenerator,
224 typename InterruptType = openvdb::util::NullInterrupter>
229 float pointsPerVolume,
230 RandomGenerator& randGen,
231 InterruptType* interrupt = NULL):
233 mInterrupter(interrupt),
235 mPointsPerVolume(pointsPerVolume),
242 template<
typename Gr
idT>
245 mVoxelCount = grid.activeVoxelCount();
246 if (mVoxelCount == 0)
return;
247 if (mInterrupter) mInterrupter->start(
"Non-uniform scattering with local point density");
249 const double volumePerVoxel = dim[0]*dim[1]*dim[2],
250 pointsPerVoxel = mPointsPerVolume * volumePerVoxel;
251 openvdb::CoordBBox bbox;
252 size_t interruptCount = 0;
253 for (
typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) {
256 const double d = (*iter) * pointsPerVoxel * iter.getVoxelCount();
257 const int n = int(d);
258 if (iter.isVoxelValue()) {
259 const openvdb::Coord
min = iter.getCoord();
261 for (
int i = 0; i < n; ++i) this->addPoint(grid, dmin);
262 if (getRand() < (d - n)) this->addPoint(grid, dmin);
264 iter.getBoundingBox(bbox);
265 const openvdb::Coord size(bbox.extents());
269 for (
int i = 0; i < n; ++i) this->addPoint(grid, dmin, size);
270 if (getRand() < (d - n)) this->addPoint(grid, dmin, size);
273 if (mInterrupter) mInterrupter->end();
278 void print(
const std::string &name, std::ostream& os = std::cout)
const
280 os <<
"Non-uniformely scattered " << mPointCount <<
" points into " << mVoxelCount
281 <<
" active voxels in \"" << name <<
"\"." << std::endl;
288 PointAccessorType& mPoints;
289 InterruptType* mInterrupter;
291 float mPointsPerVolume;
293 RandomGenerator& mRandomGen;
294 boost::uniform_01<double> mRandom;
296 double getRand() {
return mRandom(mRandomGen); }
298 template <
typename Gr
idT>
301 mPoints.add(grid.indexToWorld(pos + delta));
304 template <
typename Gr
idT>
305 inline void addPoint(
const GridT &grid,
const openvdb::Vec3R &dmin)
307 this->addPoint(grid, dmin,
openvdb::Vec3R(getRand(),getRand(),getRand()));
309 template <
typename Gr
idT>
310 inline void addPoint(
const GridT &grid,
const openvdb::Vec3R &dmin,
const openvdb::Coord &size)
312 const openvdb::Vec3R d(size.x()*getRand(),size.y()*getRand(),size.z()*getRand());
313 this->addPoint(grid, dmin, d);
322 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
Type Round(Type x)
Return x rounded down to the nearest integer.
Definition: Math.h:698
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
uint64_t Index64
Definition: Types.h:56
#define OPENVDB_VERSION_NAME
Definition: version.h:45
Vec3< double > Vec3d
Definition: Vec3.h:625
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67