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<
76 typename points::TreeConverter<typename GridT::TreeType>::Type>,
77 typename InterrupterT = util::NullInterrupter>
78 inline typename PointDataGridT::Ptr
81 const unsigned int seed = 0,
82 const float spread = 1.0f,
83 InterrupterT* interrupter =
nullptr);
102 typename RandGenT = std::mt19937,
103 typename PositionArrayT = TypedAttributeArray<Vec3f, NullCodec>,
104 typename PointDataGridT =
Grid<
105 typename points::TreeConverter<typename GridT::TreeType>::Type>,
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.0f,
112 InterrupterT* interrupter =
nullptr);
134 typename RandGenT = std::mt19937,
135 typename PositionArrayT = TypedAttributeArray<Vec3f, NullCodec>,
136 typename PointDataGridT =
Grid<
137 typename points::TreeConverter<typename GridT::TreeType>::Type>,
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.0f,
144 InterrupterT* interrupter =
nullptr);
151 namespace point_scatter_internal
157 template<
typename Po
intDataGr
idT,
typename Gr
idT>
158 inline typename PointDataGridT::Ptr
159 initialisePointTopology(
const GridT& grid)
161 typename PointDataGridT::Ptr points(
new PointDataGridT);
162 points->setTransform(grid.transform().copy());
163 points->topologyUnion(grid);
164 if (points->tree().hasActiveTiles()) {
165 points->tree().voxelizeActiveTiles();
178 template<
typename PositionType,
183 generatePositions(LeafNodeT& leaf,
184 const AttributeSet::Descriptor::Ptr& descriptor,
189 using PositionTraits = VecTraits<PositionType>;
190 using ValueType =
typename PositionTraits::ElementType;
191 using PositionWriteHandle = AttributeWriteHandle<PositionType, CodecT>;
193 leaf.initializeAttributes(descriptor, static_cast<Index>(count));
197 auto& array = leaf.attributeArray(0);
200 PositionWriteHandle pHandle(array,
false);
202 for (
Index64 index = 0; index < count; ++index) {
203 P[0] = (spread * (rand01() - ValueType(0.5)));
204 P[1] = (spread * (rand01() - ValueType(0.5)));
205 P[2] = (spread * (rand01() - ValueType(0.5)));
206 pHandle.set(static_cast<Index>(index), P);
220 typename PositionArrayT,
221 typename PointDataGridT,
222 typename InterrupterT>
223 inline typename PointDataGridT::Ptr
226 const unsigned int seed,
228 InterrupterT* interrupter)
230 using PositionType =
typename PositionArrayT::ValueType;
232 using ValueType =
typename PositionTraits::ElementType;
237 using TreeType =
typename PointDataGridT::TreeType;
238 using LeafNodeType =
typename TreeType::LeafNodeType;
246 static void getPrefixSum(LeafManagerT& leafManager,
247 std::vector<Index64>& offsets)
250 offsets.reserve(leafManager.leafCount() + 1);
251 offsets.push_back(0);
252 const auto leafRange = leafManager.
leafRange();
253 for (
auto leaf = leafRange.begin(); leaf; ++leaf) {
254 offset += leaf->onVoxelCount();
255 offsets.push_back(offset);
260 static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
261 "Invalid Position Array type.");
263 if (spread < 0.0f || spread > 1.0f) {
267 if (interrupter) interrupter->start(
"Uniform scattering with fixed point count");
269 typename PointDataGridT::Ptr points =
270 point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
271 TreeType& tree = points->tree();
272 if (!tree.cbeginLeaf())
return points;
274 LeafManagerT leafManager(tree);
275 const Index64 voxelCount = leafManager.activeLeafVoxelCount();
276 assert(voxelCount != 0);
278 const double pointsPerVolume = double(count) / double(voxelCount);
280 const Index64 remainder = count - (pointsPerVoxel * voxelCount);
282 if (remainder == 0) {
284 GridT, RandGenT, PositionArrayT, PointDataGridT, InterrupterT>(
285 grid, float(pointsPerVoxel), seed, spread, interrupter);
288 std::vector<Index64> voxelOffsets, values;
289 std::thread worker(&Local::getPrefixSum, std::ref(leafManager), std::ref(voxelOffsets));
293 values.reserve(remainder);
294 for (
Index64 i = 0; i < remainder; ++i) values.emplace_back(gen());
299 if (util::wasInterrupted<InterrupterT>(interrupter)) {
304 tbb::parallel_sort(values.begin(), values.end());
305 const bool fractionalOnly(pointsPerVoxel == 0);
307 leafManager.foreach([&voxelOffsets, &values, fractionalOnly]
308 (LeafNodeType& leaf,
const size_t idx)
310 const Index64 lowerOffset = voxelOffsets[idx];
311 const Index64 upperOffset = voxelOffsets[idx + 1];
312 assert(upperOffset > lowerOffset);
314 const auto valuesEnd = values.end();
315 auto lower = std::lower_bound(values.begin(), valuesEnd, lowerOffset);
317 auto*
const data = leaf.buffer().data();
318 auto iter = leaf.beginValueOn();
321 bool addedPoints(!fractionalOnly);
322 while (lower != valuesEnd) {
324 if (vId >= upperOffset)
break;
327 iter.increment(nextOffset - currentOffset);
328 currentOffset = nextOffset;
331 auto&
value = data[iter.pos()];
339 if (!addedPoints) leaf.setValuesOff();
342 voxelOffsets.clear();
345 if (fractionalOnly) {
347 leafManager.rebuild();
350 const AttributeSet::Descriptor::Ptr descriptor =
351 AttributeSet::Descriptor::create(PositionArrayT::attributeType());
352 RandomGenerator rand01(seed);
354 const auto leafRange = leafManager.leafRange();
355 auto leaf = leafRange.begin();
356 for (; leaf; ++leaf) {
357 if (util::wasInterrupted<InterrupterT>(interrupter))
break;
359 for (
auto iter = leaf->beginValueAll(); iter; ++iter) {
360 if (iter.isValueOn()) {
362 if (value == 0) leaf->setValueOff(iter.pos());
363 else offset +=
value;
366 leaf->setOffsetOnly(iter.pos(), offset);
371 point_scatter_internal::generatePositions<PositionType, CodecType>
372 (*leaf, descriptor, offset, spread, rand01);
377 for (; leaf; ++leaf) leaf->setValuesOff();
381 if (interrupter) interrupter->end();
392 typename PositionArrayT,
393 typename PointDataGridT,
394 typename InterrupterT>
395 inline typename PointDataGridT::Ptr
397 const float pointsPerVoxel,
398 const unsigned int seed,
400 InterrupterT* interrupter)
402 using PositionType =
typename PositionArrayT::ValueType;
404 using ValueType =
typename PositionTraits::ElementType;
409 using TreeType =
typename PointDataGridT::TreeType;
411 static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
412 "Invalid Position Array type.");
414 if (pointsPerVoxel < 0.0f) {
418 if (spread < 0.0f || spread > 1.0f) {
422 if (interrupter) interrupter->start(
"Dense uniform scattering with fixed point count");
424 typename PointDataGridT::Ptr points =
425 point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
426 TreeType& tree = points->tree();
427 auto leafIter = tree.beginLeaf();
428 if (!leafIter)
return points;
431 const double delta = pointsPerVoxel - float(pointsPerVoxelInt);
433 const bool fractionalOnly = pointsPerVoxelInt == 0;
435 const AttributeSet::Descriptor::Ptr descriptor =
436 AttributeSet::Descriptor::create(PositionArrayT::attributeType());
437 RandomGenerator rand01(seed);
439 for (; leafIter; ++leafIter) {
440 if (util::wasInterrupted<InterrupterT>(interrupter))
break;
442 for (
auto iter = leafIter->beginValueAll(); iter; ++iter) {
443 if (iter.isValueOn()) {
444 offset += pointsPerVoxelInt;
445 if (fractional && rand01() < delta) ++offset;
446 else if (fractionalOnly) leafIter->setValueOff(iter.pos());
449 leafIter->setOffsetOnly(iter.pos(), offset);
453 point_scatter_internal::generatePositions<PositionType, CodecType>
454 (*leafIter, descriptor, offset, spread, rand01);
459 const bool prune(leafIter || fractionalOnly);
460 for (; leafIter; ++leafIter) leafIter->setValuesOff();
463 if (interrupter) interrupter->end();
474 typename PositionArrayT,
475 typename PointDataGridT,
476 typename InterrupterT>
477 inline typename PointDataGridT::Ptr
479 const float pointsPerVoxel,
480 const unsigned int seed,
482 InterrupterT* interrupter)
484 using PositionType =
typename PositionArrayT::ValueType;
486 using ValueType =
typename PositionTraits::ElementType;
491 using TreeType =
typename PointDataGridT::TreeType;
493 static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
494 "Invalid Position Array type.");
496 "Scalar grid type required for weighted voxel scattering.");
498 if (pointsPerVoxel < 0.0f) {
502 if (spread < 0.0f || spread > 1.0f) {
506 if (interrupter) interrupter->start(
"Non-uniform scattering with local point density");
508 typename PointDataGridT::Ptr points =
509 point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
510 TreeType& tree = points->tree();
511 auto leafIter = tree.beginLeaf();
512 if (!leafIter)
return points;
514 const AttributeSet::Descriptor::Ptr descriptor =
515 AttributeSet::Descriptor::create(PositionArrayT::attributeType());
516 RandomGenerator rand01(seed);
517 const auto accessor = grid.getConstAccessor();
519 for (; leafIter; ++leafIter) {
520 if (util::wasInterrupted<InterrupterT>(interrupter))
break;
522 for (
auto iter = leafIter->beginValueAll(); iter; ++iter) {
523 if (iter.isValueOn()) {
525 double(accessor.getValue(iter.getCoord())) * pointsPerVoxel;
526 fractional =
std::max(0.0, fractional);
527 int count = int(fractional);
528 if (rand01() < (fractional -
double(count))) ++count;
529 else if (count == 0) leafIter->setValueOff(iter.pos());
533 leafIter->setOffsetOnly(iter.pos(), offset);
537 point_scatter_internal::generatePositions<PositionType, CodecType>
538 (*leafIter, descriptor, offset, spread, rand01);
543 for (; leafIter; ++leafIter) leafIter->setValuesOff();
546 if (interrupter) interrupter->end();
556 #endif // OPENVDB_POINTS_POINT_SCATTER_HAS_BEEN_INCLUDED float RoundDown(float x)
Return x rounded down to the nearest integer.
Definition: Math.h:806
Simple random integer generator.
Definition: Math.h:201
Simple generator of random numbers over the range [0, 1)
Definition: Math.h:165
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Attribute Array storage templated on type and compression codec.
Methods for counting points in VDB Point grids.
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:350
Definition: Exceptions.h:65
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 ...
Definition: PointScatter.h:396
int Floor(float x)
Return the floor of x.
Definition: Math.h:851
Defined various multi-threaded utility functions for trees.
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 ...
Definition: PointScatter.h:478
openvdb::GridBase Grid
Definition: Utils.h:34
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:
Definition: PointScatter.h:224
uint64_t Index64
Definition: Types.h:53
Definition: Exceptions.h:13
ValueT value
Definition: GridBuilder.h:1287
Codec
Optional compression codecs.
Definition: IO.h:61
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
uint32_t Index32
Definition: Types.h:52
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202