General info on VRML 1.0 file format : http://vag.vrml.org/vrml10c.html
GLView home page : http://www.snafu.de/~hg
This document : GLViewNodes.htm
These nodes are not implemented in other VRML tools. If VRML files with GLView nodes should be loadable in other tools, the proper fields declaration could be exported by saving the file from GLView.
In the current GLView implementation VRML 1.0 nodes can be mixed with VRML 2.0 nodes in the same file, an VRML 2.0 Inline can refer to an VRML 1.0 world and vice versa. However this is not recommended because the extension is not part of the VRML 2.0 standard, and the mixing can have side affects of the proper rendering of Appearance and Texture nodes. However it might be usefull during the porting of VRML 1.0 worlds.
If VRML 2.0 scenes with VRML 1.0 nodes are exported to a VRML
2.0 file, GLView currently does not write a proper EXTERNPROTO
statement. For GLView VRML 2.0 extension nodes proper EXTERPROTO'S
are generated.
Image is similar to the Texture2 node, but the image will be displayed as 2d image at the current coordinate system (0,0,0) location starting with the lower left pixel of the image.
If an alpha value is specified the image alpha channel will be set to this alpha value. If both an alpha value and an alphaColor is specified, the alpha value of all pixels matching the alphaColor will be set to the alpha value. This feature can be used to make parts of an image transparent, so that other objects are shining through. Normally an image should have a constant color background e.g. black or white, so that the alphaColor could easily be specified like 0,0,0 or 1,1,1
After all operations image will contain the resulting image.
In the default rendering mode, transparent pixels (Alpha == 0) will be skipped.
Image {
// Fields.
SFString filename // url/file to read image from
SFImage image // or the image specified inline
SFFloat alpha // default 1.0, alpha Value of the image
SFColor alphaColor; // default black, alpha comparison color
}
Example: render a transparent bitmap, the starting point rotates with the camera
Separator {
Translation { translation -1 -1 0 }
Image { filename "imageWithBlackBackground.bmp" alphaColor 0 0 0 alpha 0.0 }
}
The ScaledImage node scales an child image node.
ScaledImage {
// Fields
// all field of Image ++
enum ScaleMode {
NONE,
TO_WINDOW, // scale relative to the current window size
TO_SIZE, // scale to absolute pixel size
BY_FACTOR, // scale relative by float factor
}
SFNode srcImage // the source image to scale, default NULL
SFEnum scale // scale mode, default NONE
SFVec2f scaleFactor // scale factor
}
Examples are in the layer section.
One of the factors in scaleFactor can be 0, in this case scaling preserve the aspect of the original image. Scale factors can be negative, in this case the image is mirrored along the axis.
After all operations the field image will contain the resulting image.
This node turns an arbitrary pixel image into a 3D Landscape. This feature is also somtimes called Heightfield.
ImageElevationGrid {
SFNode heightImage // an Image Node, default : NULL
SFFloat heightScale // additional heightScale factor for images values, default: 1.0
SFNode colorImage // an Image Node for per vertex colors, default : NULL
// fields from ElevationGrid
SFLong xDimension // x direction, Default 0
SFFloat xSpacing // x direction Default 1.0
SFLong zDimension // z direction Default 0
SFFloat zSpacing // x direction Default 1.0
MFFloat height // height array default []
}
The field heightImage must contain an Image node e.g.
ImageElevationGrid {
heightImage Image ( filename "mandrill.bmp")
}
ImageElevationGrid is derived from ElevationGrid, fields from ElevationGrid will be computed from the heightImage :
xDimension = Width of heightImage
zDimension = Height of heightImage
if (xSpacing == 0) xSpacing = 1.0 / xDimension
if (zSpacing == 0) zSpacing = 1.0 / zDimension
height[i,j] = heightFactor * grayValue(pixel[i,j]) / 255.0
ShapeHints + per vertex material bindings can be applied as usual in VRML 1.0 Texture could be used with this node. A better way is to specify also an image (texture) to compute vertex colors for the height field by using a second colorImage, instead of using texture mapping. Often the height and the color image could be shared e.g.
ImageElevationGrid {
heightImage DEF myImage Image ( filename "mandrill.bmp")
colorImage USE myImage
}
Depending onn Computer performance and memory, the images should not be to large. Images sizes of 128*128, 256* 256 are sufficient. An image could be read in as Heightfield by using the GLView command File->New->Heightfield from image.
Example ElevatedMandrill.wrl
#VRML V1.0 ascii
Separator {
Info {string "Mandrill.bmp as Elevated grid " }
Rotation {rotation 1 0 0 -1.5708 } // rotate into xy plane
ImageElevationGrid {
xSpacing 0.1
zSpacing 0.1
heightScale 2
heightImage DEF image Image {
filename "mandrill.bmp"
}
colorImage USE image
}
}
The Layer node allows image composition effects. The Layer behaves like a Separator but sets up a new camera space and optionally enables OpenGL specific rendering functions like alpha blending.
The camera space for the child nodes in Layer is set up to view the xy plane from (-1,-1) to (1,1). Note that this space exactly maps to the window, and that objects can appear distorted if the windows aspect ratio is not 1.
A general VRML graph setup would be :
Layer { } # Background layer
Separator {} # normal VRML scene controlled by camera movements
Layer { } # Foreground layer 1
Layer { } # Foreground layer 2
Layer {
enum Clear {
NONE,
COLOR,
DEPTH,
ACCUM,
STENCIL,
};
enum DepthFunc {
NEVER
LESS
EQUAL
LEQUAL
GREATER
NOTEQUAL
GEQUAL
ALWAYS
};
enum AphaFunc {
NEVER
LESS
EQUAL
LEQUAL
GREATER
NOTEQUAL
GEQUAL
ALWAYS
};
enum BlendSrcFunc {
ZERO
ONE
DST_COLOR
ONE_MINUS_DST_COLOR
SRC_ALPHA
ONE_MINUS_SRC_ALPHA
DST_ALPHA
ONE_MINUS_DST_ALPHA
SRC_ALPHA_SATURATE
};
enum BlendDestFunc {
ZERO
ONE
SRC_COLOR
ONE_MINUS_SRC_COLOR
SRC_ALPHA
ONE_MINUS_SRC_ALPHA
DST_ALPHA
ONE_MINUS_DST_ALPHA
};
SFBitMask clear // glClear(clear); // Default : NONE
SFBool depthWrite // glDepthMask(depthWrite) // Default : FALSE
SFEnum depthFunc // glDepthFunc(depthFunc) Default : LESS
SFBool lighted //glEnable/glDisable(GL_LIGHTING); Default : TRUE (if defaultValue use context setting)
SFEnum alphaFunc // glAlphaFunc(alphaFunc,alphaRef); Default ALWAYS
SFFloat alphaRef // Default : 0.0
SFBool blend //glEnable(GL_BLEND); Default : FALSE
SFEnum blendSrcFunc //glBlendFunc(srcFunc,DestFunc); Default : SRC_ALPHA
SFEnum blendDestFunc // Default : ONE_MINUS_SRC_ALPHA
... any child nodes e.g. Image ... Scene graph for -1 -1 1 1 camera
}
More information on the different parameters can be found in the OpenGL references manual or the Microsoft Windows OpenGL SDK documentation. WWWAnchor is currently not supported inside a Layer node.
Examples :
Render some 3D VRML objects with hidden surface removal and lighting in the foreground:
#VRML V1.0 ascii
... Normal VRML scene goes here
Layer {
clear DEPTH # clear only Z-buffer
depthWrite TRUE # use z-buffer
depthFunc LESS
# world space is now the space from -1 -1 -1 to 1 1 1
ShapeHints { vertexOrdering COUNTERCLOCKWISE shapeType SOLID }
# compose a cylinder rectangle
Separator {
Translation { translation 0.85 0.0 0}
DEF CyY Cylinder { radius 0.1 height 2.0 parts SIDES}
}
Separator {
Translation { translation -0.85 0.0 0}
USE CyY
}
Separator {
Translation { translation 0.0 -0.85 0}
Rotation { rotation 0 0 1 1.57079 }
USE CyY
}
Separator {
Translation { translation 0.0 +0.85 0}
Rotation { rotation 0 0 1 1.57079 }
USE CyY
}
}
Render an image in the foreground, make all black pixels of the image transparent, make the image 25 % of the window size :
#VRML V1.0 ascii
... Normal VRML scene goes here
Layer {
depthWrite FALSE // we don´t need the z-buffer
depthFunc ALWAYS // this disables z-test
lighted FALSE // lights off
alphaFunc GREATER // all pixels with alpha GREATER 0 are written to the screen
alphaRef 0.0
Translation { translation -1 -1 0 }
ScaledImage {
scale TO_WINDOW scaleFactor 0.25 0.25
srcImage Image { filename "glview.bmp" alphaColor 0 0 0 alpha 0.0 }
}
}
Instead of the alpha test, blending can be enabled to mix partly transparent objects
on top of the current display. For images the alpha channel can be used, for other geometry
a transparency can be specified in a material node.
Blend a 50% transparent image ontop of the lower left part of the window.
#VRML V1.0 ascii
.... Normal VRML scene goes here
Layer {
depthWrite FALSE // we don´t need the z-buffer
depthFunc ALWAYS // this disables z-test
lighted FALSE // lights off
blend TRUE // blendSrc and blendDest are having the right default
Translation { translation -1 -1 0 }
ScaledImage {
scale TO_WINDOW scaleFactor 0.25 0.0
srcImage Image { filename "glview.bmp" alpha 0.5 }
}
}
The difference for a background layer is, that normally no buffers need to be cleared.
If 3D Objects are rendered to Layers there are the following considerations to speed up rendering :
If 3D Objects are presorted and/or are rendered with proper ShapesHints settings a z-buffer check and
z-buffer writing could be disabled :
Layer {
clear NONE depthWrite FALSE depthFunc ALWAYS
....
}
If complex objects with hidden surface removal are rendered :
Layer {
clear DEPTH depthWrite TRUE depthFunc LESS
....
}
Example LayerTest.wrl
Most nodes with a ktx_com suffix have been implemented as dummys to support VRML files translated from 3D Studio.
from VRML 2.0 spec :
http://vag.vrml.org/vrml10c.html
This node creates a rectangular grid of varying height, especially useful in modeling terrain.
The model is primarily described by a scalar array of height values that specify the height of
the surface above each point of the grid.
The zDimension (rows) and xDimension (columns) fields indicate the number of grid points in the
X and Z directions, respectively, defining a grid of (zDimension-1) x
(xDimension-1) rectangles.
The vertex locations for the rectangles are defined by the height field and the gridStep field:
The height field is an array of scalar values representing the height above the grid for
each vertex. The height values are stored so that row 0 is first, followed by rows 1, 2, ...
verticesPerColumn-1. Within each row, the height values are stored so that column 0 is
first, followed by columns 1, 2, ... xDimension-1.
Thus, the vertex corresponding to the ith row and jth column is placed at
( xSpacing * j, height[ i* xDimension + j ], zSpacing * i )
in object space, where
0 <= i < xDimension and 0 <= j < zDimension.
All points in a given row have the same Z value, with row 0 having the smallest Z value. All
points in a given column have the same X value, with column 0 having the smallest X value.
The default texture coordinates range from [0,0] at the first vertex to [1,1] at the far side of
the diagonal. The S texture coordinate will be aligned with X, and the T texture coordinate
with Z.
ElevationGrid {
SFLong xDimension // x direction, Default 0
SFFloat xSpacing // x direction Default 1.0
SFLong zDimension // z direction Default 0
SFFloat zSpacing // x direction Default 1.0
MFFloat height // height array default []
}
ShapeHints + per vertex material bindings can be applied as usual in VRML 1.0
See Landscape.java as an example on how to create an elevation Grid.
from VRML 2.0 spec :
http://vag.vrml.org/vrml10c.html
Extrusion
The Extrusion node is used to define shapes based on a two dimensional cross
section extruded along a three dimensional spine. The cross section can be scaled
and rotated at each spine point to produce a wide variety of shapes.
An Extrusion is defined by a 2D crossSection piecewise linear curve (described
as a series of connected vertices), a 3D spine piecewise linear curve (also
described as a series of connected vertices), a list of 2D scale parameters, and a
list of 3D orientation parameters. Shapes are constructed as follows: The
cross-section curve, which starts as a curve in the XZ plane, is first scaled about
the origin by the first scale parameter (first value scales in X, second value scales
in Z). It is then rotated about the origin by the first orientation parameter, and
translated by the vector given as the first vertex of the spine curve. It is then
extruded through space along the first segment of the spine curve. Next, it is
scaled and rotated by the second scale and orientation parameters and extruded
by the second segment of the spine, and so on.
A transformed cross section is found for each joint (that is, at each vertex of the
spine curve, where segments of the extrusion connect), and the joints and
segments are connected to form the surface. No check is made for
self-penetration. Each transformed cross section is determined as follows:
1.Start with the cross section as specified, in the XZ plane.
2.Scale it about (0, 0, 0) by the value for scale given for the current joint.
3.Apply a rotation so that when the cross section is placed at its proper location
on the spine it will be oriented properly. Essentially, this means that the cross
section's Y axis (up vector coming out of the cross section) is rotated to align
with an approximate tangent to the spine curve.
For all points other than the first or last: The tangent for spine[i] is found by
normalizing the vector defined by (spine[i+1] - spine[i-1]).
If the spine curve is closed: The first and last points need to have the same
tangent. This tangent is found as above, but using the points spine[0] for
spine[i], spine[1] for spine[i+1] and spine[n-2] for spine[i-1], where
spine[n-2] is the next to last point on the curve. The last point in the curve,
spine[n-1], is the same as the first, spine[0].
If the spine curve is not closed: The tangent used for the first point is just the
direction from spine[0] to spine[1], and the tangent used for the last is the
direction from spine[n-2] to spine[n-1].
In the simple case where the spine curve is flat in the XY plane, these
rotations are all just rotations about the Z axis. In the more general case
where the spine curve is any 3D curve, you need to find the destinations for
all 3 of the local X, Y, and Z axes so you can completely specify the rotation.
The Z axis is found by taking the cross product of
(spine[i-1] - spine[i]) and (spine[i+1] - spine[i]).
If the three points are collinear then this value is zero, so take the value from
the previous point. Once you have the Z axis (from the cross product) and the
Y axis (from the approximate tangent), calculate the X axis as the cross
product of the Y and Z axes.
4.Given the plane computed in step 3, apply the orientation to the cross-section
relative to this new plane. Rotate it counter-clockwise about the axis and by
the angle specified in the orientation field at that joint.
5.Finally, the cross section is translated to the location of the spine point.
Surfaces of revolution: If the cross section is an approximation of a circle and the
spine is straight, then the Extrusion is equivalent to a surface of revolution, where
the scale parameters define the size of the cross section along the spine.
Cookie-cutter extrusions: If the scale is 1, 1 and the spine is straight, then the
cross section acts like a cookie cutter, with the thickness of the cookie equal to
the length of the spine.
Bend/twist/taper objects: These shapes are the result of using all fields. The spine
curve bends the extruded shape defined by the cross section, the orientation
parameters twist it around the spine, and the scale parameters taper it (by scaling
about the spine).
Extrusion has three parts: the sides, the beginCap (the surface at the initial end of
the spine) and the endCap (the surface at the final end of the spine). The caps
have an associated SFBool field that indicates whether it exists (TRUE) or doesn't
exist (FALSE).
When the beginCap or endCap fields are specified as TRUE, planar cap surfaces
will be generated regardless of whether the crossSection is a closed curve. (If
crossSection isn't a closed curve, the caps are generated as if it were -- equivalent
to adding a final point to crossSection that's equal to the initial point. Note that an
open surface can still have a cap, resulting (for a simple case) in a shape
something like a soda can sliced in half vertically.) These surfaces are generated
even if spine is also a closed curve. If a field value is FALSE, the corresponding
cap is not generated.
Extrusion automatically generates its own normals. Orientation of the normals is
determined by the vertex ordering of the triangles generated by Extrusion. The
vertex ordering is in turn determined by the crossSection curve. If the
crossSection is drawn counterclockwise, then the polygons will have
counterclockwise ordering when viewed from the 'outside' of the shape (and vice
versa for clockwise ordered crossSection curves).
Texture coordinates are automatically generated by extrusions. Textures are
mapped like the label on a soup can: the coordinates range in the U direction from
0 to 1 along the crossSection curve (with 0 corresponding to the first point in
crossSection and 1 to the last) and in the V direction from 0 to 1 along the spine
curve (again with 0 corresponding to the first listed spine point and 1 to the last).
When crossSection is closed, the texture has a seam that follows the line traced
by the crossSection's start/end point as it travels along the spine. If the endCap
and/or beginCap exist, the crossSection curve is cut out of the texture square and
applied to the endCap and/or beginCap planar surfaces. The beginCap and
endCap textures' U and V directions correspond to the X and Z directions in
which the crossSection coordinates are defined.
Extrusion {
MFVec3f spine
MFVec2f crossSection
MFVec2f scale
SFBool beginCap TRUE
SFBool endCap TRUE
}
ColorGradient is a modifier property node.
Vertex colors of lower level geometry nodes are computed from the
geometry vertex values.
Colors are automatically animated during rendering if cylce is set to
TRUE.
ColorGradient {
enum Axis {
X // use x value of geometry coordinate
Y // use y value
Z // use z value
RADIAL2 // compute distance from point to origin in xy plane
RADIAL, // " " to origin
SINXY // sin(x) * sin(y)
};
MFColor colors; // a table of colors for cycling through
MFFloat keys; // optional key frame values, default [] // to be done
SFEnum axis; // the axis or coordinate to use as source parameter, default Y
SFBool cycle; // if true, parametrizations is cylcled by the nodes current time frame. default : false
SFFloat scaleFactor; // a optional scale factor for input value, default: 1.0
}
Example :
Colored*.wrl
Separator {
ColorGradient {
}
...
IndexedFaceSet { ...}
}
GLView 2.05 VRML node extensions
fileName can point to a local file. Fileformats/extensions wrl, vrml, raw, geo and 3dv are supported
additional field
description "" #SFString
name "#cameraname" will jump to a defined camera in the scene
additional fields for 3D extruded text
extrusion #MFVec3f extrusion path
parts #SFBitMask Visible parts of extrusion
invertScale #SFVec2f size of invertion box
Parts = ALL | SIDES|TOP|BOTTOM|INVERT
For extruded text the value for extrusion should be [0 0 0, 0 0 DEPTH] where DEPTH is the
desired depth of the extrusion.
Standard attribute width of AsciiText is not implemented.
If parts has the INVERT property explicitely set, GLView compute a 2d bounding box for text,
scales this box by invertScale and subtracts the text from this box, to create a "inverted"
string.
Example:
ShapeHints {
}
FontStyle {
style BOLD
family SANS ## == ARIAL
size 1.0
}
AsciiText {
string "Abc"
justification CENTER
extrusion [0.0 0.0 0.0 , 0.0 0.0 1.]
}
Example: GLViewLogo.wrl Logo*.wrl
TextFont : the font name can specify an arbitrary Windows True Type font.
BaseColor {
rgb 0.8 0.8 0.8 #MFColor
}
Replaces the diffuse part of the current material
Rotor {
rotation 0 0 1 TWOPI #SFRotation Rotation axis and value
speed 1.0 #SFFloat Rotation speed
on TRUE #SFBool enable/disable switch
offset 0 #SFFloat additional offset
}
Derived from Rotation:
Applies a rotation depending on time. For the above values
a 360 degree rotation during one time step will be applied.
Animation starts using the Render->Time->Start button.
Shuttle {
translation0 0 0 0 #SFSVec3f Translation value 0
translation1 0 0 0 #SFSVec3f Translation value 1
speed 1.0 #SFFloat speed
on TRUE #SFBool enable/disable switch
}
Derived from Translation
Applies a translation from translation0 to translation1 depending on time.
Blinker {
speed 1.0 #SFFloat speed (time scale)
offset 0.0 #SFFloat time offset
on TRUE #SFBool enable/disable switch
upto FALSE #SFBool traverse from children 0 upto current if TRUE
... List of Nodes
}
Derived from Switch
Traverses childs depending on time. Cycles through all children in one time step. The global time
is transformed to localTime = globalTime * speed + offset. If the Blinker has only one child,
the child is toggled on and off.
Blinker can be used to blink different childs with geometry, but could also blink some
properties like Material, Texture2, Transforms and so on.
To create a simple video animation create a node like :
Blinker {
Texture2{}
Texture2{}
Texture2{}
}
Blinking of Coordinate3, TextureCoordinate2, Material nodes with local Materialbindings,
Normals is currently not supported.
TextureRotor {
rotation 0 0 1 TWOPI #SFRotation Rotation axis and value
speed 1.0 #SFFloat Rotation speed
on TRUE #SFBool enable/disable switch
offset 0 #SFFloat additional offset
}
Similar to Rotor, TextureRotor applies a time dependent rotation for the texture transformation.
TexturShuttle {
translation0 0 0 0 #SFSVec3f Translation value 0
translation1 0 0 0 #SFSVec3f Translation value 1
speed 1.0 #SFFloat speed
on TRUE #SFBool enable/disable switch
}
Derived from Translation.
Similar to Shuttle, TextureShuttle applies a translation of texture coordinate space
from translation0 to translation1 depending on time.
Example Animation Files :
Rot*.wrl
Example Files :HGJumpWorld.wrl
All the above nodes can put before geometry nodes as you normally would use
the correspoding Scale Translation Rotation nodes. There is no limit on then number
of combined nodes.
To rotate about a specific point use a sequence like
Translation { ...)
Rotor {... }
Translation { ...)
TimeTransform {
function TRANSFORM # SFEnum time mapping function
translation 0.0 # SFFloat Translation vector
scaleFactor 1.0 # SFFloat Scale factor
}
Function {
TRANSFORM,
IDENTITY,
CLAMP,
CYCLE,
WRAP,
MIRROR,
SIN,
SQR,
CUB,
RND,
EASE_IN_OUT
}
Example HGJumpWorld.wrl
The TimeTransform property transforms the local time space for the following childs of the
current separator.
For reference here the actual time transform implementation functions are listed:
static float f_tria(float x)
{ if (x<=0.0) return (0); if (x>=1.0) return (0.0);
if (x<=0.5) return (x*2.0); return(1.0- (x-0.5)*2.0); static float f_lin_i(float x) return(1.0-x); static float f_linclamp(float x) if (x<=0.0) return (0.0); if (x>=1.0)
return (1.0);
return(x);
}
static float f_rect(float x)
{ if (x<0.5) return (0.0); return(1.0); static float f_saw(float x) float t0=0.3333333333; float t1=2*t0; float dt=t1-t0; if (x
/* triangle */
if (xMACROBUTTON HtmlDirect <=0.5)
return ((x-t0)/ (0.5-t0)); return(1.0- (x-0.5)/(t1-0.5));
static float f_sqr(float x) return(x*x); static
float f_cub(float x) return(x*x*x); static float f_sin(float
x) return(sin(x*PI)); static float f_smooth(float x) return((-cos(x*PI)+1)*0.5);
static float f_rnd(float x) return((float)rand() / (float)RAND_MAX);
float QvTimeTransform::Transform(GTraversal &state,
float t) switch (function) case TRANSFORM : return(translation+t*scaleFactor);
case CLAMP : return(translation+f_linclamp(t/scaleFactor)*scaleFactor);
case CYCLE : return(translation+f_tria(t/scaleFactor)*scaleFactor);
case WRAP : return(translation+fmod(t,scaleFactor)); case
MIRROR : return(translation+f_lin_i(t/scaleFactor)*scaleFactor);
case SIN : return(translation+f_sin(t/scaleFactor)*scaleFactor);
case SQR : return(translation+f_sqr(t/scaleFactor)*scaleFactor);
case CUB : return(translation+f_tria(t/scaleFactor)*scaleFactor);
case RND : return(translation+f_rnd(t/scaleFactor)*scaleFactor);
case EASE_IN_OUT : return(translation+f_smooth(t/scaleFactor)*scaleFactor);
default : return(t); return(t); </PRE>