The Annotated VRML 97 Reference

1 Intro     Concepts     3 Nodes     4 Fields/Events    Conformance
A Grammar     B Java     C JavaScript     D Examples     E Related Info    References
Quick Java         Quick JavaScript         Quick Nodes   
 

  About the Book
  
Help
  Copyright © 1997-99
  Purchase the book from Amazon.com

Chapter 3:
Node Reference


Intro
Anchor
Appearance
AudioClip
Background
Billboard
Box
Collision
Color
ColorInterpolator
Cone
Coordinate
CoordinateInterpolator
Cylinder
CylinderSensor
DirectionalLight
ElevationGrid
Extrusion
Fog
FontStyle
Group
ImageTexture
IndexedFaceSet
IndexedLineSet
Inline
LOD
Material
MovieTexture
NavigationInfo
Normal
NormalInterpolator
OrientationInterpolator
PixelTexture
PlaneSensor
PointLight
PointSet
PositionInterpolator
ProximitySensor
ScalarInterpolator
Script
Shape
Sound
Sphere
SphereSensor
SpotLight
Switch
Text
TextureCoordinate
TextureTransform
TimeSensor
TouchSensor
Transform
Viewpoint
VisibilitySensor
WorldInfo

+3.17 ElevationGrid

ElevationGrid { 
  eventIn      MFFloat  set_height
  exposedField SFNode   color             NULL
  exposedField SFNode   normal            NULL
  exposedField SFNode   texCoord          NULL
  field        MFFloat  height            []      # (-INF,INF)
  field        SFBool   ccw               TRUE
  field        SFBool   colorPerVertex    TRUE
  field        SFFloat  creaseAngle       0       # [0,INF]
  field        SFBool   normalPerVertex   TRUE
  field        SFBool   solid             TRUE
  field        SFInt32  xDimension        0       # [0,INF)
  field        SFFloat  xSpacing          1.0     # (0,INF)
  field        SFInt32  zDimension        0       # [0,INF)
  field        SFFloat  zSpacing          1.0     # (0,INF)
}

The ElevationGrid node specifies a uniform rectangular grid of varying height in the Y=0 plane of the local coordinate system. The geometry is described by a scalar array of height values that specify the height of a surface above each point of the grid.

TIP: The ElevationGrid node is a good candidate for the floor or terrain of the scene since it provides better compression than an IndexedFaceSet and thus shorter download time. It is best to divide the scene into regions to allow the browser to perform rendering optimizations. Thus, rather than creating a single ElevationGrid that spans the entire floor or terrain of the world, it is better to create a series of ElevationGrids that grid together to form the entire floor or terrain of the world. Choose a size that also lends itself to effective level of detail. Then, create an LOD for each ElevationGrid node to increase rendering performance for sections that are a reasonable distance away. Experiment with different sizes by conducting performance tests in the browser. Be careful to match the seams between the various levels of adjacent ElevationGrids.

The xDimension and zDimension fields indicate the number of elements of the grid height array in the X and Z directions. Both xDimension and zDimension must be greater than or equal to zero. The vertex locations for the rectangles are defined by the height field and the xSpacing and zSpacing fields:

  • The height field is an xDimension by zDimension array of scalar values representing the height above the grid for each vertex.
  • The xSpacing and zSpacing fields indicates the distance between vertices in the X and Z directions respectively, and shall be > 0.

Thus, the vertex corresponding to the point P[i, j] on the grid is placed at:

    P[i,j].x = xSpacing × i
    P[i,j].y = height[ i + j × xDimension]
    P[i,j].z = zSpacing × j

    where 0 <= i < xDimension and 0 <= j < zDimension,
    and P[0,0] is height[0] units above/below the origin
    of the local coordinate system

The set_height eventIn allows the height MFFloat field to be changed to support animated ElevationGrid nodes.

