9#ifndef OPENVDB_POINTS_POINT_SCATTER_IMPL_HAS_BEEN_INCLUDED 
   10#define OPENVDB_POINTS_POINT_SCATTER_IMPL_HAS_BEEN_INCLUDED 
   19namespace point_scatter_internal
 
   25template<
typename Po
intDataGr
idT, 
typename Gr
idT>
 
   26inline typename PointDataGridT::Ptr
 
   27initialisePointTopology(
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();
 
   46template<
typename PositionType,
 
   51generatePositions(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);
 
   70    for (Index64 index = 0; index < count; ++index) {
 
   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>
 
   91inline typename PointDataGridT::Ptr
 
   94                    const unsigned int seed,
 
   96                    InterrupterT* interrupter)
 
   98    using PositionType = 
typename PositionArrayT::ValueType;
 
  100    using ValueType = 
typename PositionTraits::ElementType;
 
  101    using CodecType = 
typename PositionArrayT::Codec;
 
  105    using TreeType = 
typename PointDataGridT::TreeType;
 
  106    using LeafNodeType = 
typename TreeType::LeafNodeType;
 
  114        static void getPrefixSum(LeafManagerT& leafManager,
 
  115                                 std::vector<Index64>& offsets)
 
  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.0f) {
 
  135    if (interrupter) interrupter->start(
"Uniform scattering with fixed point count");
 
  137    typename PointDataGridT::Ptr 
points =
 
  138        point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
 
  142    LeafManagerT leafManager(
tree);
 
  143    const Index64 voxelCount = leafManager.activeLeafVoxelCount();
 
  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;
 
  157    std::thread worker(&Local::getPrefixSum, std::ref(leafManager), std::ref(voxelOffsets));
 
  161        values.reserve(remainder);
 
  162        for (
Index64 i = 0; i < remainder; ++i) values.emplace_back(gen());
 
  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]; 
 
  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();
 
  220    RandomGenerator rand01(seed);
 
  222    const auto leafRange = leafManager.leafRange();
 
  223    auto leaf = leafRange.begin();
 
  224    for (; leaf; ++leaf) {
 
  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>
 
  263inline typename PointDataGridT::Ptr
 
  265                         const float pointsPerVoxel,
 
  266                         const unsigned int seed,
 
  268                         InterrupterT* interrupter)
 
  270    using PositionType = 
typename PositionArrayT::ValueType;
 
  272    using ValueType = 
typename PositionTraits::ElementType;
 
  273    using CodecType = 
typename PositionArrayT::Codec;
 
  277    using TreeType = 
typename PointDataGridT::TreeType;
 
  279    static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
 
  280                  "Invalid Position Array type.");
 
  282    if (pointsPerVoxel < 0.0f) {
 
  286    if (spread < 0.0f || spread > 1.0f) {
 
  290    if (interrupter) interrupter->start(
"Dense uniform scattering with fixed point count");
 
  292    typename PointDataGridT::Ptr 
points =
 
  293        point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
 
  295    auto leafIter = 
tree.beginLeaf();
 
  296    if (!leafIter) 
return points;
 
  299    const double delta = pointsPerVoxel - float(pointsPerVoxelInt);
 
  301    const bool fractionalOnly = pointsPerVoxelInt == 0;
 
  305    RandomGenerator rand01(seed);
 
  307    for (; leafIter; ++leafIter) {
 
  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>
 
  345inline typename PointDataGridT::Ptr
 
  347                       const float pointsPerVoxel,
 
  348                       const unsigned int seed,
 
  350                       InterrupterT* interrupter)
 
  352    using PositionType = 
typename PositionArrayT::ValueType;
 
  354    using ValueType = 
typename PositionTraits::ElementType;
 
  355    using CodecType = 
typename PositionArrayT::Codec;
 
  359    using TreeType = 
typename PointDataGridT::TreeType;
 
  361    static_assert(PositionTraits::IsVec && PositionTraits::Size == 3,
 
  362                  "Invalid Position Array type.");
 
  363    static_assert(std::is_arithmetic<typename GridT::ValueType>::value,
 
  364                  "Scalar grid type required for weighted voxel scattering.");
 
  366    if (pointsPerVoxel < 0.0f) {
 
  370    if (spread < 0.0f || spread > 1.0f) {
 
  374    if (interrupter) interrupter->start(
"Non-uniform scattering with local point density");
 
  376    typename PointDataGridT::Ptr 
points =
 
  377        point_scatter_internal::initialisePointTopology<PointDataGridT>(grid);
 
  379    auto leafIter = 
tree.beginLeaf();
 
  380    if (!leafIter) 
return points;
 
  384    RandomGenerator rand01(seed);
 
  385    const auto accessor = grid.getConstAccessor();
 
  387    for (; leafIter; ++leafIter) {
 
  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();
 
 
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Definition Exceptions.h:65
Simple generator of random numbers over the range [0, 1)
Definition Math.h:167
Simple random integer generator.
Definition Math.h:203
std::shared_ptr< Descriptor > Ptr
Definition AttributeSet.h:313
static Ptr create(const NamePair &)
Create a new descriptor from a position attribute type and assumes "P" (for convenience).
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance.
Definition Math.h:349
float RoundDown(float x)
Return x rounded down to the nearest integer.
Definition Math.h:803
int Floor(float x)
Return the floor of x.
Definition Math.h:848
Definition AttributeArray.h:42
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 PointScatterImpl.h:264
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 PointScatterImpl.h:92
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 PointScatterImpl.h:346
Definition PointDataGrid.h:170
bool wasInterrupted(T *i, int percent=-1)
Definition NullInterrupter.h:49
Index32 Index
Definition Types.h:54
uint32_t Index32
Definition Types.h:52
uint64_t Index64
Definition Types.h:53
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218