1.6.1. Height Field Overview

The height field rendering nodes are actually a solution to the challenge of rendering very large triangle surfaces. So they are not exactly volume visualization, but the nodes are part of VolumeViz for a couple reasons. First, they use the same LDM data manager and (optionally) the LDM file format to manage the height values. We’ll talk about the advantages of this solution in the next paragraph. Second, they are very useful to represent large “horizon” surfaces in oil and gas applications and these surfaces are normally rendered together with seismic data volumes. However height field rendering is also useful in other application areas, for example to represent terrain with height mapped to color or with “draped” imagery. See the simpleHorizonRGBA example in the SDK (src/VolumeViz/examples).

A horizon surface is an imaginary surface usually indicated by a reflection in the seismic volume data and usually corresponding to a layer of rock or the transition between two regions of rock having different properties. Most horizon surfaces are defined by a regular grid of time/depth values. So we can consider the surface to be a height field. In other words, the XY locations of the values are implicit and we only need to store the Z values. Because the grid normally has the same line/crossline dimensions as the seismic volume, the resulting geometry can easily contain three or four million triangles for each surface. And a typical visualization can contain multiple surfaces.

Because the actual volume data already has huge system memory requirements, loading these surfaces as triangle geometry may be limited by the available system memory. However loading just the height values allows loading significantly more surfaces in the same amount of memory. And because rendering the actual volume data is already GPU intensive, rendering these surfaces at full resolution may not be possible at interactive frame rates. Luckily it is not normally necessary to render the entire surface at full resolution because the triangles would be very small. So we can apply LDM tiling and multi-resolution techniques similar to what we use for volume visualization.

To maintain performance the application can control and limit the number of generated triangles for all height fields in the scene using a SoComplexity( C++ | Java | .NET ) node. Similar to limiting memory for volume rendering, limiting the number of triangles may force the use of lower resolution data tiles from the height field volume. VolumeViz will use the same optimization techniques (view culling, distance from the camera, etc) to generate the best possible image. The number of triangles can also be reduced temporarily while the user is interacting with the scene.

The height field data is specified using an SoHeightFieldGeometry( C++ | Java | .NET ) node. VolumeViz effectively treats the height field as a data volume whose Z dimension is 1. Just like other data volumes, height fields may be pre-converted to LDM format for optimized loading, be accessed through a custom volume reader or be given to VolumeViz in-memory. All data types are supported, although floating point is the most common for height fields. The application can specify an undefined value. Voxels with this value are not rendered. This useful to represent “holes” in the surface.

A height field is rendered using an SoHeightFieldRender( C++ | Java | .NET ) node.

One or more properties associated with the height field can be specified using an SoHeightFieldProperty( C++ | Java | .NET ) node. Each property is another data volume with the same dimensions as the height field. VolumeViz provides default shaders that conveniently color the surface using a single property. It is also possible to combine multiple properties using a custom shader program, in the same way that you would combine multiple volumes.

Multiple very large seismic horizon surfaces (courtesy CGG Veritas)

Figure 1.85. Multiple very large seismic horizon surfaces (courtesy CGG Veritas)


The appearance of height field primitives is affected by the SoMaterial( C++ | Java | .NET ) and SoTransferFunction( C++ | Java | .NET ) (color map) nodes described in Section 1.3, “Appearance”. The appearance of height fields is affected by the interpolation property (NEAREST and LINEAR only) similar to slices, but not by the alphaUse or bump mapping properties. In addition, custom shader functions may be applied to height fields for special computation or rendering effects, for example co-blending multiple volumes, as described in Section 1.8, “Shaders” and Section 1.9.3, “Combining volumes”.

Like other Open Inventor geometry, the appearance of height field primitives is automatically affected by light nodes in the scene graph, e.g. the viewer headlight and SoDirectionalLight( C++ | Java | .NET ) nodes. Note that this is different than volume rendering, for which lighting must be explicitly enabled and only the first light node traversed is used. Like other geometry, lighting can give important visual cues about the shape of objects and the relationships of objects in the scene. However when interpreting the color of voxels the user must be aware that lighting modifies the intensity (and possibly the color) of the slice. By default, turning off all lights in the scene will cause height fields to be rendered black. To prevent lighting from affecting a height field and render with its true colors, use an SoLightModel( C++ | Java | .NET ) node with the model field set to BASE_COLOR.

Like other Open Inventor geometry, when lighting is enabled height field primitives can cast and receive shadows. Shadows may be useful in some applications to give visual cues about the relationships (particularly depth ordering) of objects in the scene. To enable shadows, put the primitives under an SoShadowGroup( C++ | Java | .NET ) node and set its method field to VARIANCE_SHADOW_MAP.

The geometry of height fields can be clipped by clip planes, SoROI( C++ | Java | .NET ), polygon clipping and height field clipping as described in Section 1.7, “Clipping”. By default height fields are pickable (even where transparent). The detail class SoHeightFieldDetail( C++ | Java | .NET ) allows you to query the position and value of the picked voxel as well as the properties associated with the height field.