1.3.66
 
Loading...
Searching...
No Matches
Voxel Intersection Plugin Documentation



Warning
DEPRECATED PLUGIN: The VoxelIntersection plugin functionality has been merged into the CollisionDetection plugin. This plugin is deprecated and will be removed in a future release. Please migrate to CollisionDetection for all voxel intersection and primitive slicing operations.

Migration to CollisionDetection Plugin

All VoxelIntersection functionality is now available in the CollisionDetection plugin with the same API:

Migration Steps:

  1. Replace include "VoxelIntersection.h" with include "CollisionDetection.h"
  2. Replace VoxelIntersection class with CollisionDetection
  3. All method names remain identical (no API changes)
  4. calculatePrimitiveVoxelIntersection() now uses OpenMP instead of CUDA

Example Migration:

// Old VoxelIntersection code:
VoxelIntersection voxelintersection(&context);
voxelintersection.slicePrimitivesUsingGrid(uuids, center, size, divisions);
auto cells = voxelintersection.getCellPrimitives();
// New CollisionDetection code:
CollisionDetection collisiondetection(&context);
collisiondetection.slicePrimitivesUsingGrid(uuids, center, size, divisions);
auto cells = collisiondetection.getGridCells();

See the CollisionDetection documentation section on Primitive Slicing Operations for complete details and examples.


Dependencies

NVIDIA CUDA 9.0+

gcc/g++ 5.5+

CMakeLists.txtset( PLUGINS "voxelintersection" )
Header Fileinclude "VoxelIntersection.h"
ClassVoxelIntersection

Dependencies

Installing dependent packages
Package
td
td
td
NVIDIA CUDA 9.0+ Mac OSX:
$ brew install Caskroom/cask/cuda
Use CUDA installer Use CUDA installer

For help choosing the correct CUDA toolkit version for your system, consult this page: Choosing the right CUDA and OptiX version

Useful OS-specific information for installing CUDA can be found here: Install and Set-up

If you are using a PC, it is likely you will need to increase the GPU timeout in the registry, otherwise calculations lasting longer than 2 secs. will timeout and kill your program. A guide on how to increase the timeout can be found here: Increasing graphics driver timeout

Known Issues

  • Rotated voxels are currently not supported (must be axis-aligned).

Class Constructor

Constructors
VoxelIntersection( helios::Context* )

Variables and Primitive Data

Output Primitive Data

VariableData TypeDescription
inside_UUIDsstd::vector<uint>Vector of UUIDs of planar primitives (patches and triangles) contained within the given voxel. Thus, the primitive data "inside_UUIDs" is defined only for voxels. If no elements are contained within the voxel, the vector is empty.

Introduction

This plug-in calculates the planar primitive elements (patches and triangles) contained within voxel volumes and can also slice primitives based on voxels faces. Slicing enables more accurate primitive area computations within individual voxels by splitting primitives that intersect voxel faces. Some calculations are performed on the GPU to accelerate voxel intersection calculations.

The figure below shows an array of randomly arranged patches, and one voxel. The patches inside of the voxel are colored red, which was determined using this plug-in.

Using the Plug-In

To use the voxel intersection plug-in, an instance of the VoxelIntersection must be declared, whose constructor takes a pointer to the Context as an argument. This class has two main functions:

1) calculatePrimitiveVoxelIntersection() performs voxel intersection tests. If no arguments are passed to this function, it will consider all primitives in the Context. Alternatively, a vector of UUIDs can be passed as an argument, in which case only those primitives will be considered.

