TechiWarehouse.Com


Top 3 Products & Services

1.
2.
3.

Dated: Aug. 12, 2004

Related Categories

VRML (Virtual Reality)


Introduction

VRML - the Virtual Reality Modeling Language. It sounds quite cool really, and it is. A lot of people say it's dead, but it's just that people don't use it a lot. However, as 3D graphics takes off, 3D on the internet will become more popular, and VRML is best candidate for Web 3D at the moment.

In this tutorial, I'm going to teach you how to create your own virtual worlds. However, I can't teach you absolutely everything, so I'm going to assume some basic knowledge on your part. You will find this tutorial pretty easy if you have a basic knowledge of the following things:

The Internet - how to use it, how it's organised, how to put up a web page, stuff like that.

HTML - Not a lot, but occasionally I'll compare some VRML concepts to how it's done in HTML. Not often though, and it's never vital.The only basic requirement is the elementary knowledge of HTML. If you are among those who is not familiar with HTML you can read the HTML Tutorial before venturing into this one. An introduction to any kind of programming would certainly help.

3D Geometry - Vectors, axes, coordinates, things like that. Nothing more complex that a normal school matsh course should teach you. You will need to have good spatial reasoning to design 3D worlds, but if you don't already have it, I'm sure you'll develop it as we go along. If you don't know about those things, don't worry, but you may need to ask someone what something means evey now and again. Shouldn't be too often though... and like I say, this would take forever if I tried to teach you everything. OK, enough of this, let's get down to it.

If you are a seasoned web developer using other technologies then just read through this tutorial and with the help of the VRML manual you can add VRML into your resume.

In the next section we shall look a little at the history of VRML and how it compares to the other solutions out there.

And The Rest is History...

VRML TutorialThe Virtual Reality Modeling Language (VRML) can been seen as a 3-D visual extension of the WWW. People can navigate through 3-D space and click on objects representing URLs (including other VRML worlds). Often, VRML is pronounced like ``Vermal'', not ``V-R-M-L''.

As Mark Pesce [Pesce, 1995] points out, the WWW had two fundamental dimensions: connectivity (the http protocol) and interface (i.e. the rendering of content, especially HTML and embedded URLS). VRML inserts itself seamlessly in the Web's connectivity. VRML browsers can access other VRML files via an URL. They can access any other format that then is passed to another application (e.g. an HTML browser or a HTML window). On the other hand HTML browsers can be configured to fire up VRML helper applications (or plug-ins). HTTP servers, finally, can be configured to tell the client that a VRML (*.wrl) document is transferred.

On April 3, 1995 SGI presented WebSpace, the first publicly available VRML browser. So all in all it took about a year to set standards and make the first browser available. Since VRML is a relatively simple format building upon a well defined standard, very quickly a number of modeling tools and convertors also became available.

Purpose and the Characteristics of VRML

The Virtual Reality Modeling Language (VRML) is a file format for describing 3D interactive worlds and objects. It may be used in conjunction with the World Wide Web. It may be used to create three-dimensional representations of complex scenes such as illustrations, product definition and virtual reality presentations.

VRML is capable of representing static and animated objects and it can have hyperlinks to other media such as sound, movies, and image. Interpreters (browsers) for VRML are widely available for many different platforms as well as authoring tools for the creation VRML files. VRML supports an extensibility model that allows new objects to be defined and a registration process to allow application communities to develop interoperable extensions to the base standard. There is a mapping between VRML elements and commonly used 3D application programmer interface (API) features.

Let The Games Begin...

The structure of a WRL File: VRML (*.wrl) files have 3 basic elements:

  1. A header which tells the browser that the file is VRML and which version also. A header line is mandatory.
  2. Comments are preceded by a #.
  3. Nodes: Most everything else are nodes.Nodes generally contain:
    1. The type of node (required). Nodes always are in Capital letters.
    2. A set of curly braces {.....} (required)
    3. A number of fields, all or some of which are optional. Note that there is no mandatory ordering of fields.
    4. Fields with that can have multiple values require braces [...]. Fields always start with lowerCase letters.

Here is a typical VRML file with a single node (don't worry if you don't understand it):

# VRML V2.0 utf8
# A sample file with a single stupid node
Transform {
    translation 0 2 0
    children [
        Shape {
            geometry Sphere {}
        }
    ]
}

Now be careful! VRML is a caseSensitive Language. Respect that or you will get strange errors!

Key Concept

In addition to ending with .wrl, your VRML files will have to tell the browser what kind of content it has in it. Like any Perl script you may run across, VRML has its own type of pound bang line: #VRML V2.0 utf8

And so the interpretation begins, with these three things:

  1. The browser finds out that it's been requested to display a file with VRML code in it.
  2. That code inside the file is VRML 2.0.
  3. It uses the UTF-8 character set. This means that the file can be written in English, along with other international languages

Past the header you'll find the main code of your file. VRML is organized into objects called nodes, which have their own fields and attributes. These nodes can also go inside of fields of other nodes, and so on. Most of these nodes represent something you can actually see in your browser, but others, like the ColorInterpolator node for example, have no immediate visual effect themselves but can control other nodes.

If you're a native to HTML, you'll find that these nodes have a remarkable similarity to tags. Some tags manipulate text directly, while others may center the entire document, controlling the output of other tags. Java and C++ natives would connect with the object-oriented base of those languages, where the nodes are objects with methods, attributes, and fields.

