Skip to content

Volume Grids

Volume grid structures visualize data defined on an axis-aligned regularly-spaced 3D grid.

As usual, first you register a volume grid, then add one or more quantities defined on that grid. Registering the grid itself just means specifying the locations of its extremal corners and the grid resolution. Then you can add data, such as scalar data as linearly-interpolated values per-node or as piecewise-constant values per-cell. Slice planes can also be used inspect the interior of the grid, isosurfaces can be extracted from scalar functions at nodes, and more.

Example: registering a volume grid and adding a scalar quantity

#include "polyscope/polyscope.h"
#include "polyscope/volume_grid.h"

polyscope::init();

// define the resolution and bounds of the grid
uint32_t dimX = 20;
uint32_t dimY = 20;
uint32_t dimZ = 20;
glm::vec3 bound_low{-3., -3., -3.};
glm::vec3 bound_high{3., 3., 3.};

// register the grid
polyscope::VolumeGrid* psGrid = polyscope::registerVolumeGrid(
        "sample grid", {dimX, dimY, dimZ}, bound_low, bound_high);

// add a scalar function on the grid
uint32_t nData = dimX*dimY*dimZ;
float* scalarVals = /* your dimX*dimY*dimZ buffer of data*/;

polyscope::VolumeGridNodeScalarQuantity* scalarQ = 
    psGrid->addNodeScalarQuantity("node scalar1", 
                                  std::make_tuple(scalarVals, nData));
scalarQ->setEnabled(true);

polyscope::show();

Registering a volume grid

Specifying node vs. cells

Volume grid dimensions and locations are always defined in terms of nodes (aka cell corners). The dimension is the number of nodes along each axis, and the location is defined by the extremal nodes.

For dimensions, if you are instead thinking in terms of the number of cells (little cubical regions), add +1 to the number of cells along each dimension to get the equivalent number of nodes when registering the grid.

For locations, the min/max bounds you specify when registering the grid are the locations up the minimum and maximum node (aka cell corner). If you are instead thinking in terms of cell center locations, shift them half-cell-width offset when registering the grid.

polyscope::registerVolumeGrid(std::string name, glm::uvec3 gridNodeDim, glm::vec3 boundMin, glm::vec3 boundMax)

Add a new volume grid structure to Polyscope.

  • name the name of the structure
  • gridNodeDim a glm::uvec3 integer 3-vector giving the number of nodes in the grid along each dimension
  • boundMin a glm::vec3 float 3-vector giving the xyz coordinates for the minimal node corner of the grid
  • boundMax a glm::vec3 float 3-vector giving the xyz coordinates for the maximal node corner of the grid
polyscope::registerVolumeGrid(std::string name, uint64_t gridNodeAxesDim, glm::vec3 boundMin, glm::vec3 boundMax)

Same as above, but takes a single axis dimension which is used for all 3 axes.


Slice planes

Slice planes are particularly useful for inspecting the internal structure of a volume grid, as shown in the demo video at the top. Slice planes can be manipulated programmatically or manually in the GUI; see the slice plane documentation for more details.

Picking

“Picking” refers to selecting and inspecting elements by clicking on the object in the scene. Picking volume grid elements works a little differently from other structures. For most structures, each click selects an element of the structure. However for volume grids, clicking on the structure once initiates picking, then the UI continuously displays data for the location under your mouse cursor. You can always deselect the volume grid elements by clicking somewhere off the grid.

By default, if you have only registered data defined on nodes, then only nodes can be picked (and vice-versa for cells). You can override this behavior by calling VolumeGrid::markNodesAsUsed(), to act as if a node quantity had been added, and likewise for VolumeGrid::markCellsAsUsed().

Options

See structure management for options common to all structures such as enabling/disabling, transforms, and transparency.

Parameter Meaning Getter Setter Persistent?
color the color of the volume glm::vec3 getColor() setColor(glm::vec3 val) yes
edge color the color of the grid edges glm::vec3 getEdgeColor() setEdgeColor(glm::vec3 val) yes
edge width how thick to draw mesh edges, use 0. to disable and 1. for reasonable edges double getEdgeWidth() setEdgeWidth(double val) yes
cube size factor shrink factor from 0-1 to draw gaps between cells, 0 is no shrink (default) double getCubeSizeFactor() setCubeSizeFactor(double val) yes
material what material to use std::string getMaterial() setMaterial(std::string name) yes

(All setters return this to support chaining. Structure options return a generic structure pointer, so chain them last.)