Source/Objects/Volume

Volume Object

The volume object is aimed at smoke simulation, procedural volume generation with modifiers, and importing OpenVDB files from other applications.

Data Structures

  • Object can be of type OB_VOLUME, and then uses a Volume datablock as object data.
  • Volume is datablock that contains a list of volume grids. These grids may either come from a file, or be procedurally generated by a modifier.
  • VolumeGrid contains one OpenVDB grid. For details on this data structure, see the OpenVDB documentation.

OpenVDB grids consist of:

  • Metadata: name and other fields.
  • Transform: linear (or perspective) transform from voxel index to object space.
  • Tree: a tree data structure of nodes, with leaf nodes that contain a grid of 8x8x8 voxels.

File Loading

Volume datablocks have a filepath, and if set the volume will be loaded from that file. The list of grids and their contents is loaded on-demand, when modifier evaluation, drawing, user interface or Python code needs it.

  • BKE_volume_load() loads the list of grids and their name, metadata and transform.
  • BKE_volume_grid_load() loads the grid tree and voxels into memory.

To share grid memory between original and CoW datablocks, and between volume datablocks using the same filepath, the grid memory is managed by a global volume cache. Only grids loaded from file are in this cache, procedurally generated grids are not, they are uniquely owned by one datablock. When the number of users of a grid in the cache drops to zero, it is immediately freed.

Different volume datablocks may need either only the list of grids and their metadata, or the actual grid tree. This is accounted for in the global volume cache, with a distinction between metadata users and tree users. If the number of tree users drops to zero, the grid tree is freed while its metadata may still remain in memory for metadata users.

Modifiers

Volume modifiers take a Volume as input and output a new Volume. The input volume should be considered read-only. The modifier can either create a new Volume with no grids, or make a copy of an existing Volume for editing. After copying, the new volume will still reference the same grid memory as the input (for memory efficiency), or may not have been loaded from disk yet.

To access the actual OpenVDB grid and its contents, one of the following functions must be used:

  • BKE_volume_grid_openvdb_for_metadata(): for reading metadata and transform only.
  • BKE_volume_grid_openvdb_for_read(): for reading only, ensures grid tree is loaded into memory.
  • BKE_volume_grid_openvdb_for_write(): for read and write, ensures grid tree is loaded into memory and not shared with any other volume datablock.

Modifiers must be implemented in C++, since OpenVDB grids are a C++ data structure.

Rendering

Volumes are rendered by Cycles, Eevee and workbench as dense grids stored in 3D textures.