Take a look at this Shape node:

Shape {
    appearance Appearance { 
        material Material {
            diffuseColor 0.6 0.4 0.0 
        }
    } geometry Text {
        string "Microgoodies" 
    }
}

Now let's break it down:

You can see where the Shape node begins with "Shape" and the opening bracket ("{") afterwards. All nodes, minus a few exceptions, have this basic structure.

It may get tricky when you run into the first field, appearance. This is one of those times where a node, in this case the Appearance node, can be inserted as a field value for another node. You'll find that fields have a lowercase first letter, while nodes will have an uppercase first letter.

The second field, geometry, also takes a node as its value. Finally, the Shape node is ended with the closing curly bracket ("}").

EXAMPLE # 1:

Guys now we can start to add information to the file. The first node to deal with is the WorldInfo node. This node contains general information about the world, such as a title for the world. This is displayed in the title bar of the browser window, the same as a TITLE tag in HTML. WorldInfo can also contain an info string, which contain other information about the file. You can put what you like in this, such as keywords for search engines, or whatever. A sample WorldInfo node is shown below:

WorldInfo {
   title "Webolics World Tutorial Example 1"
   info ["(C) Copyright 2002 Webolics"
         "atifmuqeet@hotmail.com"]
}

You can have multiple strings in the info field, by putting them all inside square brackets. The title does not need square brackets, as it is only a single string. A VRML file can have as many WorldInfo nodes as you like, but only the first will be parsed. The rest will be ignored.

Basic Shapes

Now, this is all very nice, but no good at all at the moment, as there's nothing to see! Let's add a simple object to the scene. We'll add a Box object, with the default values, just so you can get the idea of how the structure works. There are a number of nodes required, such as Appearance and so on, but just ignore those, they're for the next tutorial. Just remember, if you don't specify a value for a field, it will use the default. So, this will use the default values. We add a Shape node to the world now, as shown below.

Shape {
   appearance Appearance {
      material Material {
      }
   }
   geometry Box {
   }
}

This adds a Shape node, which contains two fields for describing an object. These are the appearance and geometry fields, which describe the look and shape of the object respectively. These will be covered in a later tutorial. For now, it is enough to have a Box with the default values and colours in our world.

Co-ordinate Systems & Axes

Off we go again then. All distances in VRML are measured in metres. This doesn't matter so much in your own world, as long as you're consistent, but if you want to link to other people's worlds or use external files, it's a good idea to keep to the standard.

 

The X-Axis is horizontal, Y is vertical, and Z is coming out of the screen at you in the diagram above.

Rotations in VRML work by the right-hand rule. If you imagine wrapping your hand around one of the axes, with your thumb pointing in the positive direction, the direction of positive rotation is the same as the direction that your fingers wrap around in, i.e. clockwise looking in a positive direction. This is true for rotations about any axis, so if you want to rotate an object 90 degrees away from you around the X axis, you would use a 90 degree negative rotation. This also applies to rotations about arbitrary axes, as explained later on in this tutorial. One other point to make is that all rotations are measured in radians not degrees. So, to do the rotation described above, you would in fact do a rotation of -1.57 around the X axis. Below is a quick reference for degrees to radians conversion. In general, multiply the number of degrees by pi/180.

Degrees Radians
0 0
45 0.78
90 1.57
135 2.36
180 3.14 (pi)
225 3.93
270 4.71
315 5.5
360 6.28 (2*pi)

Transformations

Right. In order to make our world any use at all, we need to be able to transform objects. VRML has three types of transformations we can apply to objects. These are translations, rotations, and scales. These are used in a Transform node. A Transform node doesn't have to have all three in it. You can just have a rotation, for instance. The transformations within a Transform apply to the children of the node. This is called nesting, where a node can have any number of child nodes. The syntax for this is shown in the example below, along with the syntax for a Transform node.

Transform {
   translation 1 1 1
   rotation 0 1 0 0.78
   scale 2 1 2
   children [
      USE FBOX
   ]
}

A Transform node can have another nested inside it as a child, which allows you to do sequences of transformations. Remember, the order of transformations matters. A rotation followed by a translation is not the same as a translation followed by a rotation. Within a single Transform node, the transformations are carried out in strict order: Scale, then Rotate, the Translate. So, if you want a translation followed by a rotation, you need to nest Transform nodes inside one another.

Typical VRML Shapes:

Box

The Box is exactly what is says, a cube or cuboid shape. The default Box is a cube, two metres to a side, centred on the origin. To make a Box of a different size, you can define it with an explicit size:

geometry Box {
   size 5.5 3.75 1.0
}

This creates a Box with X, Y and Z dimensions as specified in the size parameter.

Textures are mapped onto the Box by applying them individually to each face. The texture is applied the obvious way up to the sides, and applied to the top so that if it is tilted towards the camera, the texture is the right way up. The bottom is texture-mapped the opposite way, so if the bottom is tilted towards the camera, the texture is the right way up still.

Cylinder

The Cylinder node is slightly more complex. The default is a cylinder from +1 to -1 in all dimensions, the same as the Box above (radius of 1, height of 2). This too is centred on the origin. To specify a different size, we can use the radius and height fields. There are also three other fields, side, top, and bottom. These are Boolean values (TRUE or FALSE), and tell the browser whether to display the appropriate section of the cylinder. These default to TRUE, so you don't need to put them in at all most of the time. However, if you had a cylinder where an end was obscured by another object, it would be worth turning off that end, as it will reduce the amount of work for the browser, speeding up the execution of your world.