When the calculatePrimitiveVoxelIntersection() function is run, the plug-in will search all patches and triangles and determine whether any portion of them is contained within any voxel. The plug-in will create primitive data called "inside_UUIDs", which is defined only for voxels currently in the Context. This primitive is a vector of UUIDs, and contains the UUIDs of any primitives that were found to be inside of the particular voxel. If no primitives are inside of the voxel, the vector will be empty. If there are no voxels in the Context, the plug-in will do nothing.

  include "Context.h"
  include "VoxelIntersection.h"

  using namespace helios;

  int main( void ){

      Context context;

     uint UUIDt = context.addTriangle( make_vec3(0,0,1), make_vec3(0,1,1), make_vec3(1,1,1) );

     vec3 voxel_center(0,0,1);
     vec3 voxel_size(2,2,2);
     uint UUIDv = context.addVoxel( voxel_center, voxel_size );

     VoxelIntersection intersection(&context);

     intersection.calculatePrimitiveVoxelIntersection();

     std::vector<uint> intersected_UUIDs;
     context.getPrimitiveData( UUIDv, "inside_UUIDs", intersected_UUIDs );

     int p = std::find( intersected_UUIDs.begin(), intersected_UUIDs.end(), UUIDt );
     if( p != intersected_UUIDs.end() ){
         std::cout << "Primitive is inside voxel." << std::endl;
     }else{
         std::cout << "Primitive is not inside voxel." << std::endl;
     }

  }

2) slicePrimitivesUsingGrid() takes a vector of primitive UUIDs to be sliced and arguments specifiying the grid center, size, and subdivisions (as used in the LiDAR plugin). Each face of the defined voxel grid will then be used to slice the primitives. The function returns a vector of planar primitive UUIDs representing the original primitives provided (both new primitives that resulted from slicing and primitives that didn't need to be sliced). The function also sets the primitive data field "cell_ID" according to which voxel grid cell the primitive is inside (or a value of -1 for primitives outside any grid cell). The function also saves vectors of the primitive UUIDs in each grid cell to private class variable std::vector<std::vector<uint>> cell_primitives, accessible using getCellPrimitives(). This vector is one element longer than the number of grid cells, with the last element storing UUIDs that didn't fall into any grid cell. This indexing was used so that grid cell IDs would correspond to those used by the LiDAR plugin.

The figure below shows a visualization of square patches that have been sliced by a voxel grid, produced by the example code below. Primitives are colored by the grid cell they are inside.

  include "Context.h"
  include "Visualizer.h"
  include "CanopyGenerator.h"
  include "VoxelIntersection.h"

  using namespace helios;

  int main() {

    Context context;

generate an example canopy and get UUIDs
    CanopyGenerator cg(&context);
    HomogeneousCanopyParameters hcp;
    hcp.leaf_area_index = 3;
    hcp.canopy_height = 3;
    hcp.canopy_extent = make_vec2(3.5,3);
    hcp.leaf_size = make_vec2(0.3,0.3);
    cg.buildCanopy(hcp);
    std::vector<uint> UUIDs = flatten(cg.getLeafUUIDs(0));

define a voxel grid
    vec3 grid_center = make_vec3(0,0,1.5);
    vec3 grid_size = make_vec3(3,3,3);
    int3 grid_divisions = make_int3(3,3,3);

slice the UUIDs using the voxel grid
    VoxelIntersection vi(&context);
    vi.slicePrimitivesUsingGrid(UUIDs, grid_center , grid_size, grid_divisions);

get UUIDs inside grid cell 0
    std::vector<std::vector<uint>> cell_primitives = vi.getCellPrimitives();
    std::vector<uint> cell_0_primitives = cell_primitives.at(0);
    std::cout << "Primitive UUIDs in grid cell 0:" << std::endl;
    for(uint i=0;i<cell_0_primitives.size();i++)
    {
      std::cout << cell_0_primitives.at(i) << std::endl;
    }


visualize by coloring primitives by the cell_ID data field
    Visualizer vis(1800, 900);
    vis.buildContextGeometry(&context);
    vis.colorContextPrimitivesByData("cell_ID");
    vis.setColormap(Visualizer::COLORMAP_RAINBOW);
    vis.addGridWireFrame(grid_center, grid_size, grid_divisions);
    vis.disableColorbar();
    vis.hideWatermark();
    vis.setBackgroundColor(RGB::white);

    vis.plotInteractive();

  }