Building Virtual Worlds

Lecture 4: VRML Introduced and Demonstrated

This lecture has two parts: Theory and Practice. The Theory part of the lecture makes uses of examples taken from theVRML 2.0 Handbook, which can be purchased from www.barnesandnoble.com. In these notes, we'll refer to that handbook as V2H. The actual dialect of VRML we will be using is called VRML97.

The main tool we will be using is called CPC - I'll tell you what that stands for in class. It's available for download from my site.

The main source of information about VRML and three dimensional stuff on the Web can be found at www.web3d.org

You will also need a plug-in with which to enable your browser to look at VRML files. There are two player plug-ins available at the same site, which is www.cai.com/cosmo. The player most folks use is called Cosmo Player; it was originally from Silicon Graphics. You can also get the WorldView plug-in from InterVista (Brian Blau's former company) from the same site. (Click the plug-ins button and do what you're told.) It took me about a half-hour to get Cosmo Player and an hour to download the WorldView plug-in via 56k modem.

Why do we need a plug-in? Well, you can view VRML with the CPC, but its ultimate purpose was to become a kind of '3d HTML' and to be included into web sites. To conveniently see VRML in this fashion, you need a plug-in.
Basics. The VRML universe has a coordinate system with X to the right, Y up and Z coming out of the screen at you. This is called "right handed" because if your right hand's fingers go from the X to the Y axis, your thumb is pointing along the Z axis. The coordinates are normally thought of as having the meaning of meters, though you can think anything you want of course. In the Tenochtitlan example from V2H, all measurements are in feet (which is wierd, as Mexico is a metric country!)

Here is a simple link to a local copy of the program we'll start with today. (The example number comes from the book's Chapter 3, even though this is Lecture 4.) If you click on this link AND your Netscape or Internet Explorer is VRML-ready (because one of the above plug-ins has been installed), then you will get a quick peek of a large purple cylinder.

And here's the actual source for Example 3.1:

#VRML V2.0 utf8
# Your basic purple cylinder - Example 3.1, Page 38 of V2H
Shape {
appearance Appearance{
material Material {
diffuseColor .5 0 .5
shininess .5
}
}
geometry Cylinder {
height 6
side TRUE
top FALSE
bottom TRUE
}
}

We'll discuss the following concepts in class.

Scene Graph - a part-whole hierarchical description of a scene, of which a VRML file is an example. We often represent Scene Graphs (an abstract concept) with concrete Scene Diagrams.

The structure of a scene diagram is organized as follows: (this display is from Community Space Conductor)

Each of these types of nodes will contain a bunch of information. We see in Example 3.1 that the appearance node can specify a material, which in turn can specify surface properties such as diffuseColor (red green blue, 0 to 1) and shininess (0 to 1).

The Geometry node can specify a number of basic objects including cylinder, Cone and Box, as well as user-defined shapes. The parameters of a geometric object are rather obvious, but in general, you need some documentation to explore the legal values for parameters as well as to find about parameters that might not be in the examples you are exploring.

The order of presentation nodes at a given level in the scene graph is up to the display system. CPC, as you see above, puts geometry before appearance, whereas V2H puts the appearance first.

Working with VRML using Community Place Conductor. At this point, please refer to the Tutorial that came with CPC. We'll informally introduce some theoretical concepts as we go along through the tutorial, including:

Sensor Node
Routes
Events

Here are some Queries for today, based on Chapter 1 of the Tutorial.

Query 4.1. Try opening the Cylinder example using CPC. You should see the above Scene Graph. Now try adding a TouchSensor to the Cylinder, like we added it in the Tutorial. What happens? Why?

TouchSensors, like almost every other structure in VRML, expect to hang off of a Transform node. The simple Cylinder example did not include a Transform node, and so the TouchSensor had no place to go.

Query 4.2. What would happen if, instead of routing from TS1.isActive, you routed from TS1.isOver? Use the DELETE button to get rid of the previous route, then add the new route.

The behavior is much as one would expect. But now, for some more soul searching, how about:

Query 4.3. Try putting BOTH routes in place at the same time. Without deleting the route from TS1.isOver to PL1.on, add na new route fromTS1.isActive to PL1.on. Is there any behavioral difference? It would seem that "isOver" would always be true whenever the mouse cursor is in any position to trigger the light, and thus it would seem that the isActive command would be useless.

To understand why this is NOT the case, you need to think about how Events work. Events are different from Boolean state variables, because they are always (effectively) instantaneous. The following text describes events.

Theory: Events in multi-threaded software systems

The simplest programming model is one in which your program has ultimate control of when everything happens. Only when you call a procedure such as a disk write or a keyboard read, does anything actually happen to an i/o device. This model is obsolete for most applications.

The modern paradigm is "interrupt-driven". A sophisticated operating system (or even Windows 95) runs on top of hardware capable of generating interrupts within a priority structure. An interrupt is a procedure call that may happen without your program knowing it's happening. Your program's state is saved and the CPU goes off to do whatever it has to, such as updating the on-screen clock once per second. Then your program resumes.

Interrupts were originally thought of as hardware-generated. Thus when a tape drive had moved to the next available data block, it would interrupt the CPU and a service routine would read the data and store it in RAM or on disk. But the usefulness of having software interrupt other software quickly became apparent. Plain old procedure calls require that you know where the called procedure is, whereas interrupts are just like pulling the fire alarm. Let the fire department worry about where it keeps the trucks; just get them to the fire on time!