The color field specifies per-vertex or per-quadrilateral colours for the ElevationGrid node depending on the value of colorPerVertex. If the color field is NULL, the ElevationGrid node is rendered with the overall attributes of the Shape node enclosing the ElevationGrid node (see "2.14 Lighting model").

The colorPerVertex field determines whether colours specified in the colour field are applied to each vertex or each quadrilateral of the ElevationGrid node. If colorPerVertex is FALSE and the color field is not NULL, the color field shall specify a Color node containing at least (xDimension-1)×(zDimension-1) colours; one for each quadrilateral, ordered as follows:

    QuadColor[i,j] = Color[ i + j × (xDimension-1)]

    where 0 <= i < xDimension-1 and 0 <= j < zDimension-1,
    and QuadColor[i,j] is the colour for the quadrilateral
    defined by height[i+j×xDimension],
    height[(i+1)+j×xDimension],
    height[(i+1)+(j+1)×xDimension] and
    height[i+(j+1)×xDimension]

If colorPerVertex is TRUE and the color field is not NULL, the color field shall specify a Color node containing at least xDimension × zDimension colours, one for each vertex, ordered as follows:

    VertexColor[i,j] = Color[ i + j × xDimension]

    where 0 <= i < xDimension and 0 <= j < zDimension,
    and VertexColor[i,j] is the colour for the vertex defined
    by height[i+j×xDimension]

The normal field specifies per-vertex or per-quadrilateral normals for the ElevationGrid node. If the normal field is NULL, the browser shall automatically generate normals, using the creaseAngle field to determine if and how normals are smoothed across the surface (see "2.6.3.5 Crease angle field").

The normalPerVertex field determines whether normals are applied to each vertex or each quadrilateral of the ElevationGrid node depending on the value of normalPerVertex. If normalPerVertex is FALSE and the normal node is not NULL, the normal field shall specify a Normal node containing at least (xDimension-1)×(zDimension-1) normals; one for each quadrilateral, ordered as follows:

    QuadNormal[i,j] = Normal[ i + j × (xDimension-1)]

    where 0 <= i < xDimension-1 and 0 <= j < zDimension-1,
    and QuadNormal[i,j] is the normal for the quadrilateral
    defined by height[i+j×xDimension],
    height[(i+1)+j×xDimension], height[(i+1)+(j+1)×xDimension]
    and height[i+(j+1)×xDimension]

If normalPerVertex is TRUE and the normal field is not NULL, the normal field shall specify a Normal node containing at least xDimension × zDimension normals; one for each vertex, ordered as follows:

    VertexNormal[i,j] = Normal[ i + j × xDimension]

    where 0 <= i < xDimension and 0 <= j < zDimension,
    and VertexNormal[i,j] is the normal for the vertex
    defined by height[i+j×xDimension]

The texCoord field specifies per-vertex texture coordinates for the ElevationGrid node. If texCoord is NULL, default texture coordinates are applied to the geometry. The default texture coordinates range from (0,0) at the first vertex to (1,1) at the last vertex. The S texture coordinate is aligned with the positive X-axis, and the T texture coordinate with positive Z-axis. If texCoord is not NULL, it shall specify a TextureCoordinate node containing at least (xDimension)×(zDimension) texture coordinates; one for each vertex, ordered as follows:

    VertexTexCoord[i,j]
             = TextureCoordinate[ i + j × xDimension]

    where 0 <= i < xDimension and 0 <= j < zDimension,
    and VertexTexCoord[i,j] is the texture coordinate for the
    vertex defined by height[i+j×xDimension]

The ccw, solid, and creaseAngle fields are described in "2.6.3 Shapes and geometry."

By default, the quadrilaterals are defined with a counterclockwise ordering. Hence, the Y-component of the normal is positive. Setting the ccw field to FALSE reverses the normal direction. Backface culling is enabled when the solid field is TRUE.

See Figure 3-20 for a depiction of the ElevationGrid node.

Figure 3-20: ElevationGrid node

