9 #ifndef OPENVDB_POINTS_POINT_SCATTER_IMPL_HAS_BEEN_INCLUDED
10 #define OPENVDB_POINTS_POINT_SCATTER_IMPL_HAS_BEEN_INCLUDED
19 namespace point_scatter_internal
25 template<
typename Po
intDataGr
idT,
typename Gr
idT>
26 inline typename PointDataGridT::Ptr
27 initialisePointTopology(
const GridT& grid)
29 typename PointDataGridT::Ptr
points(
new PointDataGridT);
30 points->setTransform(grid.transform().copy());
31 points->topologyUnion(grid);
32 if (
points->tree().hasActiveTiles()) {
33 points->tree().voxelizeActiveTiles();
51 generatePositions(LeafNodeT& leaf,
52 const AttributeSet::Descriptor::Ptr& descriptor,
57 using PositionTraits = VecTraits<PositionType>;
58 using ValueType =
typename PositionTraits::ElementType;
59 using PositionWriteHandle = AttributeWriteHandle<PositionType, CodecT>;
61 leaf.initializeAttributes(descriptor, static_cast<Index>(count));
65 auto& array = leaf.attributeArray(0);
68 PositionWriteHandle pHandle(array,
false);
71 P[0] = (spread * (rand01() -
ValueType(0.5)));
72 P[1] = (spread * (rand01() -
ValueType(0.5)));
73 P[2] = (spread * (rand01() -
ValueType(0.5)));
74 pHandle.set(static_cast<Index>(
index), P);
88 typename PositionArrayT,
89 typename PointDataGridT,
90 typename InterrupterT>
91 inline typename PointDataGridT::Ptr
94 const unsigned int seed,
96 InterrupterT* interrupter)
100 using ValueType =
typename PositionTraits::ElementType;
105 using TreeType =
typename PointDataGridT::TreeType;
106 using LeafNodeType =
typename TreeType::LeafNodeType;
114 static void getPrefixSum(LeafManagerT& leafManager,
118 offsets.reserve(leafManager.leafCount() + 1);
119 offsets.push_back(0);
120 const auto leafRange = leafManager.
leafRange();
121 for (
auto leaf = leafRange.begin(); leaf; ++leaf) {
122 offset += leaf->onVoxelCount();
123 offsets.push_back(offset);
128 static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
129 "Invalid Position Array type.");
131 if (spread < 0.0f || spread > 1.0
f) {
132 OPENVDB_THROW(ValueError,
"Spread must be between 0 and 1.");
135 if (interrupter) interrupter->start(
"Uniform scattering with fixed point count");
137 typename PointDataGridT::Ptr
points =
138 point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
139 TreeType& tree = points->tree();
140 if (!tree.cbeginLeaf())
return points;
142 LeafManagerT leafManager(tree);
143 const Index64 voxelCount = leafManager.activeLeafVoxelCount();
144 assert(voxelCount != 0);
146 const double pointsPerVolume = double(count) / double(voxelCount);
148 const Index64 remainder = count - (pointsPerVoxel * voxelCount);
150 if (remainder == 0) {
152 GridT, RandGenT, PositionArrayT, PointDataGridT, InterrupterT>(
153 grid,
float(pointsPerVoxel), seed, spread, interrupter);
156 std::vector<Index64> voxelOffsets,
values;
161 values.reserve(remainder);
162 for (
Index64 i = 0; i < remainder; ++i) values.emplace_back(gen());
167 if (util::wasInterrupted<InterrupterT>(interrupter)) {
172 tbb::parallel_sort(values.begin(), values.end());
173 const bool fractionalOnly(pointsPerVoxel == 0);
175 leafManager.foreach([&voxelOffsets, &values, fractionalOnly]
176 (LeafNodeType& leaf,
const size_t idx)
178 const Index64 lowerOffset = voxelOffsets[idx];
179 const Index64 upperOffset = voxelOffsets[idx + 1];
180 assert(upperOffset > lowerOffset);
182 const auto valuesEnd = values.end();
183 auto lower = std::lower_bound(values.begin(), valuesEnd, lowerOffset);
185 auto*
const data = leaf.buffer().data();
186 auto iter = leaf.beginValueOn();
189 bool addedPoints(!fractionalOnly);
190 while (
lower != valuesEnd) {
192 if (vId >= upperOffset)
break;
195 iter.increment(nextOffset - currentOffset);
196 currentOffset = nextOffset;
199 auto&
value = data[iter.pos()];
207 if (!addedPoints) leaf.setValuesOff();
210 voxelOffsets.clear();
213 if (fractionalOnly) {
215 leafManager.rebuild();
218 const AttributeSet::Descriptor::Ptr descriptor =
219 AttributeSet::Descriptor::create(PositionArrayT::attributeType());
220 RandomGenerator rand01(seed);
222 const auto leafRange = leafManager.leafRange();
223 auto leaf = leafRange.begin();
224 for (; leaf; ++leaf) {
225 if (util::wasInterrupted<InterrupterT>(interrupter))
break;
227 for (
auto iter = leaf->beginValueAll(); iter; ++iter) {
228 if (iter.isValueOn()) {
230 if (value == 0) leaf->setValueOff(iter.pos());
231 else offset +=
value;
234 leaf->setOffsetOnly(iter.pos(),
offset);
239 point_scatter_internal::generatePositions<PositionType, CodecType>
240 (*leaf, descriptor,
offset, spread, rand01);
245 for (; leaf; ++leaf) leaf->setValuesOff();
249 if (interrupter) interrupter->end();
260 typename PositionArrayT,
261 typename PointDataGridT,
262 typename InterrupterT>
263 inline typename PointDataGridT::Ptr
265 const float pointsPerVoxel,
266 const unsigned int seed,
268 InterrupterT* interrupter)
272 using ValueType =
typename PositionTraits::ElementType;
277 using TreeType =
typename PointDataGridT::TreeType;
279 static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
280 "Invalid Position Array type.");
282 if (pointsPerVoxel < 0.0
f) {
283 OPENVDB_THROW(ValueError,
"Points per voxel must not be less than zero.");
286 if (spread < 0.0f || spread > 1.0
f) {
287 OPENVDB_THROW(ValueError,
"Spread must be between 0 and 1.");
290 if (interrupter) interrupter->start(
"Dense uniform scattering with fixed point count");
292 typename PointDataGridT::Ptr
points =
293 point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
294 TreeType& tree = points->tree();
295 auto leafIter = tree.beginLeaf();
296 if (!leafIter)
return points;
299 const double delta = pointsPerVoxel -
float(pointsPerVoxelInt);
301 const bool fractionalOnly = pointsPerVoxelInt == 0;
303 const AttributeSet::Descriptor::Ptr descriptor =
304 AttributeSet::Descriptor::create(PositionArrayT::attributeType());
305 RandomGenerator rand01(seed);
307 for (; leafIter; ++leafIter) {
308 if (util::wasInterrupted<InterrupterT>(interrupter))
break;
310 for (
auto iter = leafIter->beginValueAll(); iter; ++iter) {
311 if (iter.isValueOn()) {
312 offset += pointsPerVoxelInt;
313 if (fractional && rand01() < delta) ++offset;
314 else if (fractionalOnly) leafIter->setValueOff(iter.pos());
317 leafIter->setOffsetOnly(iter.pos(),
offset);
321 point_scatter_internal::generatePositions<PositionType, CodecType>
322 (*leafIter, descriptor,
offset, spread, rand01);
327 const bool prune(leafIter || fractionalOnly);
328 for (; leafIter; ++leafIter) leafIter->setValuesOff();
331 if (interrupter) interrupter->end();
342 typename PositionArrayT,
343 typename PointDataGridT,
344 typename InterrupterT>
345 inline typename PointDataGridT::Ptr
347 const float pointsPerVoxel,
348 const unsigned int seed,
350 InterrupterT* interrupter)
354 using ValueType =
typename PositionTraits::ElementType;
359 using TreeType =
typename PointDataGridT::TreeType;
361 static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
362 "Invalid Position Array type.");
364 "Scalar grid type required for weighted voxel scattering.");
366 if (pointsPerVoxel < 0.0
f) {
367 OPENVDB_THROW(ValueError,
"Points per voxel must not be less than zero.");
370 if (spread < 0.0f || spread > 1.0
f) {
371 OPENVDB_THROW(ValueError,
"Spread must be between 0 and 1.");
374 if (interrupter) interrupter->start(
"Non-uniform scattering with local point density");
376 typename PointDataGridT::Ptr
points =
377 point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
378 TreeType& tree = points->tree();
379 auto leafIter = tree.beginLeaf();
380 if (!leafIter)
return points;
382 const AttributeSet::Descriptor::Ptr descriptor =
383 AttributeSet::Descriptor::create(PositionArrayT::attributeType());
384 RandomGenerator rand01(seed);
385 const auto accessor = grid.getConstAccessor();
387 for (; leafIter; ++leafIter) {
388 if (util::wasInterrupted<InterrupterT>(interrupter))
break;
390 for (
auto iter = leafIter->beginValueAll(); iter; ++iter) {
391 if (iter.isValueOn()) {
393 double(accessor.getValue(iter.getCoord())) * pointsPerVoxel;
394 fractional =
std::max(0.0, fractional);
395 int count =
int(fractional);
396 if (rand01() < (fractional -
double(count))) ++count;
397 else if (count == 0) leafIter->setValueOff(iter.pos());
401 leafIter->setOffsetOnly(iter.pos(),
offset);
405 point_scatter_internal::generatePositions<PositionType, CodecType>
406 (*leafIter, descriptor,
offset, spread, rand01);
411 for (; leafIter; ++leafIter) leafIter->setValuesOff();
414 if (interrupter) interrupter->end();
424 #endif // OPENVDB_POINTS_POINT_SCATTER_IMPL_HAS_BEEN_INCLUDED
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
PositionType
How the position of the anchor is interpreted.
GLdouble GLdouble GLint GLint const GLdouble * points
Simple generator of random numbers over the range [0, 1)
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
GLsizei const GLfloat * value
#define OPENVDB_USE_VERSION_NAMESPACE
GA_API const UT_StringHolder P
float RoundDown(float x)
Return x rounded down to the nearest integer.
Codec
Define compression codecs.
Simple random integer generator.
GLuint GLsizei const GLuint const GLintptr * offsets
IMATH_NAMESPACE::V2f float
GA_API const UT_StringHolder gen
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, const float spread, InterrupterT *interrupter)
Non uniformly scatter points per active voxel. The pointsPerVoxel value is used to weight each grids ...
**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
GLenum GLsizei GLsizei GLint * values
std::string lower(string_view a)
Return an all-upper case version of a (locale-independent).
PointDataGridT::Ptr uniformPointScatter(const GridT &grid, const Index64 count, const unsigned int seed, const float spread, InterrupterT *interrupter)
The free functions depend on the following class:
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
int Floor(float x)
Return the floor of x.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
PointDataGridT::Ptr denseUniformPointScatter(const GridT &grid, const float pointsPerVoxel, const unsigned int seed, const float spread, InterrupterT *interrupter)
Uniformly scatter a fixed number of points per active voxel. If the pointsPerVoxel value provided is ...
#define OPENVDB_THROW(exception, message)