#VRML V2.0 utf8
#def.wrl
#explains how the DEF and USE structures work
Transform {
children [
DEF theCone Shape {
appearance Appearance {
material Material {
diffuseColor 0 0 1
} # end material
} # end appearance
geometry Cone { }
} # end shape
Transform {
translation 0 2 0
children [
USE theCone
] # end children
} # end transform
] # end children
} # end big transform
The above program contains a large transform, which contains a shape
and another transform. When you look at the world which is created,
you will see two identical cones. You would expect a Shape node for
each cone, with all the details of generating a cone. However, when
we look at the code, we see that the code for the second cone is
extremely simple. In fact, all the code really makes the
transformation which moves the cone. There is no shape, appearance,
or geometry explicitly defined for the second cone. Instead, where we
expect to see a shape, we see USE theCone.
DEF theCone Shape {
Usually, we would only see the keyword Shape there. The DEF
keyword (which must be all in uppercase) means 'Definition coming.'
By declaring a DEF, we have assigned (in this situation) the keyword
'theCone' to the entire Shape structure which will follow. This is
similar to creating variables in traditional languages, or naming
components in the visual languages like VB or HTML.
#VRML V2.0 utf8
#sharing colors
Transform {
children [
Shape {
appearance DEF green Appearance {
material Material{
diffuseColor 0 0 1
} # end material
} # end appearance
geometry box { }
} # end shape
#note how much easier the appearance is here...
Transform {
translate -2 0 0
children [
Shape {
appearance USE green
geometry Sphere { }
} # end shape
] # end children
} # end transform
] # end children
} # end transform
Notice that the green color was re-used.
#VRML V2.0 utf8
PROTO ColorBall [
field SFColor ballColor 1 0 0
] # end proto interface
{
Shape {
appearance Appearance {
material Material {
diffuseColor IS ballColor
} # end material
} # end appearance
geometry Sphere {
radius .2
} # end geometry
} # end shape
} # end proto
ColorBall {
ballColor 0 1 0
} # end colorBall
Transform {
translation .5 0 0
children [
ColorBall {
ballColor 0 0 1
} # end Colorball
] # end children
} # end transform
Transform {
translation -.5 0 0
children [
ColorBall {
} # end Colorball
] # end children
} # end transform
Transform {
translation 0 .5 0
children [
ColorBall {
ballColor 0 1 1
} # end Colorball
] # end children
} # end transform
Transform {
translation 0 -.5 0
children [
ColorBall {
ballColor 1 1 0
} # end Colorball
] # end children
} # end transform
Transform {
translation 0 0 .5
children [
ColorBall {
ballColor 1 0 1
} # end Colorball
] # end children
} # end transform
Transform {
translation 0 0 -.5
children [
ColorBall {
ballColor 1 1 1
} # end Colorball
] # end children
} # end transform
As you can see, there is repetition in this program, but it could be
worse, as it describes five balls, all inside transforms.
Fortunately, though, we can improve the readability by prototyping.
To define a prototype, we use the PROTO keyword. Prototypes have two
main areas: field definition and the proto shape definition. Fields
are the part of the prototype we wish to expose, or allow to be
changed through code. Prototypes do not always have fields, but they
make the prototype much more flexible. The field definitions are
encased in square brackets. They consist of the field keyword,
followed by the type of variable contained, followed by its name,
followed by a default value. Below is a list of the principle data
types in VRML:
| Field type | Contents |
|---|---|
| SFBool | Single field Boolean (TRUE or FALSE) |
| SFColor/ MFColor | Three floating point values, all between zero and one Used to to determine red, green, blue pigments |
| SFFloat/MFFloat | floating-point real number(s) |
| SFInt32/MFInt32 | a 32-bit integer |
| SFNode/MFNode | A VRML node. Usually a specific type of node is indicated |
| SFRotation, MFRotation | Three floats to determine an axis of rotation, and fourth is amount of rotation in radians |
| SFString/MFString | text string(s) |
| SFTime | a floating-point value for time |
| SFVec2f/MFVec2f | a vector of two floats. Mainly used for textures, cross-sections |
| SFVec3f/MFVec3f | a vector of three floats. Mainly used for points in 3D space |
#VRML V2.0 utf8
#the prototype demo extended to include offset!!
PROTO ColorBall [
field SFColor ballColor 1 1 1
field SFVec3f offset 0 0 0
] # end proto interface
{
Transform {
translation IS offset
children [
Shape {
appearance Appearance {
material Material {
diffuseColor IS ballColor
} # end material
} # end appearance
geometry Sphere {
radius .2
} # end geometry
} # end shape
] # end children
} # end transform
} # end proto
ColorBall{}
ColorBall{
ballColor 0 0 1
offset -.5 0 0
}
ColorBall{
ballColor 0 1 0
offset .5 0 0
}
ColorBall{
ballColor 0 1 1
offset 0 -.5 0
}
ColorBall{
ballColor 1 0 0
offset 0 .5 0
}
ColorBall{
ballColor 1 0 1
offset 0 0 .5
}
ColorBall{
ballColor 1 1 0
offset 0 0 -.5
}
This one is MUCH better!!
#VRML V2.0 utf8
#the prototype library
PROTO ColorBall [
field SFColor ballColor 1 1 1
field SFVec3f offset 0 0 0
] # end proto interface
{
Transform {
translation IS offset
children [
Shape {
appearance Appearance {
material Material {
diffuseColor IS ballColor
} # end material
} # end appearance
geometry Sphere {
radius .2
} # end geometry
} # end shape
] # end children
} # end transform
} # end proto
... and here's a page that uses it:
#VRML V2.0 utf8
#the prototype demo using EXTERNPROTO
#no default values in extern protos!!
EXTERNPROTO ColorBall [
field SFColor ballColor
field SFVec3f offset
] "protoLib.wrl#ColorBall"
ColorBall{}
ColorBall{
ballColor 0 0 1
offset -.5 0 0
}
ColorBall{
ballColor 0 1 0
offset .5 0 0
}
ColorBall{
ballColor 0 1 1
offset 0 -.5 0
}
ColorBall{
ballColor 1 0 0
offset 0 .5 0
}
ColorBall{
ballColor 1 0 1
offset 0 0 .5
}
ColorBall{
ballColor 1 1 0
offset 0 0 -.5
}
Note the use of EXTERNPROTO. It is much like the proto definition,
but it does not need the default values, and there is only field
definitions here.
#VRML V2.0 utf8
#legLib
#demonstrates proto node
PROTO Leg1 [
exposedField SFColor color 1 0 0
exposedField SFVec3f translation 0 0 0
]
{
Transform {
translation IS translation
children [
Shape {
appearance DEF myColor Appearance {
material Material {
diffuseColor IS color
shininess 1
} # end material
} # end appearance
geometry Box {
size .25 .25 .25
} # end geometry
} # end shape
Transform {
translation 0 .1 0
children [
Shape {
appearance USE myColor
geometry Cylinder {
height .25
radius .1
} # end geometry
} # end shape
] # end children
} # end transform
] # end children
} # end transform
} # end proto definition
PROTO Leg2 [
exposedField SFColor color 1 0 0
exposedField SFVec3f translation 0 0 0
]
{
Transform {
translation IS translation
children [
Transform {
translation -.125 0 0
children [
Leg1 { color IS color }
] # end children
} # end transform
Transform {
translation .125 0 0
children [
Leg1 { color IS color }
] # end children
} # end transform
] # end children
} # end transform
} # end Leg2 Definition
PROTO Leg4 [
exposedField SFColor color 1 0 0
exposedField SFVec3f translation 0 0 0
]
{
Transform {
translation IS translation
children [
Transform {
translation 0 0 -.125
children [
Leg2 { color IS color }
] # end children
} # end transform
Transform {
translation 0 0 .125
children [
Leg2 { color IS color }
] # end children
} # end transform
] # end children
} # end transform
} # end Leg4 Definition
PROTO Leg6 [
exposedField SFColor color 1 0 0
exposedField SFVec3f translation 0 0 0
]
{
Transform {
translation IS translation
translation .125 0 0
children [
Transform {
translation -.25 0 0
children [
Leg4 { color IS color }
] # end children
} # end transform
Transform {
translation 0 0 0
children [
Leg4 { color IS color }
] # end children
} # end transform
] # end children
} # end transform
} # end Leg6 Definition
PROTO Leg8 [
exposedField SFColor color 1 0 0
exposedField SFVec3f translation 0 0 0
]
{
Transform {
translation IS translation
children [
Transform {
translation -.25 0 0
children [
Leg4 { color IS color }
] # end children
} # end transform
Transform {
translation .25 0 0
children [
Leg4 { color IS color }
] # end children
} # end transform
] # end children
} # end transform
} # end Leg8 Definition
#show model here
Leg2 {
color 0 0 1
translation 0 1 0
}
Leg4 {
color 0 1 1
translation 0 0 0
}
Leg6 {
color 1 0 1
translation 0 -1 0
}
Leg8 {
color 1 1 0
translation 0 -2 0
}
... and a sample world using them...