geometry Cylinder {
   radius 0.5
   height 10
   top FALSE
}

This gives a tall, thin cylinder with no top.

Textures are wrapped around Cylinders so that the edges of the texture meet at the back. Circular pieces are cut out of the texture and applied to the top and bottom in the same orientation as for the Box.

Cone

Again, much the same as the Cylinder, except that instead of a radius field, we have a bottomRadius, which does exactly what it says it does. Also, there is no top field, as cones don't tend to have tops. Normally.

geometry Cone {
   bottomRadius 5
   height 10
   side TRUE      #this isn't actually needed, 
                  #because it's the default.
   bottom FALSE
}

Textures are applied in the same way as for cylinders. The default value is a cone of the same dimensions as the Cylinder and Box. The centre of this one is a bit more difficult to visualise. The centre is in the middle, halfway up the cone. Now, when you consider the bounding box of the cone, it seems obvious, but it's not totally intuitive. So, a default cone will extend 1 metre above the Y plane and 1 metre below, having a radius of 1 at the bottom.

Sphere

A Sphere node has only one field, which is its radius. Hmmmm, that was easy.

geometry Sphere {
   radius 10,000,000
}

That's one very BIG sphere. Anyway, textures are applied by wrapping the texture around the sphere, and then pinching in the top and bottom. So, If you had a texture with a grid on it, the vertical lines would get closer together at the top and bottom, while the horizontal lines would stay the same distance apart all the time.

Text & FontStyle

This node creates some 2D text in the world. It's all very simple really, unless you want to do more complex stuff using FontStyle. The Text node has only four fields. The first is string, where you define the string or list of strings to display. The fontStyle field contains a FontStyle node, which I'll cover in a minute. The last two fields are maxExtent, where you specify the maximum width (in metres) of the text, and length, which is a list of lengths (again, in metres) for each string, so you can specify a specific width for each of them. If lengths are specified, the browser will resize the text to fit in that size.

geometry Text {
   string ["Hello", "World"]
   fontStyle USE HELLOFONT
   maxExtent 5
   length [3, 3]
}

OK, that's the Text node then, all very simple stuff. FontStyle is more complex. The best way to start here is to list all the fields.

FontStyle {
   size
   family
   style
   horizontal
   leftToRight
   topToBottom
   language
   justify
   spacing
}

OK then. size is the height, in metres, of the line of text. The family field can take one of three values, and alters the typeface of the font. The three types are "SERIF", "SANS", or "TYPEWRITER". These are all fairly self-explanatory. To change the look of the text, you can use the style field. This can be any of "PLAIN", "BOLD", "ITALIC", or "BOLD ITALIC". horizontal is a boolean value showing whether the text is horizontal ("TRUE") or vertical ("FALSE"). leftToRight and topToBottom are also boolean, and are fairly obvious in their operation. The same utf-8 string can appear differently, depending on which language it is in, so this is a two-character code for the language. I really don't know what the codes are, so it's probably best to ignore this field. justify is very useful, and can be any of "BEGIN", "MIDDLE", or "END". spacing is the amount of space between the lines of text. 1 is normal, and 2 corresponds to double-spacing (a blank line between each line).

That's FontStyle then. You can really ignore most of the fields, but things like the style, family, and justify are very useful.

Happily Ever After

All the geometry nodes so far ( and all the others we'll meet later on) are centred on the origin of the local coordinate system. When we get onto more complex objects, this becomes more obvious. For now, just remember that the point you position with transforms and so on is the centre of the object. Right then, that's about it for this tutorial then. To see what we've done so far, take a look at this

#VRML V2.0 utf8
WorldInfo {
   title "Webolics Tutorial Example"
   info ["(C) Copyright 2002 Webolics"
         "atifmuqeet@hotmail.com"]
}
Shape {
   appearance Appearance {
      material Material {
         diffuseColor 0 0.5 0
         emissiveColor 0 0.8 0
         transparency 0.5
      }
   }
   geometry Cylinder {
      radius 0.35
      height 3
      bottom FALSE
   }
}
Transform {
   translation 0 -2 0
   children [
      Shape {
         appearance Appearance {
            texture ImageTexture {
               url "brick.jpg"
               repeatS TRUE
               repeatT TRUE
            }
         }
         geometry Box {
            size 4 1 4
         }
      }
   ]
}
Transform {
   translation 1.6 -1 1.6
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 1 0 0
            }
         }
         geometry DEF ICKLECONE Cone {
            bottomRadius 0.3
            height 1
            bottom FALSE
         }
      }
   ]
}
Transform {
   translation -1.6 -1 -1.6
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 1 0 0
            }
         }
         geometry USE ICKLECONE
      }
   ]
}
Transform {
   translation -1.6 -1 1.6
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 1 0 0
            }
         }
         geometry USE ICKLECONE
      }
   ]
}
Transform {
   translation 1.6 -1 -1.6
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 1 0 0
            }
         }
         geometry USE ICKLECONE
      }
   ]
}
Transform {
   translation 0 2.25 0
   children [
      Shape {
         appearance Appearance {
            texture ImageTexture {
               url "me.jpg"
            }
         }
         geometry Sphere {
            radius 0.75
         }
      }
   ]
}
Transform {
   translation 0 -2.2 2.01
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 0 1 0
            }
         }
         geometry Text {
            string "FloppyWorld"
            fontStyle FontStyle {
               size 0.8
               justify "MIDDLE"
            }
         }
      }
   ]
}