Event-driven programming was the result of this evolution. WIMP (Windows, Icons, Mice and Pulldowns) interfaces are inherently event-driven. A mouse-movement or a mouse-click generates a series of events which are handled by the window management system, and directed to the program associated with any particular window. If you click on something within the window belonging to your Web browser, the browser will be notified. If in turn, you click on something within the part of the browser's window which contains VRML, then your VRML plug-in will be notified.

VRML then has to decide what kind of event just happened. Your VRML code will provide a rich collection of sensors which, when clicked on (for instance) generate events. In VRML an event has a very specific meaning: it results in the change of value of a variable associated with a sensor. That new value has to go somewhere, to have an effect.

Fields and Events. We have already seen several fields, which are the parameters describing any node. These included the size and color of the Cylinder, for instance. Fields we've seen so far are static, specified when you write the code. "Events" in VRML look a lot like static fields but they can change values. They change when sensors sense something going on. It could be a collision between a moving and static object, a mouse click, or other conditions that come into being.

We use "routes" to connect sources of events (of type eventOut), with places that should know about them (of type eventIn.).

Key Idea: An Event has BOTH a name and a value. Sometimes the receiving field only cares about the event's name, but usually it also cares about its value. For instance, when you move your mouse over an object, the event isOver is transmitted, with value TRUE. When you move your mouse off of the object, the event isOver is transmitted AGAIN, with value FALSE. Think of the event as an envelope, and its value as the contents.

The name of an event is a kind of classifier, telling you what to do with it. For instance, if a check arrives, you know you have to deposit or cash it. The check's actual value is distinct from its "check-ness."

Exposed Fields are fields (or attributes) for which there are two specially defined events. Assume the field's name is translation.The input version of that field would be set_translation and the output version of it would be translation_changed. You can look in the VRML specifications to see if a given field is exposed; a good place to do this is in the back of the V2H book if you have it. Otherwise look at the online definitions in the VRML specs.

Consider the following example. If XFORM1 and XFORM2 are two transformations, the following code will force XFORM2 to have the same translation as XFORM1, because every time XFORM1 changes, its values will automatically be sent over to XFORM2.

`ROUTE XFORM1.translation_changed TO XFORM2.set_translation`
(You can actually omit the _changed and set_ handles, but I don't recommend it. They are useful for clarity, to remind us that we're working with dynamic data.)

You cannot send events to nodes defined in a file that has been supplied by an Inline node.

Query 4.4: How, then, could you bring in an object such as the chacmool, and make it perform a pre-planned series of actions? (You may have to come back to this question after you know how to make something do some actions.)

In addition to the "implicit" events defined by exposed fields, there are also events that are explicitly defined. These are indicated by eventIn or eventOut in the node description. Here's an example of how you can make a light come on while you hold down the mouse button.

`Group {`
`children [`
`DEF LIGHT_CONTROL TouchSensor { }`
`Inline {`
`url [ "lightswitch.wrl" ] # Click this to light the light`
`}`
`]`
`}`
`DEF LIGHT PointLight {`
`location -6 4 2`
`on        FALSE`
`}`
`Inline { url [ "table.wrl"] } # objects to be lit`
`ROUTE LIGHT_CONTROL.isActive TO LIGHT.set_on`
Now when the user points to the light switch and presses the left mouse button, the touch sensor named LIGHT_CONTROL generates a Boolean event named isActive, with value TRUE. The ROUTE statement sends this event to the node named LIGHT.

Working with VRML Using a Word Processor. If you don't have a tool like CPC, you can still manipulate VRML as follows. In fact it's good to know how to do this, too, because you shouldn't be totally dependent on a single tool.

The above example source code can be stored in a folder on your computer; use Netscape or Explorer to follow the link, then 'save as' into your folder of choice. Now you can use any convenient editor like WordPad or Microsoft Word to edit the file. When you SAVE, make sure the extension is .wrl and the file type is plain text. (Word loves to put .txt on, instead. And if you're not careful, it'll put the whole thing out as a binary .doc file which is useless for our purposes.)

Then, use your browser's OPEN command to browse down to that file in that folder (file:/// etc.) and open your VRML file (this whole strategy works for HTML just as it does for VRML.) If your Cosmo or WorldView plug-in is properly installed, you will now see your VRML model. (If this doesn't work, just open CP Browser to look at the model.)

Now you can minimize the browser, maximize the word processor, and change the file. Then minimize the editor, maximize the browser and click the RELOAD button. You can alternate back and forth between the editor and browser like this and make rapid progress.

More Concepts

Transforming the Cylinder. A 'transformation' is an operation that moves data through space. A point (x,y,z) can be moved by a distance of (dx, dy, dz) by simply adding the values pairwise, so we get a new point (x+dx, y+dy, z+dz). In VRML, that looks like the following:

#VRML V2.0 utf8
# The cylinder somewhere else - Example 3.2, Page 41 of V2H
Transform{
translation -2.4 2 3
children [    # NOTE the square bracket here!

Shape {

appearance Appearance{
material Material {

diffuseColor .5 0 .5
shininess .5
}
}
geometry Cylinder {
height 6
side TRUE
top FALSE
bottom TRUE
}
}
]
} # End of transform grouping

That's it for today - except for the following Lab Project 1. More next week. Happy Holiday!

Back to the course syllabus
Back to the previous lecture
Onward to the next lecture