Class SoObliqueSlice
- All Implemented Interfaces:
SafeDisposable
SoVolumeData
node and the plane defined by the plane
field.
The SoVolumeData
node can be specified with dataSetId
. When this field is set to 0, the last SoVolumeData
node on state is used.
For a non-RGBA (scalar valued) volume, each voxel's RGBA value is determined by the current SoDataRange
and SoTransferFunction
. The current diffuse color and transparency (set, for example, with an SoMaterial
node) modify the appearance of the slice. This means that, for example, the current transparency can be used as a
global alpha value to modulate the overall opacity of the slice. For an RGBA volume each voxel's RGBA value comes directly from the volume data.
The interpolation
field controls how the texture is interpolated.
The alphaUse
field (SoSlice
) controls how the voxel's alpha component is used when drawing the slice.
Optionally a bump mapping effect may be applied. Normal vectors are automatically computed from the data value gradient. The enableBumpMapping
and bumpScale
fields (SoSlice
) control whether bump mapping is active and the intensity of the effect.
Notes:
- Transformation matrices:
The volume size and orientation (like geometry) can be modified by transformation nodes in the scene graph and this in turn modifies the appearance of volume visualization nodes. However the same transformation must be applied to the volume data node and all volume visualization nodes associated with that volume. So effectively any transformation nodes that affect the volume must be placed before the volume data node. - Plane normal:
The "polarity" of the plane normal (for example whether it is +Z or -Z) doesn't affect rendering the oblique slice. However it's very important if you also use that plane to define a clipping plane. The clipping plane will clip away everything on the side of the plane *opposite* the normal vector direction. So to clip away the "front" (+Z) of the volume set the normal to 0,0,-1. - Picking:
The entire slice is pickable, even where it is transparent as a result of the current transfer function. TheSoObliqueSliceDetail
class allows you to get the voxel position and value after picking. - Dragging:
It is possible to interactively translate and rotate slices using an Open Inventor dragger, e.g.SoTranslate1Dragger
. However the dragger's field values must be converted to anSbPlane
. For a dragger that has a convenient "plane" field that can be directly connected, see the ClipPlaneDragger article in the Resources section of the Open Inventor Forum: http://forum.openinventor.com/showthread.php?t=733 (registration is required to view this section of the forum). - Interpolation:
Interpolation is specified using theinterpolation
field. The default (LINEAR) does bi-linear interpolation between voxel values. The NEAREST value can be used to display individual voxels. For best image quality we recommend using the TRILINEAR or MULTISAMPLE_12 value. - Data range:
By default VolumeViz maps the entire range of the voxel's data type (e.g. 0..65535 for unsigned short) into the colormap. This is often correct for byte (8 bit) voxels, but seldom correct for 16 bit voxels and never correct for floating point voxels. Use anSoDataRange
node to specify the actual (or desired) range of data values to be mapped. Also use anSoDataRange
node to implement brightness/contrast control like the Window/Level setting commonly used with medical images. - Clipping:
Volume primitives can be clipped using a region of interest (SoROI
), geometry (SoVolumeClippingGroup
) and/or height fields (SoUniformGridClipping
). They are also clipped by OpenGL clipping planes (SoClipPlane
), but we recommend using the VolumeViz clipping nodes instead. - Material:
The color of each voxel is modulated by the current diffuse color in the traversal state. The default diffuse color is 0.8,0.8,0.8. This results in full intensity values in the color map being displayed as 80% intensity. Therefore we recommend adding anSoMaterial
node before the slice and setting its diffuseColor field to full white (1,1,1). - Transparency:
- Typically the color map (
SoTransferFunction
) used for volume rendering (SoVolumeRender
) assigns transparency (alpha < 1) to some voxel values. If you want to use the same color map for slice rendering, but render the slice completely opaque, set thealphaUse
field to ALPHA_OPAQUE. This overrides the alpha values in the color map (or an RGBA volume). However it does not affect transparency assigned using anSoMaterial
node.
- If you want to adjust the overall transparency of the slice, add an
SoMaterial
node and set its transparency field (keeping alphaUse set to ALPHA_AS_IS). Effectively a scale factor 1-transparency is applied to each voxel's alpha value.
- Intersecting transparent slices cannot be rendered correctly by the basic blending transparency algorithms. To render this case correctly, set the transparency algorithm to SORTED_PIXEL using the viewer class or
SoGLRenderAction
.
- Typically the color map (
- Voxel edges:
The edges of the voxels can also be rendered. See options in theSoVolumeRenderingQuality
node. - Custom shaders:
The currentSoVolumeShader
node, if any, allows custom shaders to be defined for special computation or rendering effects, including blending multiple volumes. - Composition with Multiple Data:
It is possible to compose datasets that have different dimensions, tile sizes and transformations.
In order to help fetch the correct data values in custom shaders, texture coordinates conversion functions are provided in the VolumeViz/vvizStructure.h shader include.
For instance,vec3 VVizTextureToTextureVec(in VVizDataSetId datasetSrc, in VVizDataSetId datasetDst, in vec3 texCoord);
The conversion is based solely on the transformations applied to each dataset, which are defined by their model matrix and their extent.
Please note that the model matrix of a dataset is defined by to theSoTransformation
nodes that are placed before theSoDataSet
node in the order of the traversal. - Performance:
- Tile size:
For backward compatibility, the default tile size is still only 64. This is quite small for modern CPU/GPU hardware. The smaller the tile size, the larger the total number of tiles that must be managed by VolumeViz. This overhead can be significant, especially for operations that require reloading the data textures on the GPU, for example, changing the data range (SoDataRange
). For smaller volumes, like 512^3, it can be efficient to set the tile size large enough to contain the entire volume. For very large volumes, larger tile sizes are efficient forSoVolumeRender
but somewhat inefficient for slice rendering because complete tiles must be loaded even though the slice only uses part of the data. Applications should experiment.
For volumes stored in LDM file format, the tile size must be specified when the volume is converted to LDM (seeSoConverter
and the "-t" option). For other data data formats the tile size can be specified using theSoVolumeData
node's ldmResourceParameters field, but only after setting the filename field or calling the setReader() method. - Tile cache policy: It specifies how the tiles are stored in CPU memory. The selected policy can significantly impact the data loading performance versus the CPU memory footprint. See
SoLDMResourceParameters.tileCachePolicy
for detail.
- Tile size:
For simple data sets, a basic VolumeViz rendering could be achieved with only a few nodes: minimally an SoVolumeData
node to identify the data set and one rendering node. However most data sets need at least some of the additional nodes shown here in order to get a correct and useful rendering. Most applications will need additional nodes to take advantage of region of interest, interaction, clipping and other VolumeViz features. Please consider the code shown here as simply a guideline and a starting point for exploring the many powerful features available in Open Inventor.
Note that some of the property nodes (data, material, color map, etc) will typically be shared by multiple rendering nodes. In other words the volume usually only needs to be loaded once, using a single SoVolumeData
node, then multiple slices and/or regions can be rendered using that data node.
Also note that this example is for a data volume, where each voxel can be considered a discrete sample from a continuous data field and interpolation should be used to compute values between voxel centers. If you are rendering a label volume, then each voxel is an "id" assigning that voxel to a specific material, object, etc. In this case, set the interpolation field to NEAREST to disable interpolation.
// Keep volume viz separate from geometry SoSeparator volSep = new SoSeparator(); root.addChild( volSep ); // Load volume data SoVolumeData volData = new SoVolumeData(); volData.fileName.setValue( "$OIVJHOME/data/VolumeViz/3DHead.vol" ); volSep.addChild( volData ); // Set range of data values to visualize. // Not required for 8-bit voxels, critical for larger data types. // The getMinMax() call may be expensive for non-LDM file formats. SoDataRange volRange = new SoDataRange(); if (volData.getDatumSize() > 1) { double[] minmax; minmax = volData.getDoubleMinMax(); volRange.min.setValue( minmax[0] ); volRange.max.setValue( minmax[1] ); } volSep.addChild( volRange ); // Load opaque intensity ramp SoTransferFunction volTF = new SoTransferFunction(); volTF.predefColorMap.setValue( SoTransferFunction.PredefColorMaps.INTENSITY ); volSep.addChild( volTF ); // Display slice at full intensity SoMaterial volMat = new SoMaterial(); volMat.diffuseColor.setValue( 1, 1, 1 ); volSep.addChild( volMat ); // Remove tile boundary artifacts while moving. SoVolumeShader volShader = new SoVolumeShader(); volShader.interpolateOnMove.setValue( true ); volSep.addChild( volShader ); // Display a Z axis slice at center of volume SoObliqueSlice slice = new SoObliqueSlice(); SbBox3f volext = volData.extent.getValue(); SbVec3f center = volext.getCenter(); slice.plane.setValue( new SbPlane( new SbVec3f(0,0,1), center.getZ() ) ); slice.interpolation.setValue( SoVolumeShape.Interpolations.MULTISAMPLE_12 ); volSep.addChild( slice );
File format/default:
ObliqueSlice {
dataSetId | 0 |
plane | 0, 0, 1, 0 |
interpolation | LINEAR |
alphaUse | ALPHA_BINARY |
useRGBA | false |
alternateRep | NULL |
enableBumpMapping | false |
bumpScale | 1.0 |
Action behavior:
SoGLRenderAction
Draws a textured polygon based on current SoVolumeData
, SoTransferFunction
, and SoROI
nodes.
SoGetBoundingBoxAction
Computes the bounding box that encloses the slice.
- See Also:
-
Nested Class Summary
Nested classes/interfaces inherited from class com.openinventor.volumeviz.nodes.SoSlice
SoSlice.AlphaUses
Nested classes/interfaces inherited from class com.openinventor.volumeviz.nodes.SoVolumeShape
SoVolumeShape.Compositions, SoVolumeShape.Interpolations
Nested classes/interfaces inherited from class com.openinventor.inventor.nodes.SoShape
SoShape.ShapeTypes
Nested classes/interfaces inherited from class com.openinventor.inventor.nodes.SoNode
SoNode.RenderModes
Nested classes/interfaces inherited from class com.openinventor.inventor.Inventor
Inventor.ConstructorCommand
-
Field Summary
FieldsModifier and TypeFieldDescriptionfinal SoSFInt32
Specifies theSoVolumeData
node to use.final SoSFPlane
Plane defining the slice.Fields inherited from class com.openinventor.volumeviz.nodes.SoSlice
alphaUse, alternateRep, bumpScale, enableBumpMapping, largeSliceSupport, useRGBA
Fields inherited from class com.openinventor.volumeviz.nodes.SoVolumeShape
composition, interpolation
Fields inherited from class com.openinventor.inventor.nodes.SoShape
boundingBoxIgnoring
Fields inherited from class com.openinventor.inventor.Inventor
VERBOSE_LEVEL, ZeroHandle
-
Constructor Summary
Constructors -
Method Summary
Methods inherited from class com.openinventor.volumeviz.nodes.SoVolumeShape
setRenderProgress
Methods inherited from class com.openinventor.inventor.nodes.SoShape
getShapeType, isPrimitiveRestartAvailable, isPrimitiveRestartAvailable
Methods inherited from class com.openinventor.inventor.nodes.SoNode
affectsState, callback, copy, copy, distribute, doAction, getAlternateRep, getBoundingBox, getByName, getMatrix, getPrimitiveCount, getRenderEngineMode, getRenderUnitID, GLRender, GLRenderBelowPath, GLRenderInPath, GLRenderOffPath, grabEventsCleanup, grabEventsSetup, handleEvent, isBoundingBoxIgnoring, isOverride, pick, rayPick, search, setOverride, touch, write
Methods inherited from class com.openinventor.inventor.fields.SoFieldContainer
copyFieldValues, copyFieldValues, enableNotify, fieldsAreEqual, get, getAllFields, getEventIn, getEventOut, getField, getFieldName, hasDefaultValues, isNotifyEnabled, set, setToDefaults
Methods inherited from class com.openinventor.inventor.misc.SoBase
dispose, getName, isDisposable, isSynchronizable, setName, setSynchronizable
Methods inherited from class com.openinventor.inventor.Inventor
getNativeResourceHandle
-
Field Details
-
dataSetId
Specifies theSoVolumeData
node to use. This is useful when datasets of different dimensions are present in the scene graph. Please seeSoMultiDataSeparator
for more details.When set to 0, the last
SoVolumeData
node on state is used. Default is 0.- Since:
- Open Inventor 10.11.0
-
plane
Plane defining the slice. The default plane corresponds to the XY plane.
-
-
Constructor Details
-
SoObliqueSlice
public SoObliqueSlice()Constructor.
-