So, now we have a small monument type thing, topped by a green plastic column with a replica of my head on the top. Groovy. That's all then, carry on to the next lesson, which is a tiny little short one about linking to the outside world.

Anchor

In VRML, you navigate between pages the same way as in HTML. You have an object that, when the user clicks on it, links to another page. Exactly what you're all used to. In VRML, this is done with the Anchor node.

Anchor {
   children [
      USE HEAD
   ]
   description "Back to the Tutorial"
   url "tut16.html"
}

The Anchor node is activated whenever one of its children is clicked, and opens up the page specified in url. The description field is a piece of text that appears somewhere in the browser when the mouse is over the hyperlink, just as in HTML.

There are a couple of extra fields not shown above. One of these is parameter field, which can take extra information, such as a frame name.

parameter [ "target=main_frame" ]

There are also two fields concerned with bounding boxes. These are concerned with providing a bounding box for the VRML browser to speed up its calculations when rendering the scene. The two fields are bboxCenter and bboxSize. I wouldn't worry about them, but if you do, make sure the size is big enough to fit all the children of the object in. Both take X Y Z values as arguments.

Fields:

Right then. As you've probably picked up from the previous tutorials, VRML files consist of groups of nodes. These nodes can also contain other nodes, and also can contain fields. Each field has a type, which governs what data it can contain, and how much of it. There are a number of different types in VRML, which are described below. You'd best get used to these, because I'm going to use them to describe the nodes from now on.

SFBool
This is a single boolean value, which can take the value "TRUE" or "FALSE".
SFColor & MFColor
SFColor is a field containing a single colour, made up of three floating-point numbers between 0 and 1 corresponding to the red, green and blue values of that colour, e.g. 0 1 0 is green. MFColor is a field containing multiple colours, e.g. [0 1 0, 1 0 0, 0 0 1].
SFFloat & MFFloat
SFFloat is a single floating-point value, e.g. 7.5. An MFFloat is a number of floating-point values, e.g. [1.0, 3.4, 76.54].
SFImage
SFImage is a two-dimensional image, either in colour or grey. It consists of:
  • Two integers, representing the width and height of the image.
  • One integer representing the number of components in the image. 1 is grey levels only, 2 is greys with transparency, 3 is RGB colour, and 4 is RGB with transparency.
  • After these, there are width * height hexadecimal numbers, consisting of 2 digits for each component. So, 0xFF would be white in a 1-component image, and 0xFF00007F would be half-transparent red in a 4-component image.
Pixels are specified from left to right, bottom to top.
SFInt32 & MFInt32
A single or list of 32-bit integer numbers. These can be in decimal or hexadecimal format. Hexadecimal numbers start with 0x, e.g. 0xFF is 255 in decimal.
SFNode & MFNode
SFNode is a single node, and MFNode is a list of nodes. Note that the children field in many nodes is of type MFNode.
SFRotation & MFRotation
These fields specify a rotation about an axis. It is made up of four floating-point numbers. The first three specify X Y and Z coordinates for the vector corresponding to the axis about which to rotate, and the fourth is the number of radians to rotate by. Further explanation is in the rotation section of tutorial 1.3. SFRotation is a single set of values, MFRotation is a list.
SFString & MFString
This type contains a list of characters in the utf-8 character set. ASCII is a subset of utf-8, so you needn't worry about different character sets or anything. A string (SFString) is specified as "Hello", in double quotes. A list (MFString) looks like this: ["Hello", "World"].
SFTime & MFTime
A single or list of times. Times are specified as floating-point numbers representing the number of seconds elapsed since midnight on the 1st January 1970. This make more sense when we cover events later on.
SFVec2f & MFVec2f
A single or list of 2D vectors. A 2D vector is a pair of floating-point numbers.
SFVec3f & MFVec3f
A single or list of 3D vectors. A 3D vector is a triple of floating-point numbers.

Background

So far, the worlds we have created look OK, but are lacking something in the way of distance. You have an object floating in space, and that's it. OK for some things, but to look good, we need some kind of background. The default background is black, but that's not very nice. Lets do something about it.

There are two ways we can change the background of our scene. One is to specify colours for the background, and the other is to provide images to be mapped onto the background. Both of these are implemented with the Background node. First of all, I'll describe how to add colour to the background of your scene.

The Background node has a number of fields used for background colours. These are:

Background {
   MFFloat     groundAngle       []
   MFColor     groundColor       []
   MFFloat     skyAngle          []
   MFColor     skyColor          [0 0 0]
}

Just a quick note about the format of the node definitions. Up until now, I've been showing you examples of the nodes with value in place, which is how you would actually use it. From now on, however, I'm going to give the actual definition of the fields. This is the field name, the type, and the default value. You still use the nodes in the same way (as shown in the example a little further down), but I'm giving you a little more information. If you've read the Techy Stuff tutorial, you'll understand what's going on.

