AcademySoftwareFoundation / openvdb

OpenVDB - Sparse volume data structure and tools
http://www.openvdb.org/
Mozilla Public License 2.0
2.59k stars 643 forks source link

dilate voxels from a PointDataGrid #1717

Open PerspectivesLab opened 9 months ago

PerspectivesLab commented 9 months ago

Environment

Operating System: windows 10 Compiler: msvc 2019

Describe the problem

i am trying to dilate voxels of a PointDataGrid in order to save each voxels to file with an offset, the dilateActiveValues doesnt affect the voxel of a PointDataGrid. ex: PointDataGrid with voxel 2.0, and a extra offset of 0.3. so thats all the saved voxels overlap by 0.3, is there a way to achieve that ?


openvdb::points::PointAttributeVector<openvdb::Vec3d> positionsWrapper(positions/* my point cloud points */);
transform = openvdb::math::Transform::createLinearTransform(2.0); // voxel size => 2.0
// grid
grid = openvdb::tools::createPointIndexGrid<openvdb::tools::PointIndexGrid>(positionsWrapper, *transform);
grid->setName("PointsIndex"); 
// data
  gridData = openvdb::points::createPointDataGrid<openvdb::points::NullCodec, openvdb::points::PointDataGrid>(*grid, positionsWrapper, *transform);
gridData->setName("PointsData");  

// dilate all voxels for
int iterations = 3;
openvdb::tools::dilateActiveValues(gridData->tree(),  iterations );
// now save all voxels to file... but dilate has no effect on the saved points

auto cut_particles_op = [&](openvdb::points::PointDataTree::LeafNodeType& leaf, openvdb::Index leafpos) { 
           const openvdb::points::AttributeArray& positionArray = leaf.attributeArray("P");
           openvdb::points::AttributeHandle<openvdb::Vec3f > positionHandle(positionArray);
           for (openvdb::Index offset = 0; offset < leaf.SIZE; offset++) {
                  const openvdb::Index original_attribute_end = leaf.getValue(offset);
                  const auto ijk = leaf.offsetToGlobalCoord(offset);
                  const openvdb::Vec3d vec = ijk.asVec3d();
                 for (auto iter = leaf.beginIndexVoxel(ijk); iter; ++iter) {  
                     const openvdb::Index index = *iter;// position
                    const openvdb::Vec3d pos = openvdb::Vec3d(positionHandle.get(index)) + vec;
                    Vec3d positionWorldSpace = transform->indexToWorld(pos);
                    here my points arent affected by any voxel bounding box dilated.... voxel size isnt 2.3 but remain 2.0 in size.

          }                

      }

}

 openvdb::tree::LeafManager<openvdb::points::PointDataTree> points_iter(gridData->tree());
bool threaded = false; // for debug, set to false
points_iter.foreach(cut_particles_op, threaded );

i tried clip, clipGrid, ( to slow ), is there a fast way to slice/cut voxel volumes in a grid with an overlap/padding between voxels ? ( ex 0.3 )

Idclip commented 9 months ago

Hi @PerspectivesLab,

The topology of PointDataGrid's is slightly more locked down than that of other grid types as the idea is that the active states of PDG voxels represent whether that voxel contains any points or not (you can manipulate this yourself but a lot of tools work on that assumption) - so I wouldn't be suprised if the dilate/erode methods do nothing for PDGs. We can add a static_assert to this method so that it doesn't compile for PDGs if that's the case

i tried clip, clipGrid, ( to slow ), is there a fast way to slice/cut voxel volumes in a grid with an overlap/padding between voxels ? ( ex 0.3 )

I'm not 100% clear on what you're trying to do here - dialteActiveValues only works on the topology of the provided grid, so even if it was allowed to change the active states of PDG voxels, it wouldn't move the points or change their positions. Can you elaborate on what you're trying to do?

PerspectivesLab commented 9 months ago

Hi @Idclip, thank's for the clarification,

what i am trying to do at the moment, is serializing each voxels ( size 2 ) points to file, i would need to include points from adjacent voxels but only in the limit of a bounding box, let say 2.6 ( main voxel: 2 + 0.6 on each axis to gather neighboor points ).

i know i can iterate adjacent voxels from a voxel and gather the points as for (int n = 0; n < 26; n++) { Coord neigh = util::COORD_OFFSETS[n]; } => check if inside the main Bbox, append points.. but it seems i cant get the point indexes inside some of the adjacent voxels ( they contain points ), but voxel is flagged as off...

but i would like to avoid if/statements in order to be fast.

the main idea i had, was looking for a function to scale the voxel grid (all voxels from their center, only their bounds, not the data) so they overlap ( 0.3 ), in that way i could just iterate once each voxel's and serialize the points faster, ( such the idea of dilate grid i had ), let me know if this is more clear, or any faster solution ? thx