14 #ifndef OPENVDB_POINTS_POINT_SCATTER_HAS_BEEN_INCLUDED
15 #define OPENVDB_POINTS_POINT_SCATTER_HAS_BEEN_INCLUDED
17 #include <type_traits>
32 #include <tbb/parallel_sort.h>
33 #include <tbb/parallel_for.h>
73 typename RandGenT = std::mt19937,
74 typename PositionArrayT = TypedAttributeArray<Vec3f, NullCodec>,
75 typename PointDataGridT = Grid<
77 typename InterrupterT = util::NullInterrupter>
78 inline typename PointDataGridT::Ptr
81 const unsigned int seed = 0,
82 const float spread = 1.0
f,
83 InterrupterT* interrupter =
nullptr);
102 typename RandGenT = std::mt19937,
103 typename PositionArrayT = TypedAttributeArray<Vec3f, NullCodec>,
104 typename PointDataGridT = Grid<
106 typename InterrupterT = util::NullInterrupter>
107 inline typename PointDataGridT::Ptr
109 const float pointsPerVoxel,
110 const unsigned int seed = 0,
111 const float spread = 1.0
f,
112 InterrupterT* interrupter =
nullptr);
134 typename RandGenT = std::mt19937,
135 typename PositionArrayT = TypedAttributeArray<Vec3f, NullCodec>,
136 typename PointDataGridT = Grid<
138 typename InterrupterT = util::NullInterrupter>
139 inline typename PointDataGridT::Ptr
141 const float pointsPerVoxel,
142 const unsigned int seed = 0,
143 const float spread = 1.0
f,
144 InterrupterT* interrupter =
nullptr);
150 namespace point_scatter_internal
156 template<
typename Po
intDataGr
idT,
typename Gr
idT>
157 inline typename PointDataGridT::Ptr
160 typename PointDataGridT::Ptr
points(
new PointDataGridT);
161 points->setTransform(grid.transform().copy());
162 points->topologyUnion(grid);
163 if (points->tree().hasActiveTiles()) {
164 points->tree().voxelizeActiveTiles();
183 const AttributeSet::Descriptor::Ptr& descriptor,
189 using ValueType =
typename PositionTraits::ElementType;
192 leaf.initializeAttributes(descriptor, static_cast<Index>(count));
196 auto&
array = leaf.attributeArray(0);
199 PositionWriteHandle pHandle(
array,
false);
202 P[0] = (spread * (rand01() - ValueType(0.5)));
203 P[1] = (spread * (rand01() - ValueType(0.5)));
204 P[2] = (spread * (rand01() - ValueType(0.5)));
205 pHandle.set(static_cast<Index>(
index), P);
218 typename PositionArrayT,
219 typename PointDataGridT,
220 typename InterrupterT>
221 inline typename PointDataGridT::Ptr
224 const unsigned int seed,
226 InterrupterT* interrupter)
228 using PositionType =
typename PositionArrayT::ValueType;
230 using ValueType =
typename PositionTraits::ElementType;
231 using CodecType =
typename PositionArrayT::Codec;
235 using TreeType =
typename PointDataGridT::TreeType;
236 using LeafNodeType =
typename TreeType::LeafNodeType;
244 static void getPrefixSum(LeafManagerT& leafManager,
248 offsets.reserve(leafManager.leafCount() + 1);
249 offsets.push_back(0);
250 const auto leafRange = leafManager.
leafRange();
251 for (
auto leaf = leafRange.begin(); leaf; ++leaf) {
252 offset += leaf->onVoxelCount();
253 offsets.push_back(offset);
258 static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
259 "Invalid Position Array type.");
261 if (spread < 0.0f || spread > 1.0
f) {
262 OPENVDB_THROW(ValueError,
"Spread must be between 0 and 1.");
265 if (interrupter) interrupter->start(
"Uniform scattering with fixed point count");
267 typename PointDataGridT::Ptr
points =
268 point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
269 TreeType& tree = points->tree();
270 if (!tree.cbeginLeaf())
return points;
272 LeafManagerT leafManager(tree);
273 const Index64 voxelCount = leafManager.activeLeafVoxelCount();
274 assert(voxelCount != 0);
276 const double pointsPerVolume = double(count) / double(voxelCount);
280 if (remainder == 0) {
282 GridT, RandGenT, PositionArrayT, PointDataGridT, InterrupterT>(
283 grid, float(pointsPerVoxel), seed, spread, interrupter);
286 std::vector<Index64> voxelOffsets,
values;
291 values.reserve(remainder);
297 if (util::wasInterrupted<InterrupterT>(interrupter)) {
302 tbb::parallel_sort(values.begin(), values.end());
303 const bool fractionalOnly(pointsPerVoxel == 0);
305 leafManager.foreach([&voxelOffsets, &values, fractionalOnly]
306 (LeafNodeType& leaf,
const size_t idx)
308 const Index64 lowerOffset = voxelOffsets[idx];
309 const Index64 upperOffset = voxelOffsets[idx + 1];
310 assert(upperOffset > lowerOffset);
312 const auto valuesEnd = values.end();
313 auto lower = std::lower_bound(values.begin(), valuesEnd, lowerOffset);
315 auto*
const data = leaf.buffer().data();
316 auto iter = leaf.beginValueOn();
319 bool addedPoints(!fractionalOnly);
320 while (lower != valuesEnd) {
322 if (vId >= upperOffset)
break;
325 iter.increment(nextOffset - currentOffset);
326 currentOffset = nextOffset;
329 auto&
value = data[iter.pos()];
337 if (!addedPoints) leaf.setValuesOff();
340 voxelOffsets.clear();
343 if (fractionalOnly) {
345 leafManager.rebuild();
348 const AttributeSet::Descriptor::Ptr descriptor =
349 AttributeSet::Descriptor::create(PositionArrayT::attributeType());
350 RandomGenerator rand01(seed);
352 const auto leafRange = leafManager.leafRange();
353 auto leaf = leafRange.begin();
354 for (; leaf; ++leaf) {
355 if (util::wasInterrupted<InterrupterT>(interrupter))
break;
357 for (
auto iter = leaf->beginValueAll(); iter; ++iter) {
358 if (iter.isValueOn()) {
360 if (value == 0) leaf->setValueOff(iter.pos());
361 else offset +=
value;
364 leaf->setOffsetOnly(iter.pos(),
offset);
369 point_scatter_internal::generatePositions<PositionType, CodecType>
370 (*leaf, descriptor,
offset, spread, rand01);
375 for (; leaf; ++leaf) leaf->setValuesOff();
379 if (interrupter) interrupter->end();
390 typename PositionArrayT,
391 typename PointDataGridT,
392 typename InterrupterT>
393 inline typename PointDataGridT::Ptr
395 const float pointsPerVoxel,
396 const unsigned int seed,
398 InterrupterT* interrupter)
400 using PositionType =
typename PositionArrayT::ValueType;
402 using ValueType =
typename PositionTraits::ElementType;
403 using CodecType =
typename PositionArrayT::Codec;
407 using TreeType =
typename PointDataGridT::TreeType;
409 static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
410 "Invalid Position Array type.");
412 if (pointsPerVoxel < 0.0
f) {
413 OPENVDB_THROW(ValueError,
"Points per voxel must not be less than zero.");
416 if (spread < 0.0f || spread > 1.0
f) {
417 OPENVDB_THROW(ValueError,
"Spread must be between 0 and 1.");
420 if (interrupter) interrupter->start(
"Dense uniform scattering with fixed point count");
422 typename PointDataGridT::Ptr
points =
423 point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
424 TreeType& tree = points->tree();
425 auto leafIter = tree.beginLeaf();
426 if (!leafIter)
return points;
429 const double delta = pointsPerVoxel - float(pointsPerVoxelInt);
431 const bool fractionalOnly = pointsPerVoxelInt == 0;
433 const AttributeSet::Descriptor::Ptr descriptor =
434 AttributeSet::Descriptor::create(PositionArrayT::attributeType());
435 RandomGenerator rand01(seed);
437 for (; leafIter; ++leafIter) {
438 if (util::wasInterrupted<InterrupterT>(interrupter))
break;
440 for (
auto iter = leafIter->beginValueAll(); iter; ++iter) {
441 if (iter.isValueOn()) {
442 offset += pointsPerVoxelInt;
443 if (fractional && rand01() < delta) ++offset;
444 else if (fractionalOnly) leafIter->setValueOff(iter.pos());
447 leafIter->setOffsetOnly(iter.pos(),
offset);
451 point_scatter_internal::generatePositions<PositionType, CodecType>
452 (*leafIter, descriptor,
offset, spread, rand01);
457 const bool prune(leafIter || fractionalOnly);
458 for (; leafIter; ++leafIter) leafIter->setValuesOff();
461 if (interrupter) interrupter->end();
472 typename PositionArrayT,
473 typename PointDataGridT,
474 typename InterrupterT>
475 inline typename PointDataGridT::Ptr
477 const float pointsPerVoxel,
478 const unsigned int seed,
480 InterrupterT* interrupter)
482 using PositionType =
typename PositionArrayT::ValueType;
484 using ValueType =
typename PositionTraits::ElementType;
485 using CodecType =
typename PositionArrayT::Codec;
489 using TreeType =
typename PointDataGridT::TreeType;
491 static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
492 "Invalid Position Array type.");
494 "Scalar grid type required for weighted voxel scattering.");
496 if (pointsPerVoxel < 0.0
f) {
497 OPENVDB_THROW(ValueError,
"Points per voxel must not be less than zero.");
500 if (spread < 0.0f || spread > 1.0
f) {
501 OPENVDB_THROW(ValueError,
"Spread must be between 0 and 1.");
504 if (interrupter) interrupter->start(
"Non-uniform scattering with local point density");
506 typename PointDataGridT::Ptr
points =
507 point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
508 TreeType& tree = points->tree();
509 auto leafIter = tree.beginLeaf();
510 if (!leafIter)
return points;
512 const AttributeSet::Descriptor::Ptr descriptor =
513 AttributeSet::Descriptor::create(PositionArrayT::attributeType());
514 RandomGenerator rand01(seed);
515 const auto accessor = grid.getConstAccessor();
517 for (; leafIter; ++leafIter) {
518 if (util::wasInterrupted<InterrupterT>(interrupter))
break;
520 for (
auto iter = leafIter->beginValueAll(); iter; ++iter) {
521 if (iter.isValueOn()) {
523 double(accessor.getValue(iter.getCoord())) * pointsPerVoxel;
524 fractional =
std::max(0.0, fractional);
526 if (rand01() < (fractional -
double(count))) ++
count;
527 else if (count == 0) leafIter->setValueOff(iter.pos());
531 leafIter->setOffsetOnly(iter.pos(),
offset);
535 point_scatter_internal::generatePositions<PositionType, CodecType>
536 (*leafIter, descriptor,
offset, spread, rand01);
541 for (; leafIter; ++leafIter) leafIter->setValuesOff();
544 if (interrupter) interrupter->end();
554 #endif // OPENVDB_POINTS_POINT_SCATTER_HAS_BEEN_INCLUDED
vint4 max(const vint4 &a, const vint4 &b)
PositionType
How the position of the anchor is interpreted.
Simple generator of random numbers over the range [0, 1)
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
void generatePositions(LeafNodeT &leaf, const AttributeSet::Descriptor::Ptr &descriptor, const Index64 &count, const float spread, RandGenT &rand01)
Generate random point positions for a leaf node.
Write-able version of AttributeHandle.
GLuint GLsizei const GLuint const GLintptr * offsets
GLint GLsizei const GLuint64 * values
#define OPENVDB_USE_VERSION_NAMESPACE
float RoundDown(float x)
Return x rounded down to the nearest integer.
void expand(bool fill=true)
If this array is uniform, replace it with an array of length size().
Simple random integer generator.
Methods for counting points in VDB Point grids.
PointDataGridT::Ptr initialisePointTopology(const GridT &grid)
initialise the topology of a PointDataGrid and ensure everything is voxelized
GLint GLenum GLsizei GLint GLsizei const void * data
GA_API const UT_StringHolder gen
Defined various multi-threaded utility functions for trees.
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
*Note that the tasks the is the thread number *for the or if it s being executed by a non pool thread(this *can happen in cases where the whole pool is occupied and the calling *thread contributes to running the work load).**Thread pool.Have fun
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
PointDataGridT::Ptr nonUniformPointScatter(const GridT &grid, const float pointsPerVoxel, const unsigned int seed=0, const float spread=1.0f, InterrupterT *interrupter=nullptr)
Non uniformly scatter points per active voxel. The pointsPerVoxel value is used to weight each grids ...
PointDataGridT::Ptr uniformPointScatter(const GridT &grid, const Index64 count, const unsigned int seed=0, const float spread=1.0f, InterrupterT *interrupter=nullptr)
The free functions depend on the following class:
GLuint GLdouble GLdouble GLint GLint const GLdouble * points
GLuint GLuint GLsizei count
INT64 INT64 INT64 remainder
int Floor(float x)
Return the floor of x.
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
Attribute Array storage templated on type and compression codec.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
GLsizei const GLfloat * value
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
PointDataGridT::Ptr denseUniformPointScatter(const GridT &grid, const float pointsPerVoxel, const unsigned int seed=0, const float spread=1.0f, InterrupterT *interrupter=nullptr)
Uniformly scatter a fixed number of points per active voxel. If the pointsPerVoxel value provided is ...
#define OPENVDB_THROW(exception, message)