Right, we can carry on now... The default values are shown above. The default is a single skyColor of 0 0 0, black. skyColor is a list of SFColor values, corresponding to the sequence of colours to be displayed on the background, from the point directly above, downwards. So, the first value is displayed above, and the next is displayed below that, and so on. skyAngle is the angle (down from the top) that each band of colour will be displayed at. The first colour is automatically displayed at an angle of 0 (straight up), so you don't need to include that one. Therefore, there will always be one fewer angles than colours. The browser interpolates between the colours on the background, so you get a smooth blending effect. For instance, the following code would give a mix between red (straight up), green (45 degrees up), and blue (straight ahead).

Background {
   skyColor [1 0 0, 0 1 0, 0 0 1]
   skyAngle [0.78, 1.57]
}

This will appear as shown in this example

#VRML V2.0 utf8 
WorldInfo {
   title "Webolics Tutorial"
   info ["(C) Copyright 2002 WEbolics"
         "atifmuqeet@hotmail.com"]
}
Background {
   skyColor [1 0 0, 0 1 0, 0 0 1]
   skyAngle [0.78, 1.57]
}

In order to make your world more interesting, we can add sound to it. This can take the form of ambient background noise, doorbells, warning sirens, anything you like. It's all done with two types of node, the Sound and AudioClip nodes. You can imagine a Sound node as specifying where in space you can hear a sound, and where it originates from. The actual sound itself is specified by the AudioClip node. First of all, we'll deal with the Sound node.

Sound

The Sound node is used to specify the positioning and orientation of a sound source in your world. The Sound node is positioned at a certain place, and whether you can hear the sound or not depends on where you are in relation to it. The sound is emitted in an ellipsoid pattern.

 

Inside the red area, the sound is heard at full intensity. Inside the yellow area, the sound fades with distance from the source. The minFront, maxFront, minBack, and maxBack distances are fields specified in the Sound node, as is direction. The actual syntax of the Sound node is as follows:

Sound {
   SFVec3f     direction         0 0 1
   SFFloat     intensity         1
   SFVec3f     location          0 0 0
   SFFloat     maxBack           10
   SFFloat     maxFront          10
   SFFloat     minBack           1
   SFFloat     minFront          1
   SFFloat     priority          0
   SFNode      source            NULL
   SFBool      spatialize        TRUE   
}

The other fields operate as follows: direction is a vector specifying the direction that the sound node points in. intensity is the volume of the sound. A value of 1 is the full volume as found in the sound file, and 0 is silent. location is the position of the sound source in the world. The four max/min Front/Back parameters specify the shape of the ellipsoid, as shown above. For instance, to have a sound that was equally audible in all directions, you would have maxFront=maxBack, and minFront=minBack. If you didn't want this sound to decrease with distance, you would set all the values to the same distance, which should be plenty big enough to cover your entire world in this case. If you do want to make your sound tail off with distance, setting the max values to 10 times the min values gives a realistic drop-off rate.

priority is the importance of the sound. The browser will only have a certain number of sound channels available to it, and the priority of a sound is used to determine which ones are played. This takes values from 0 to 1. Low-priority background sounds should have a value of 0, and high-priority, short sounds like doorbells or whatever should have a value of 1.

The spatialize field is used by the browser to determine whether it should spatialize the sound. This means it will play the sound through the speakers as though coming from the source of the sound, so you will hear the sound moving when you move relative to the it. If this field is FALSE, the browser will not do this. This is useful both for optimization and creating ambient sounds.

Only one field left in the Sound node, and that is the source node. This is the really important one. It can contain either a AudioClip node or a MovieTexture node. If you use a MovieTexture, the browser will play the sound from the movie file specified. This can be useful for playing back MPEG sound files, for instance. More useful is the AudioClip node, which we'll cover in detail now!

AudioClip

The AudioClip node actually specifies what will be played by the sound node, and when. The syntax is as follows:

AudioClip {
   SFString    description       ""
   SFBool      loop              FALSE
   SFFloat     pitch             1.0
   SFTime      startTime         0
   SFTime      stopTime          0
   MFString    url               []
}

The AudioClip functions like this. The url field is a list of files in uncompressed .WAV format, or General MIDI .MID type 1 format, which is useful for compact representation of music. The browser will play the first of these that it can load. loop specifies whether the sound loops, which is useful for ambient sounds, and description is a description of the sound, which the browser can display if it so desires. pitch is a multiplier for the speed of playback, and hence the pitch of the sound. A pitch of 1.0 is the normal speed. A pitch of 0.5 will play back at half the speed, and transpose the sound down an octave. A value of 2.0 will have the opposite effect, doubling the speed of the sound, and raising the pitch by an octave.

startTime and stopTime are SFTime values, which specify when the sound will start and stop. If you remember, these are a number of seconds since 1st January 1970, which may not seem much use, but when linked up with sensors and routes, makes a lot more sense. A sensor will generate a eventOut with the time it is activated, and if this is routed to an AudioClip node, via the set_startTime eventIn, it will play the sound. We'll see more about that later when we actually cover sensors and interaction, but we don't know enough about them yet to do that.

Fade Away...

One thing to say about sound nodes, is that uncompressed .WAV files are HUGE, and take absolutely ages to download. Therefore, they should be used very sparingly for the sake of efficiency. MIDI files are better, and should be OK for background music, but try to steer clear of .WAV files as much as you can. If you do have them, make them short and low-quality, otherwise no-one will ever wait around for your 10-minute CD-quality .WAV to download.

