The SoVolumeMask( C++ | Java | .NET ) node specifies an arbitrary voxel-based region of a volume data set (SoVolumeData( C++ | Java | .NET )). A volume mask is itself a data volume consisting of binary values. Zero values are "false" and non-zero values are "true". A large number of masks may be defined simultaneously, using an SoVolumeMask( C++ | Java | .NET ) node for each one, and mask regions may overlap if desired.
SoVolumeMask( C++ | Java | .NET ) is derived from SoVolumeData( C++ | Java | .NET ). Like SoVolumeData( C++ | Java | .NET ) it accesses its data through an SoVolumeReader( C++ | Java | .NET ) class. I.e. the data may be in a file or in memory (or any data source using a custom volume reader). The mask volume can be any data type, but unsigned byte is currently the most memory efficient representation.
SoVolumeMask( C++ | Java | .NET ) nodes must follow these rules:
Each mask volume must have exactly the same voxel dimensions and tile size value as the data volume it is applied to.
All SoVolumeMask( C++ | Java | .NET ) nodes must be children of an SoVolumeMaskGroup( C++ | Java | .NET ) node.
The SoVolumeData( C++ | Java | .NET ) node and the SoVolumeMaskGroup( C++ | Java | .NET ) nodes must be children of an SoMultiDataSeparator( C++ | Java | .NET ) node.
The SoVolumeData( C++ | Java | .NET ) and associated SoVolumeMask( C++ | Java | .NET ) nodes must each have a different value assigned to their dataSetId field (see SoDataSet( C++ | Java | .NET )).
Currently SoVolumeMask( C++ | Java | .NET ) nodes only affect volume rendering (SoVolumeRender( C++ | Java | .NET )). They do not affect slice rendering or other VolumeViz primitives.
SoVolumeMask( C++ | Java | .NET ) can be used to clip the data volume on a per-voxel basis. But the mask mechanism is much more powerful than that. Each region can have its own transfer function (color map) using SoTransferFunction( C++ | Java | .NET ) nodes. Each region can also have its own draw style (volume rendering, isosurface or boundary) using SoVolumeDataDrawStyle( C++ | Java | .NET ) nodes. Each region, including the original unmasked volume, is only visible if there exists a transfer function (SoTransferFunction( C++ | Java | .NET )) with the same id value.
Mask regions:
A single SoVolumeMask( C++ | Java | .NET ) node effectively defines two regions:
False voxels (where the mask voxel = 0), and
True voxels (where is mask voxel != 0).
Because intersecting regions are allowed, two SoVolumeMask( C++ | Java | .NET ) nodes define (up to) four regions:
False (where all masks are 0),
True only in mask 1,
True only in mask 2, and
True in more than one mask (intersection region).
Each additional mask defines one additional region (voxels that are true only in that mask).
In addition, if there exists a transfer function with the same id as the original volume (SoVolumeData( C++ | Java | .NET ) node), the color value from that transfer function is combined with the color value from the mask region's transfer function.
Transfer functions:
A separate transfer function can be specified for each of these regions using SoTransferFunction( C++ | Java | .NET ) nodes. The transfer function nodes may be placed under the SoVolumeMaskGroup( C++ | Java | .NET ) node, but this is not required.
A transfer function is associated with a specific mask (i.e. with the voxels that are true only in that mask), by setting the SoTransferFunction( C++ | Java | .NET ) node's transferFunctionId equal to the mask's dataSetId . If there is no transfer function with the same id as the mask, then that mask is ignored.
A transfer function is associated with all "false" voxels (voxels that do not belong to any mask) by setting its transferFunctionId equal to zero. If there is no transfer function with id = 0, then "false" voxels are not rendered.
A transfer function is associated with all "intersection" voxels (voxels that belong to more than one mask) by setting its transferFunctionId equal to SoVolumeMaskGroup( C++ | Java | .NET )::TRANSFERFUNCTION_INTERSECTION_ID. If there is no transfer function with this id value, then intersection voxels (if any) are rendered using the default GRAY color map.
Draw Styles:
A separate draw style can be specified for each mask region and for the intersection voxels (but not for false voxels) using SoVolumeDataDrawStyle( C++ | Java | .NET ) nodes:
Unlike transfer functions, a draw style is associated with a mask (voxels that are true only in that mask) by traversal order. In other words, each mask uses the draw style that is current when the mask is traversed. So you need to put SoVolumeDataDrawStyle( C++ | Java | .NET ) nodes under the SoVolumeMaskGroup( C++ | Java | .NET ), alternating draw style, mask, draw style, mask.
A draw style is associated with all "intersection" voxels (voxels that belong to more than one mask) by placing it before the SoVolumeMaskGroup( C++ | Java | .NET ) node in the scene graph.