Class SoOrthoSlice
- All Implemented Interfaces:
SafeDisposable
SoVolumeData node. The slice orientation and position are defined by the axis and sliceNumber fields.
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) modifies the appearance of the slice. This means that, for example, the current transparency can be used as an
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:
- Drawing position:
TheSoOrthoSlicegeometry passes through the center of the voxels in the specified slice. So, for example, an ortho slice with sliceNumber = 0 will be drawn one-half voxel size (on the slice axis) in from the bounding box of the volume. This is slightly different fromSoVolumeSkin. A volume skin is approximately the same as six ortho slices, but each face of the skin is drawn at the outer edge of the voxel. - 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. - Picking:
The entire slice is pickable, even where it is transparent as a result of the current transfer function. TheSoOrthoSliceDetailclass 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 position in XYZ space must be converted to a slice number. For a dragger that is specific to ortho slices, see the classSoOrthoSliceDragger. - Interpolation:
Interpolation is specified using theinterpolationfield. 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 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 anSoDataRangenode to specify the actual (or desired) range of data values to be mapped. Also use anSoDataRangenode 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.
Optionally, this node also defines a clipping plane. Similar toSoClipPlane, this clipping plane affects all subsequent geometry, includingSoVolumeRender, but does not of course affect the ortho slice itself. TheclippingandclippingSidefields control whether clipping is active and which half-space is clipped. Clipping side FRONT means that the clip plane (removes) clips away geometry in the positive direction on the slice axis. - Border:
Border can be enabled with theenableBorderfield, which allows to draw a border around the slice following volume boundary. However, the border is invisible when anSoROI(orSoROIManip) is used in the scene. - 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 anSoMaterialnode 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. You can use the same color map for slice rendering, but note that the default value of thealphaUsefield (since Open Inventor 10.0) is ALPHA_OPAQUE, meaning that alpha values in the color map are ignored. However, it does not affect the transparency assigned by anSoMaterialnode.
- If you want to adjust the overall transparency of the slice, set the
alphaUsefield to ALPHA_AS_IS, add anSoMaterialnode and set its transparency field. 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 theSoVolumeRenderingQualitynode. - Custom shaders:
The currentSoVolumeShadernode, 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,
can be used to convert texture coordinates related to one dataset to texture coordinates related to another dataset.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 theSoTransformationnodes that are placed before theSoDataSetnode in the order of the traversal. - Large Slice mode:
When the "large slice" mode is enabled (seeSoSlice.largeSliceSupport), if all the required full resolution tiles have already been loaded, then the slice data is taken from LDM system memory cache as usual. But if some required tiles are not currently in memory, the required slice data will be loaded directly from the volume reader without loading the complete tiles. This reduces disk I/O and reduces the amount of system memory required to display the slice at full resolution, so larger (or more) slices can be displayed. The required tiles are then scheduled to be loaded asynchronously in case adjacent slices are displayed later. For example, loading a 1024x1024SoOrthoSlicefrom an 8-bit dataset with 128x128x128 tiles would normally require loading 1024x1024x128 bytes of data (as complete tiles). With largeSliceSupport enabled, only 1024x1024 bytes (maximum) of data need to be loaded (in the worst case where no high resolution data is currently in memory). - 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 forSoVolumeRenderbut somewhat inefficient for slice rendering because complete tiles must be loaded even though the slice only uses a 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 (seeSoConverterand the "-t" option). For other data formats the tile size can be specified using theSoVolumeDatanode'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.tileCachePolicyfor details. - Compressed textures
For performance reasons,SoOrthoSliceaccumulates small textures into a bigger one. When using compressed RGBA textures (viaSoDataSet's field useCompressedTexture), this optimization cannot be done. If you want to favor performance rather than memory usage, you should disable compression (enabled by default if supported by the graphic card)
- Tile size:
- Medical data axes:
The three standard axes (or viewing planes) are Axial, Coronal and Sagittal. How these axes correspond to the IJK axes in voxel space and the XYZ axes in 3D space depends on the data set. However DICOM volumes typically have LPS (Left, Posterior, Superior) orientation and in this case:- Axial is the Z axis
i.e., toward the head (Superior) is the K / +Z / Axial axis.
- Coronal is the Y axis
i.e., toward the back of the body (Posterior) is the J / +Y / Coronal axis.
- Sagittal is the X axis
i.e., toward the left side of the body (Left) is the I / +X / Sagittal axis.
- Axial is the Z axis
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.
// Keeps volume viz separate from geometry SoSeparator volSep = new SoSeparator(); root.addChild(volSep); // Loads volume data SoVolumeData volData = new SoVolumeData(); volData.fileName.setValue( "$OIVJHOME/data/VolumeViz/3DHead.vol" ); volSep.addChild( volData ); // Sets 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 ); // Loads opaque intensity ramp SoTransferFunction volTF = new SoTransferFunction(); volTF.predefColorMap.setValue( SoTransferFunction.PredefColorMaps.INTENSITY ); volSep.addChild( volTF ); // Displays slice at full intensity SoMaterial volMat = new SoMaterial(); volMat.diffuseColor.setValue( 1, 1, 1 ); volSep.addChild( volMat ); // Removes tile boundary artifacts while moving. SoVolumeShader volShader = new SoVolumeShader(); volShader.interpolateOnMove.setValue( true ); volSep.addChild( volShader ); // Displays a Z axis slice at center of volume SoOrthoSlice slice = new SoOrthoSlice(); SbVec3i32 voldim = volData.data.getSize(); slice.axis.setValue( SoOrthoSlice.AxisType.Z ); slice.sliceNumber.setValue( voldim.getZ() / 2 ); slice.interpolation.setValue( SoVolumeShape.Interpolations.MULTISAMPLE_12 ); volSep.addChild( slice );
File format/default:
OrthoSlice {
| dataSetId | 0 |
| sliceNumber | 0 |
| axis | Z |
| interpolation | LINEAR |
| alphaUse | ALPHA_BINARY |
| useRGBA | false |
| clipping | false |
| clippingSide | BACK |
| alternateRep | NULL |
| enableBumpMapping | false |
| bumpScale | 1.0 |
| enableBorder | false |
| borderColor | 0.84 0.43 0.02 |
| borderWidth | 2.0 |
| enableImage | true |
Action behavior:
SoGLRenderAction
Draws a textured rectangle based on current SoVolumeData, SoTransferFunction, and SoROI nodes. Sets: SoClipPlaneElement
SoGetBoundingBoxAction
Computes the bounding box that encloses the slice.
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumSlice Axis (see discussion of medical data axes in the class description)static enumClipping Side mode.Nested classes/interfaces inherited from class com.openinventor.volumeviz.nodes.SoSlice
SoSlice.AlphaUsesNested classes/interfaces inherited from class com.openinventor.volumeviz.nodes.SoVolumeShape
SoVolumeShape.Compositions, SoVolumeShape.InterpolationsNested classes/interfaces inherited from class com.openinventor.inventor.nodes.SoShape
SoShape.ShapeTypesNested classes/interfaces inherited from class com.openinventor.inventor.nodes.SoNode
SoNode.RenderModesNested classes/interfaces inherited from class com.openinventor.inventor.Inventor
Inventor.ConstructorCommand -
Field Summary
FieldsModifier and TypeFieldDescriptionfinal SoSFEnum<SoOrthoSlice.AxisType> Slice axis (X, Y, or Z).final SoSFColorBorder color.final SoSFFloatBorder width in pixels.final SoSFBoolActivate/deactivate a clipping plane on a per-slice basis.Specifies the clipping side.final SoSFInt32Specifies theSoVolumeDatanode to use.final SoSFBoolEnables drawing the border.final SoSFBoolEnables drawing the slice image.final SoSFUInt32Slice number.Fields inherited from class com.openinventor.volumeviz.nodes.SoSlice
alphaUse, alternateRep, bumpScale, enableBumpMapping, largeSliceSupport, useRGBAFields inherited from class com.openinventor.volumeviz.nodes.SoVolumeShape
composition, interpolationFields inherited from class com.openinventor.inventor.nodes.SoShape
boundingBoxIgnoringFields inherited from class com.openinventor.inventor.Inventor
VERBOSE_LEVEL, ZeroHandle -
Constructor Summary
Constructors -
Method Summary
Methods inherited from class com.openinventor.volumeviz.nodes.SoVolumeShape
setRenderProgressMethods inherited from class com.openinventor.inventor.nodes.SoShape
getShapeType, isPrimitiveRestartAvailable, isPrimitiveRestartAvailableMethods 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, writeMethods inherited from class com.openinventor.inventor.fields.SoFieldContainer
copyFieldValues, copyFieldValues, enableNotify, fieldsAreEqual, get, getAllFields, getEventIn, getEventOut, getField, getFieldName, hasDefaultValues, isNotifyEnabled, set, setToDefaultsMethods inherited from class com.openinventor.inventor.misc.SoBase
dispose, getName, isDisposable, isSynchronizable, setName, setSynchronizableMethods inherited from class com.openinventor.inventor.Inventor
getNativeResourceHandle
-
Field Details
-
dataSetId
Specifies theSoVolumeDatanode to use. This is useful when datasets of different dimensions are present in the scene graph. Please seeSoMultiDataSeparatorfor more details.When set to 0, the last
SoVolumeDatanode on state is used. Default is 0.- Since:
- Open Inventor 10.11.0
-
sliceNumber
Slice number. -
axis
Slice axis (X, Y, or Z). . Default is Z. -
clippingSide
Specifies the clipping side. . Default is BACK. Clipping side FRONT means that the clip plane (removes) clips away geometry in the positive direction on the slice axis. BACK means that the clip plane clips away geometry in the negative direction on the slice axis.alphaUse= ALPHA_BINARY
interpolation= LINEARalphaUse= ALPHA_OPAQUE
interpolation= LINEARalphaUse= ALPHA_BINARY
interpolation= NEAREST
These figures show an ortho slice clipping a data volume. Right:
Bottom left:
Bottom right:



-
clipping
Activate/deactivate a clipping plane on a per-slice basis. Optionally, this node also defines a clipping plane. Similar toSoClipPlane, this clipping plane affects all subsequent geometry, includingSoVolumeRender, but does not of course affect the ortho slice itself. TheclippingSidefield controls which half-space is clipped. -
enableBorder
Enables drawing the border. Default is false.- Since:
- Open Inventor 10.10
-
borderColor
Border color. Default is [0.84, 0.43, 0.02] (orange luminance 55%).- Since:
- Open Inventor 10.10
-
borderWidth
Border width in pixels. Default is 2. For more information about borderWidth units: seeSoDrawStyle.lineWidth- Since:
- Open Inventor 10.10
-
enableImage
Enables drawing the slice image. Default is true. Note that setting this field to false makes the slice image invisible, but the slice is still detectable by picking if the border is enabled.Example of a typical use case : The folling code shows how to use a boolean engine to disable the image rendering while dragging.
SoBoolOperation engine = new SoBoolOperation(); engine.a.connectFrom(dragger.isActive); orthoslice.enableImage.connectFrom(engine.inverse); Another typical usecase is if you want to display the slice image in a 2D view and also show only the slice position in a 3D view (without the slice image).
- Since:
- Open Inventor 10.10
-
-
Constructor Details
-
SoOrthoSlice
public SoOrthoSlice()Constructor.
-