That's all you need to know about basic sound stuff. In order to actually produce useful sounds, like doorbells and so on, we need to be able to interact with the world, through sensors and things like that. We haven't covered those yet, so I'll leave the demonstration of interactive sounds for now, and just add some drum noises coming from the podium to the example world.

#VRML V2.0 utf8 
WorldInfo {
   title "Webolics Tutorial Example"
   info ["(C) Copyright 2002 Webolics"
         "atifmuqeet@hotmail.com"]
}
Shape {
   appearance Appearance {
      material Material {
         diffuseColor 0 0.5 0
         emissiveColor 0 0.8 0
         transparency 0.5
      }
   }
   geometry Cylinder {
      radius 0.35
      height 3
      bottom FALSE
   }
}
Transform {
   translation 0 -2 0
   children [
      Shape {
         appearance Appearance {
            texture ImageTexture {
               url "brick.jpg"
               repeatS TRUE
               repeatT TRUE
            }
         }
         geometry Box {
            size 4 1 4
         }
      }
   ]
}
Transform {
   translation 1.6 -1 1.6
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 1 0 0
            }
         }
         geometry DEF ICKLECONE Cone {
            bottomRadius 0.3
            height 1
            bottom FALSE
         }
      }
   ]
}
Transform {
   translation -1.6 -1 -1.6
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 1 0 0
            }
         }
         geometry USE ICKLECONE
      }
   ]
}
Transform {
   translation -1.6 -1 1.6
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 1 0 0
            }
         }
         geometry USE ICKLECONE
      }
   ]
}
Transform {
   translation 1.6 -1 -1.6
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 1 0 0
            }
         }
         geometry USE ICKLECONE
      }
   ]
}
Transform {
   translation 0 2.25 0
   children [
      Shape {
         appearance Appearance {
            texture ImageTexture {
               url "me.jpg"
            }
         }
         geometry Sphere {
            radius 0.75
         }
      }
   ]
}
Transform {
   translation 0 -2.2 2.01
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 0 1 0
            }
         }
         geometry Text {
            string "FloppyWorld"
            fontStyle FontStyle {
               size 0.8
               justify "MIDDLE"
            }
         }
      }
   ]
}

Lighting in VRML

The first thing to mention is the way that the VRML lighting model works. All lights have the following fields: color, ambientIntensity, and intensity. Each light has an intensity, which a value between 0 and 1 corresponding to its brightness. It also has an ambient intensity, also between 0 and 1, which is how much light it contributes to the general ambient light in the scene. Because of this, the more lights in the scene, the brighter the ambient illumination, which makes sense. Ambient light is light that shines on every surface in the scene, simulating light scattered from other objects. Each light also has a colour associated with it, which surprisingly enough is the colour of the light it emits. The direct light emitted by a light source is calculated by intensity * color. The ambient light contributed to the scene is ambientIntensity * color. Each light source also has an area of effect, so as to keep VRML worlds enclosed and scalable. The method of doing this varies between the different types.

Most VRML browsers calculate lighting by working it out for each corner of a face, and interpolating the shading between these vertices. This means that if you have a huge face with a light source shining on the middle of it, with corners that are very distant, you will NOT get a light spot on the face. It will all be uniformly dark. This is an important thing to bear in mind. Another important point to notice is that faces are only lit if they have a Material node. Objects with textures will not be affected by lighting. This is awkward, and you may have to produce pre-lit textures to compensate if you need shading on them. Another very important thing to remember is that by default, VRML worlds will have the user's headlight ON. This will seriously screw the careful lighting in your worlds, so remember to turn it off if you feel it necessary. This is done by inserting a headlight FALSE line into a NavigationInfo node, as shown in the code sample below. We'll cover the NavigationInfo in one of the later tutorials, but for now you can just include this in your files to turn off the headlight. It just goes at the top level of the scene graph, like WorldInfo. We'll come back to it, don't worry.

NavigationInfo {
   headlight FALSE
}

Directional Light

Right then, time to get down to business. The first light node we'll cover is the DirectionalLight node. This is a light that shines from a uniform direction, like a set of parallel rays. This gives an effect like that of the Sun, where everything is illuminated from the same direction. The DirectionalLight node does not have a location in the worlds space, but simply exists.

It illuminates everything that is a child of its parent, so everything at its level in the hierarchy and below. This example (code) shows the scoping of the DirectionalLight node.

#VRML V2.0 utf8
WorldInfo {
   title "Webolics Tutorial Example"
   info ["(C) Copyright 2002 Webolics"
         "atifmuqeet@hotmail.com"]
}

NavigationInfo {
   headlight FALSE
   type "EXAMINE"
}
DirectionalLight {
   ambientIntensity 0.75
   intensity 1
   color 0 1 0
   direction 0 -1 1
}
Transform {
   translation -2.5 0 0
   children [
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 1 1 1
            }
         }
         geometry Sphere {
            radius 2
         }
      }
   ]
}
Transform {
   translation 2.5 0 0
   children [
      DirectionalLight {
         ambientIntensity 0.75
         intensity 1
         color 1 0 0
         direction 0 -1 -1
      }
      Shape {
         appearance Appearance {
            material Material {
               diffuseColor 1 1 1
            }
         }
         geometry Sphere {
            radius 2
         }
      }
   ]
}

Both Spheres are lit by a green light from behind, but the one on the right is also lit by a red light pointing from in front of it. This is because the green light is at the top level in the file, so illuminates everything. The red light, however is grouped in the same node as the sphere it shines on. The other sphere is in a separate part of the scene graph, so is not lit.

 

