Houdini Engine 1.9
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages

Table of Contents


Volumetric data can be thought of as 3D grids in space. In Houdini, volumes can represent two main types of objects: either fields in a fluid simulation, or the surface of an object (SDF). For example, in a single fluid simulation, there are many fields, eg. density, velocity, heat, temperature, fuel. These fields all come together to become a fluid. Volumes may contain two types of data, ints or floats, and it may be scalars (tupleSize == 1) or vectors (tupleSize > 1).

In Houdini, volumes may be represented in two different ways, as Houdini native volumes, or as VDBs. Houdini native volumes are dense whereas VDBs are sparse. The volume data representation you will be extracting / setting will be sparse, as the dense data is a special case of the sparse data. Therefore, instead of retrieving the volume data as one massive array, it is given out in smaller subarrays called tiles. Each tile refers to a cube subset of the volume. Each volume might have a different resolution for the size of the tile. At the time of writing, this should either be 8 or 16 (ie. 8x8x8 and 16x16x16).

To extract volumetric data through HAPI, we begin at the point of the process where we are extracting parts from geos. Whether a part contains volumetric data or not is given by HAPI_PartInfo::hasVolume. If this field is set to true, then more information can be obtained about the volume though the HAPI_GetVolumeInfo() call.

A HAPI_VolumeInfo struct is returned. Note that the HAPI_VolumeInfo::minX, HAPI_VolumeInfo::minY, HAPI_VolumeInfo::minZ, HAPI_VolumeInfo::xLength, HAPI_VolumeInfo::yLength, and HAPI_VolumeInfo::zLength fields do NOT refer to the spatial extents of the volume - notice they are integers and not floats. Instead, they refer to the range of valid "indices" into the volume. The quotes are around the term indices because to index into volume data, a 3-tuple of indices in each of x,y, and z are required. It is important to notice that the 3-tuple of integers may be negative, as each of HAPI_VolumeInfo::minX, HAPI_VolumeInfo::minY, and HAPI_VolumeInfo::minZ could be negative.


The HAPI_VolumeInfo::minX, HAPI_VolumeInfo::minY, HAPI_VolumeInfo::minZ, HAPI_VolumeInfo::xLength, HAPI_VolumeInfo::yLength, and HAPI_VolumeInfo::zLength fields tell us how to index into the overall volume, and the transform field tells us how to go from volume object space into world space, but we need to know how to map a voxel at a particular (i,j,k) index into object space. This mapping from (i,j,k) index into object space is given by the following pseudo-code:

indexToObject( int i, int j, int k, HAPI_VolumeInfo vol ):
vec3 pos = 2.0 * ( ( i, j, k ) - ( 0.5, 0.5, 0.5 ) )
if ( vol.hasTaper ):
taper( pos, vol );
pos = vol.transform.scale * pos
pos = rotate( pos, vol.transform.rotationEuler, vol.transform.rotationOrder )
pos = pos + vol.transform.position
return pos

The taper function pseudo-code is given as follows:

taper( vec3 pos, HAPI_VolumeInfo vol ):
zscale = ( 1 - pos.z ) * 0.5;
taperx = 1 + ( vol.xTaper - 1 ) * zscale;
tapery = 1 + ( vol.yTaper - 1 ) * zscale;
pos.x = pos.x * taperx;
pos.y = pos.y * tapery;
return pos;

Note that the situation of tapering is relatively rare in practice.

Tile Data

Knowing the size of each tile from the HAPI_VolumeInfo, we can retrieve each tile as a HAPI_VolumeTileInfo with the following functions:

The HAPI_VolumeTileInfo::minX, HAPI_VolumeTileInfo::minY, and HAPI_VolumeTileInfo::minZ fields denote the tile's position within the overall volume. Note that a tile may not have values at all of its voxels. This can happen in two cases: -@ when the tile straddles either the boundary for the entire volume, -@ or one of many boundaries within a VDB where there is sparse data.

In the first case, the invalid voxels will not be written to (ie. the input buffer at those locations will be left as is). Whether a voxel index is within the volume or not can be determined by checking if the index is in the range given by HAPI_VolumeInfo::minX, HAPI_VolumeInfo::minY, HAPI_VolumeInfo::minZ, HAPI_VolumeInfo::xLength, HAPI_VolumeInfo::yLength, and HAPI_VolumeInfo::zLength.

Note: If you have build 13.0.237 or earlier, the isValid field hasn’t yet been implemented. In that case, you test for the end of the the volume tiles by testing minX, minY, and minZ against MAX_INT.

Finally, the actual values in each tile can be retrieved with:

Given an index into the tile (i,j,k), and the component index c (0 for x, 1 for y, 2 for z), the value of the component c in the voxel is given by:

values[ k*tileSize*tileSize*tupleSize + j*tileSize*tupleSize + i*tupleSize + c ]