TIP: Note that the default texture mapping produces a texture that is upside down when viewed from the positive Z-axis. To orient the texture to a more intuitive mapping, use a TextureTransform node to reverse the t texture coordinate, like this:
     Shape { 
       appearance Appearance { 
         textureTransform TextureTransform { scale 1 -1 } 
       } 
       geometry ElevationGrid { ... } 
     } 

This will produce a compact ElevationGrid with texture mapping that aligns to the natural orientation of the image. Note that this only works if the texture is repeated (default). If the texture is not repeated, you need to set the translation field of TextureTransform to translation 0 1. Alternatively, you can specify texture coordinates in the texCoord field that map the first height coordinate to an s and t of (0,1), the last height to (1,0) and so on; this will produce larger files, though.

TECHNICAL NOTE: Most interactive renderers do not draw quadrilaterals directly, but instead split them into triangles before rendering. The VRML specification does not specify how this should be done for ElevationGrid. Implementations are free to do whatever their underlying rendering libraries do. If your ElevationGrids are highly irregular, forming highly nonplanar quadrilaterals, then results may vary between implementations.

TECHNICAL NOTE: ElevationGrid is specified in the geometry field of a Shape node. Like all other geometry nodes, it may not be directly used as the child of a grouping node.

ElevationGrid was added to VRML 2.0 as a compact way of representing terrain. It is not a fundamental node; its functionality is a subset of what can be accomplished with the more general IndexedFaceSet node. Because terrain is common in virtual worlds (and because 2D grids with a value at each grid point are a very common data type used in many different applications) and because ElevationGrid is so much smaller than the equivalent IndexedFaceSet, it was added to the specification. For example, a 10 × 10 ElevationGrid requires a specification of 10 × 10 = 100 heights, plus two integers and two floats for the dimensions and spacing, or 102 floating point and two integer values. Accomplishing the equivalent using an IndexedFaceSet requires 10 × 10 = 100 3D vertices, plus 81 × 5 = 405 integer indices (81 quadrilaterals plus end-of-face markers), or 300 floating point and 405 integer values. Even assuming that compression will make integer indices one-fourth as big as floating point coordinates, the Elevation-Grid is still about four times smaller.

The height field of ElevationGrid is not completely exposed; you can set it using set_height, but there is no height_changed eventOut that you can route from or read from a Script. This was done to allow efficient implementations that convert ElevationGrids into the equivalent IndexedFaceSet (or whatever representation is best for the underlying rendering library). If height were exposed, then such implementations would be forced to maintain the height array. Since it isn't, implementations can free that storage after the conversion is done.

EXAMPLE (click to run): The following example illustrates use of the ElevationGrid node. Note the default texture map orientation on the first ElevationGrid and how TextureTransform is used on the second ElevationGrid to orient the texture more naturally:
#VRML V2.0 utf8
Transform { children [
  Shape {
    geometry DEF EG ElevationGrid { 
      xDimension 5
      xSpacing 1
      zDimension 4
      zSpacing 1
      height [          # 5x4 array of heights
        0 .707 1 .707 0
        0 .47 .667 .47 0
        0 .236 .33 .236 0
        0 0 0 0 0
      creaseAngle 0.8
    }
    appearance Appearance { 
      material DEF M Material { diffuseColor 1 1 1 }
      texture DEF IT ImageTexture { url "marble2.gif" }
    }
  }
  Transform {
    translation 4.3 0 0
    children Shape {
      geometry ElevationGrid {
        xDimension 5
        xSpacing 1
        zDimension 4
        zSpacing 1
        height [          # 5x4 array of heights
          0 .707 1 .707 0
          0 .47 .667 .47 0
          0 .236 .33 .236 0
          0 0 0 0 0
        ]
        creaseAngle 0.8
      }
      appearance Appearance {
        material USE M
        texture USE IT
        textureTransform TextureTransform { scale 1 -1 }
      }
    }
  }
  DirectionalLight { direction -0.80 -0.6 0 }
  Viewpoint { position 3 2 8 }
  Background { skyColor 1 1 1 }
]}