The DirectionalLight node has the basic light fields of intensity, color, and ambientIntensity. It also has an on field, which is simply TRUE or FALSE, indicating whether the light is on or off. It also has a direction field, which is a vector corresponding to the direction that the light shines in. The default value of 0 0 -1, for instance, indicates that the light shines from +Z towards the origin, or down the -Z axis. The full definition of the DirectionalLight node is shown below.

DirectionalLight {
   exposedField   SFFloat     ambientIntensity  0
   exposedField   SFColor     color             1 1 1
   exposedField   SFVec3f     direction         0 0 -1
   exposedField   SFFloat     intensity         1
   exposedField   SFBool      on                TRUE
}

Point Light

A PointLight is light that emanates from a particular point in space, spreading equally in all directions. Unlike the DirectionalLight, this node actually has a position in space, specified in its location field. This is the point from which the light will emanate. The effect of the PointLight is limited in a different way to the DirectionalLight. Rather than being scoped by its position in the scene hierarchy, is it scoped by its position in space. It has fields that perform this scoping, the radius field. The radius of the light is the maximum distance at which objects will be illuminated. Within this radius, the intensity of the light is affected by a set of attenuation constants. These are 3 floating point values (stored as an SFVec3f) that affect the lighting with the following formula:

1 / (attenuation[0] + attenuation[1]*r + attenuation[2]*r2)

This means that the 3 values in the attenuation field are used as coefficients in a quadratic formula for the intensity of the light at a distance r. It is left up to you to experiment with different coefficients. The default value of 1 0 0 gives no attenuation, giving a sharp limit to the effect of the light. To make the light fall off linearly, you would have an attenuation of the form 0 x 0. I'll leave you to experiment, but I'll leave this node with this example

#VRML V2.0 utf8
WorldInfo {
   title "Webolics Tutorial Example"
   info ["(C) Copyright 2002 Webolics"
         "atifmuqeet@hotmail.com"]
}
NavigationInfo {
   headlight FALSE
   type "EXAMINE"
}
Transform {
   translation -5 0 0
   children [
      PointLight {
         color 1 1 1
         intensity 1
         ambientIntensity 0.5
         location 0 0 0
         radius 5
         attenuation 0 1 0
      }
      DEF SPHERETHING Group {
         children [
            Transform {
               translation 0 1 0
               children [
                  DEF SPHERE Shape {
                     appearance Appearance {
                        material Material {
                           diffuseColor 1 0 0
                        }
                     }
                     geometry Sphere {
                        radius 0.5
                     }
                  }
               ]
            }
            Transform {
               translation 0 2 0
               children [
                  USE SPHERE
               ]
            }
            Transform {
               translation 0 3 0
               children [
                  USE SPHERE
               ]
            }
            Transform {
               translation 0 -1 0
               children [
                  USE SPHERE
               ]
            }
            Transform {
               translation 0 -2 0
               children [
                  USE SPHERE
               ]
            }
            Transform {
               translation 0 -3 0
               children [
                  USE SPHERE
               ]
            }
         ]
      } 
      Transform {
         rotation 0 0 1 1.57
         children [
            USE SPHERETHING
         ]
      }
   ]
}
Transform {
   translation 5 0 0
   children [
      PointLight {
         color 1 1 1
         intensity 1
         ambientIntensity 0.5
         location 0 0 0
         radius 5
         attenuation 0 0 1
      }
      USE SPHERETHING
      Transform {
         rotation 0 0 1 1.57
         children [
            USE SPHERETHING
         ]
      }
   ]
}

The set of spheres on the left is lit with attenuation constants of 0 1 0, giving a linear attenuation. The right-hand set is lit with non-linear attenuation constants of 0 0 1, causing the light to fall off in an r2 kind of way. Bear in mind that this may not look correct on your system, depending on the renderer used by your browser. Direct3D renderers do not seem to support attenuation, so don't worry if you can't see it, it's just your browser limitations. It does work, honest.

PointLight {
   exposedField   SFFloat     ambientIntensity  0
   exposedField   SFVec3f     attenuation       1 0 0
   exposedField   SFColor     color             1 1 1
   exposedField   SFFloat     intensity         1
   exposedField   SFVec3f     location          0 0 0
   exposedField   SFBool      on                TRUE
   exposedField   SFFloat     radius            100
}

Spot Light

The last lighting node is the SpotLight node. This, obviously enough, defines a spotlight. It has all the standard fields of the normal lighting nodes. It also has the location, radius and attenuation fields of the PointLight node. These fields have exactly the same effect as described above, giving a position, a maximum radius, and an attenuation within this radius for the light source. However, it also has a couple of other fields. The SpotLight is scoped by its position in space in the same way as the PointLight. However, as it is a light that shines in a particular direction, as well as its location, it also has a direction field, which defines the direction that the light points in.

We can also specify the size of the spotlight produced with two other fields, the beamWidth and the cutOffAngle. These are angles, which define how wide the main beam will be, and how fast it fades out at the edges. Note that this cutOffAngle is completely unrelated to the attenuation. The attenuation governs how the light changes in the direction that it is shining, and cutOffAngle defines how it falls off at the edges of the beam. By default, the beamWidth is larger than the cutOffAngle, giving a sharp edge to the beam. This increases rendering performance considerably. 

 

SpotLight {
   exposedField   SFFloat   ambientIntensity  0
   exposedField   SFVec3f   attenuation       1 0 0
   exposedField   SFFloat   beamWidth         1.570796
   exposedField   SFColor   color             1 1 1
   exposedField   SFFloat   cutOffAngle       0.785398
   exposedField   SFVec3f   direction         0 0 -1
   exposedField   SFFloat   intensity         1
   exposedField   SFVec3f   location          0 0 0
   exposedField   SFBool    on                TRUE
   exposedField   SFFloat   radius            100
}

Darkness Falls

It is worth remembering that if you want any kind of special lighting effect on a surface, such as a spotlight with a soft edge, that surface will have to have many vertices on it and be made up of many faces, as VRML only does lighting at each corner. This is a very important thing to remember. If you have a light shining on the middle of a large surface, you will not get the effect you want. Also, different rendering libraries support lighting an attenuation in different ways, so lighting may appear different in different browsers. The important thing to do with lighting is to experiment, if possible with different browsers.

SUMMARY:

This file is a summary of the way a VRML scene should be arranged. It lists the valid grouping nodes, root-level nodes, and children nodes, amongst other useful bits and pieces.

VRML97 File Header

The header (i.e. the first line) for a VRML97 file is as follows:

#VRML V2.0 utf8

Any succeeding line with a # at the start is seen as a comment and ignored.

VRML97 MIME Types

The MIME types for VRML are:

x-world/x-vrml
model/vrml

The first is old, and new applications should assume the second one.

Grouping Nodes

The following nodes are grouping nodes, which means that they can contain other nodes in their children field.

  • Anchor
  • Billboard
  • Collision
  • Group
  • LOD
  • Switch
  • Transform

Child Nodes

The following nodes are legal child nodes, which means that they do not need to be contained within anything else, but can be contained within grouping nodes. Therefore, they can go either at the root of the scene graph or further down, contained within one of the grouping nodes described earlier.

  • Anchor
  • Background
  • Billboard
  • Collision
  • ColorInterpolator
  • CoordinateInterpolator
  • CylinderSensor
  • DirectionalLight
  • Fog
  • Group
  • Inline
  • LOD
  • NavigationInfo
  • NormalInterpolator
  • OrientationInterpolator
  • PlaneSensor
  • PointLight
  • PositionInterpolator
  • ProximitySensor
  • ScalarInterpolator
  • Script
  • Shape
  • Sound
  • SpotLight
  • SphereSensor
  • Switch
  • TimeSensor
  • TouchSensor
  • Transform
  • Viewpoint
  • VisibilitySensor
  • WorldInfo
  • Child nodes redefined
    with PROTO

Bindable Nodes

The following nodes are bindable.

  • Background
  • Fog
  • NavigationInfo
  • Viewpoint

Geometry Nodes

The following nodes are geometry nodes, and can only be contained inside a Shapes geometry field.

  • Box
  • Cone
  • Cylinder
  • ElevationGrid
  • Extrusion
  • IndexedFaceSet
  • IndexedLineSet
  • PointSet
  • Sphere
  • Text

Special Nodes

The following are special nodes, and can only be contained within certain fields in certain nodes:

Node Parent Field
Appearance Shape appearance
AudioClip Sound source
Color ElevationGrid
IndexedFaceSet
IndexedLineSet
color
color
color
Coordinate IndexedFaceSet
IndexedLineSet
PointSet
coord
coord
coord
FontStyle Text fontStyle
ImageTexture Appearance texture
Material Appearance material
MovieTexture Appearance
Sound
texture
source
Normal ElevationGrid
IndexedFaceSet
normal
normal
PixelTexture Appearance texture
TextureCoordinate ElevationGrid
IndexedFaceSet
texCoord
texCoord
TextureTransform Appearance textureTransform

Return to the top of the page.

Now that you've gotten free know-how on this topic, try to grow your skills even faster with online video training. Then finally, put these skills to the test and make a name for yourself by offering these skills to others by becoming a freelancer. There are literally 2000+ new projects that are posted every single freakin' day, no lie!


Previous Article

Next Article


Antonio's Comment
Hey Danik,I actually place an cboejt that defines which side is the outside, and which side is the inside. So, wherever that cboejt is placed is where it starts to fill the wall from, and once the wall is filled I can detect which side the grass should be on.I have however been using a script that can detect which is the inside/outside of a particular shape, but I was finding that, sometimes, I actually wanted to fill what would be the outside, rather then the inside (in the Ogmo screenshot above you can see an cboejt called F placed near the center of the screen. That's the Filler cboejt)
12 Mon Mar 2012
Admin's Reply:

I don't understand what you meant regarding the "Ogmo screenshot above". However, I'm still quite a n00b with VRML. I've only recently been able to create object's based on shape as foresee it. Thanks for your comment Antonio.




Brijesh Pant's Comment
Can i make the JPEG Image to HTML by using this ? If yes please give me suggestion.
14 Sat Aug 2010
Admin's Reply:

Nope, doesn't work that way.




oluwole's Comment
it's great
14 Wed Jul 2010
Admin's Reply:

You're Welcome.




Surbhi's Comment
Its a very good article.. But for a beginner to VRML tings are not that easy..
20 Tue Oct 2009
Admin's Reply: in my view, it's quite tedious to learn if you go through the coding. there are however, WYSIWYG type of VRML editors out there.