Key Concepts

February 2, 1996

This section describes key concepts related to the use of VRML, including how nodes are combined into scene graphs, how nodes receive and generate events, how to create node types using prototypes, how to add node types to VRML and export them for use by others, and how to incorporate programmatic scripts into a VRML file.

This subdocument includes the following sections:

File Syntax and Structure

For easy identification of VRML files, every VRML 2.0 file must begin with the characters:

#VRML V2.0 utf8

The identifier utf8 allows for international characters to be displayed in VRML using the UTF-8 encoding of the ISO 10646 standard. Unicode is an alternate encoding of ISO 10646. UTF-8 is explained under the Text node.

Any characters after these on the same line are ignored. The line is terminated by either the ASCII newline or carriage-return characters.

The # character begins a comment; all characters until the next newline or carriage return are ignored. The only exception to this is within double-quoted SFString and MFString fields, where the # character will be part of the string.

Note: Comments and whitespace may not be preserved; in particular, a VRML document server may strip comments and extra whitespace from a VRML file before transmitting it. WorldInfo nodes should be used for persistent information such as copyrights or author information. To extend the set of existing nodes in VRML 2.0, use prototypes or external prototypes rather than named information nodes.

Blanks, tabs, newlines and carriage returns are whitespace characters wherever they appear outside of string fields. One or more whitespace characters separate the syntactical entities in VRML files, where necessary.

After the required header, a VRML file can contain the following:

Field names start with lowercase letters. Node types start with uppercase. The remainder of the characters may be any printable ASCII characters (0x21-0x7E) except curly braces {}, square brackets [], single ' or double " quotes, sharp #, backslash \\ plus +, period . or ampersand &.

Node names (specified using the DEF keyword; see the "Instancing" section of this document for details) must not begin with a digit, but they may begin with and contain any UTF8 character except those below 0x21 (control characters and white space), and the characters {} [] ' " # \\ + . and &.

VRML is case-sensitive; "Sphere" is different from "sphere" and "BEGIN" is different from "begin."

URLs and URNs

A URL (Universal Resource Locator) specifies a file located on a particular server and accessed through a specified protocol. A URN (Universal Resource Name) provides a more persistent way to refer to data than is provided by a URL. The exact definition of a URN is currently under debate. See the discussion at http://www.w3.org/hypertext/WWW/Addressing/Addressing.html for further details.

All fields in VRML 2.0 that have URLs are of type MFString. The strings in such a field indicate multiple places to look for files, in decreasing order of preference. If the browser can't locate the first file or doesn't know how to deal with a URN given as the first file, it can try the second location, and so on.

VRML 2.0 browsers are not required to support URNs. If they do not support URNs, they should ignore any URNs that appear in MFString fields along with URLs. URN support is specified in a separate document at http://www.mitra.biz/vrml/vrml2/vrml-urn.html, which may undergo minor revisions to keep it in line with parallel work happening at the IETF.

Relative URLs are handled as described in RFC 1808, "Relative Uniform Resource Locators."

File Extension

The file extension for VMRL files is .wrl (for world).

MIME Type

The MIME type for VRML files is defined as follows:

x-world/x-vrml

The MIME major type for 3D world descriptions is x-world. The MIME minor type for VRML documents is x-vrml. Other 3D world descriptions, such as oogl for The Geometry Center's Object-Oriented Geometry Language, or iv, for SGI's Open Inventor ASCII format, can be supported by using different MIME minor types.

It is anticipated that the official type will change to "model/vrml". At this time, servers should present files as being of type x-world/x-vrml. Browsers should recognise both x-world/x-vrml and model/vrml.

IETF work-in-progress on this subject can be found in "The Model Primary Content Type for Multipurpose Internet Mail Extensions."

Nodes, Fields, and Events

At the highest level of abstraction, VRML is just a file format for describing objects. Theoretically, the objects can contain anything--3D geometry, MIDI data, JPEG images, and so on. VRML defines a set of objects useful for doing 3D graphics. These objects are called nodes. Nodes contain data, which is stored in fields.

VRML defines several different classes of nodes. Most of the nodes can be classified into one of two categories; grouping nodes or leaf nodes. Grouping nodes gather other nodes together, allowing collections of nodes (specified in a grouping-node field called children) to be treated as a single object. Some grouping nodes also control which of their children are drawn. Grouping nodes can have only other grouping nodes or leaf nodes as children.

Leaf nodes may not have children. Nodes that are considered leaf nodes include shapes, lights, viewpoints, sounds, scripts, sensors, interpolators, and nodes that provide information to the browser.

Shape nodes contain two kinds of additional information: geometry and appearance. For purposes of discussion, this specification uses a third node category, subsidiary nodes, for nodes that are always used within fields of other nodes and cannot be used alone. These nodes include geometry (for example, Cone and Cube), geometric property (for example, Coordinate3 and Normal), appearance (Appearance) and appearance property nodes (for example, Material and Texture2).

Nodes can be prototyped and shared. Nodes are arranged in hierarchical structures called scene graphs. A Transform node is a kind of grouping node that defines a coordinate system for its child (leaf) nodes. Each Transform node defines a coordinate system relative to its parent nodes (see Coordinate Systems and Transformations).

Applications that interpret VRML files need not maintain the scene graph structure internally; the scene graph is merely a convenient way of describing objects.

General Node Characteristics

A node has the following characteristics:

The syntax for representing these pieces of information is as follows:

nodetype { fields }

Only the node type and braces are required; nodes may or may not have fields.

Sample File Format

For example, this file contains a simple scene defining a view of a red cone and a blue sphere, lit by a directional light:

#VRML V2.0 utf8
Transform {
  children [

    DirectionalLight {
        direction 0 0 -1  # Light shining into scene
    },

    Transform {   # The red sphere
      translation 3 0 1
      children [
        Shape {
          geometry Sphere {radius 2.3}
          appearance Appearance [ 
             material Material {diffuseColor 1 0 0} ] # Red
        }
      ]
    },

    Transform {  # The blue cube
      translation -2.4 .2 1
      rotation     0 1 1  .9
      children [
        Shape {
          geometry Cube {}
          appearance Appearance [ 
             material Material {diffuseColor 0 0 1} ] # Blue
        }
      ]
    }

  ]
}

The Structure of the Scene Graph

This section describes the general scene graph hierarchy, how to reuse nodes within a file, coordinate systems and transformations in VRML files, and the general model for viewing and interaction within a VRML world.

Grouping Nodes and Leaves

A scene graph consists of grouping nodes and leaf nodes. Grouping nodes, such as Transform, LOD, and Switch, can have child nodes. These children can be other grouping nodes or leaf nodes, such as shapes, browser information nodes, lights, cameras, and sounds. Appearance, appearance properties, geometry, and geometric properties are contained within Shape nodes.

Transformations are stored within Transform nodes. Each Transform node defines a coordinate space for its children. This coordinate space is relative to the parent (Transform) node's coordinate space--that is, transformation accumulate down the scene graph hierarchy. Geometric sensors are contained within a Transform node.

Instancing

A node may be referenced in a VRML file multiple times. This is called instancing (using the same instance of a node multiple times; called "aliasing" or "multiple references" by other systems) and is accomplished by using the DEF and USE keywords.

The DEF keyword gives a node a name and creates an instance of the node. The USE keyword indicates that a previously named node should be used again. If several nodes were given the same name, then the last DEF encountered during parsing "wins." DEF/USE is limited to a single file. There is no mechanism for using nodes that are defined in other files. Nodes cannot be shared between files. For example, if a node is defined inside a file referenced by a WWWInline node, the file containing the WWWInline node cannot USE that node.

Rendering the following scene results in three spheres being drawn. Both of the spheres are named "Joe"; the second (smaller) sphere is drawn twice, on either side of the first (larger) sphere:

#VRML V2.0 utf8
Transform {
  children [
    DEF Joe Sphere { },
    Transform {
      translation 2 0 0
      children [
        DEF Joe Sphere { radius .2 }
      ]
    },
    Transform {
      translation -2 0 0
      children [
        USE Joe  # radius .2 sphere will be used here; most recent one defined
      ]
    }
  ]
}

Coordinate Systems and Transformations

VRML uses a Cartesian, right-handed, 3-dimensional coordinate system. By default, objects are projected onto a 2-dimensional display device by projecting them in the direction of the positive Z axis, with the positive X axis to the right and the positive Y axis up. A modeling transformation can be used to alter this default projection.

The standard unit for lengths and distances is meters. The standard unit for angles is radians.

VRML scenes may contain an arbitrary number of local (or object-space) coordinate systems, defined by the transformation fields of the Transform node. These fields are translation, rotation, scaleFactor, scaleOrientation, and center.

Given a vertex V and a series of transformations such as:

Transform {
  translation T
  rotation    R
  scale       S
  children [
    Shape {
      geometry[ PointSet { ... }]
    }
  ]
}

the vertex is transformed into vertex V' in world-space by first scaling, then rotating, and finally translating. In matrix-transformation notation, thinking of T, R, and S as the equivalent transformation matrices,

V' = T·R·S·V

(if you think of vertices as column vectors)

or

V' = V·S·R·T

(if you think of vertices as row vectors).

Conceptually, VRML also has a world coordinate system. The various local coordinate transformations map objects into the world coordinate system, which is where the scene is assembled. Transformations accumulate downward through the scene graph hierarchy, with each Transform inheriting the transformations of its parents. (Note however, that this series of transformations takes effect from the leaf nodes up through the hierarchy. The local transformations closest to the Shape object take effect first, followed in turn by each successive transformation upward in the hierarchy.)

Viewing Model

This specification assumes that there is a user viewing and interacting with the VRML world. It is expected that a future extension to this specification will provide mechanisms for creating multi-participant worlds. The viewing and interaction model that should be used for the single-participant case is described here.

The world creator may place any number of viewpoints in the world -- interesting places from which the user might wish to view the world. Each viewpoint is described by a Viewpoint node. Viewpoints exist in a particular coordinate system, and either the viewpoint or the coordinate system may be animated.

It is expected that browsers will support user-interface mechanisms by which users may "teleport" themselves from one viewpoint to another, and scripting-language mechanisms by which a viewer can be bound to a viewpoint which can then be animated. If a user teleports to a viewpoint that is moving (one of its parent coordinate systems is being animated), then the user should move along with that viewpoint.

The browser may provide a user interface that allows the user to change his or her viewing position or orientation, which will also change the currently bound viewpoint.

Time

The browser controls the passage of time in a world by causing TimeSensors to generate events as time passes. Specialized browsers or authoring applications may cause time to pass more quickly or slowly than in the real world, but typically the times generated by TimeSensors will roughly correspond to "real" time.

A world's creator must make no assumptions about how often a TimeSensor will generate events but can safely assume that each time event generated will be greater than any previous time event.

Typically, a TimeSensor affecting a visible (or otherwise perceptible) portion of the world will generate events once per "frame," where a "frame" is a single rendering of the world or one time-step in a simulation.

Events

Most nodes can receive events, which have names and types corresponding to their fields, with the effect that the corresponding field is changed to the value of the event received. For example, the Transform node can receive set_translation events (of type SFVec3f) that change the Transform's translation field (it may also receive set_rotation events, set_scale events, and so on).

Nodes can also generate events that have names and types corresponding to their fields when those fields are changed. For example, the Transform node generates a translation_changed event when its translation field changes.

Routes

The connection between the node generating the event and the node receiving the event is called a route. A node that produces events of a given name (and a given type) can be routed to a node that receives events of the same type using the following syntax:

ROUTE NodeName.eventOutName TO NodeName.eventInName

Routes are not nodes; ROUTE is merely a syntactic construct for establishing event paths between nodes.

Sensors

Sensor nodes generate events. Geometric sensor nodes (BoxProximitySensor, ClickSensor, CylinderSensor, DiskSensor, PlaneSensor, and SphereSensor) generate events based on user actions, such as a mouse click or navigating close to a particular object. TimeSensor nodes generate events at regular intervals, as time passes.

Prototypes

Prototyping is a mechanism that allows the set of node types to be extended from within a VRML file. It allows the encapsulation and parameterization of geometry, behaviors, or both.

A prototype definition consists of the following:

Square brackets enclose the list of events and fields, and braces enclose the definition itself:

PROTO prototypename [ eventIn      eventtypename name
                      eventOut     eventtypename name
                      exposedField fieldtypename name defaultValue
                      field        fieldtypename name defaultValue
                      ... ] {
  Scene graph
  (nodes, prototypes, and routes)
}

A prototype is not a node; it merely defines a prototype (named prototypename) that can be instantiated later in the same file as if it were a built-in node. The implementation of the prototype is contained in the scene graph rooted by node. That node may be followed by Script and/or ROUTE declarations, as necessary to implement the prototype.

The eventIn and eventOut declarations export events from the scene graph rooted by node. Specifying the type of each event in the prototype is intended to prevent errors when the implementation of prototypes is changed and to provide consistency with external prototypes. Events generated or received by nodes in the prototype's implementation are associated with the prototype using the keyword IS. For example, the following statement exposes a Transform node's built-in set_translation event by giving it a new name (set_position) in the prototype interface:

Transform {
  set_translation IS set_position
}

Fields hold the persistent state of VRML objects. Allowing a prototype to export fields allows the initial state of a prototyped object to be specified when an instance of the prototype is created. The fields of the prototype are associated with fields in the implementation using the IS keyword. For example:

Transform {
  translation IS position
}

A prototype is instantiated as if typename were a built-in node. For example, a simple chair with variable colors for the leg and seat might be prototyped as:

PROTO TwoColorChair [ field MFColor legColor  .8 .4 .7
                      field MFColor seatColor .6 .6 .1 ] {
  Transform {
    children [

      Transform { # chair seat
        children [
          Shape {
            appearance Appearance {
              material Material { diffuseColor IS seatColor }
            }
            geometry Cube { ... }
          }
        ]
      },

      Transform { # chair leg
        translation ...
        children [
          Shape {
            appearance Appearance {
              material Material { diffuseColor IS legColor }
            }
            geometry Cylinder { ... }
          }
        ]
      }

    ] # End of root Transform's children
  } # End of root Transform
} # End of prototype

The prototype is now defined. Although it contains a number of nodes, only the legColor and seatColor fields are public. Instead of using the default legColor and seatColor, this instance of the chair has red legs and a green seat:

TwoColorChair {
  legColor 1 0 0
  seatColor 0 1 0
}

A prototype instance can be used in the scene graph wherever its root node can be used. For example, a prototype defined as

PROTO MyObject [ ... ] {
  Transform { ... }
}

can be instantiated wherever a Transform can be used, since the root node of this prototype's implementation is a Transform node.

Prototype definitions can be nested. A prototype instance may be DEF'ed or USE'ed. Prototype or DEF names declared inside the prototype are not visible outside the prototype.

Defining Prototypes in External Files

The syntax for defining prototypes in external files is as follows:

EXTERNPROTO prototypename [ eventIn eventtypename name
                            eventOut eventtypename name
                            field fieldtypename
                            ... ]
  "URL" or [ "URL", "URL", ... ]

The external prototype is then given the name prototypename in this file's scope. It is an error if the eventIn/eventOut declaration in the EXTERNPROTO is not a subset of the eventIn/eventOut declarations specified in the PROTO referred to by the URL. If multiple URLs are specified, the first one found should be used.

Unlike a prototype, an external prototype does not contain an inline implementation of the node type. Instead, the prototype definition and implementation is found in a set of URLs. The other difference between a prototype and an external prototype is that external prototypes do not contain default values for fields. The external prototype points to a file that contains the prototype implementation, and this file contains the default values.

Extensibility

The set of built-in VRML nodes can be extended using either prototypes or external prototypes. External prototypes provide a way to extend VRML in a manner that all browsers will understand. If a new node type is defined as an external prototype, other browsers can parse it and understand what it looks like, or they can ignore it. An external prototype uses the URL syntax to refer to an internal or built-in implementation of a node. For example, suppose your system has a Torus geometry node. This node can be exported to other systems using an external prototype:

EXTERNPROTO Torus [ field SFFloat bigRadius
                    field SFFloat smallRadius ]
  ["urn:yourdomain:Torus", "http://machine/directory/protofile" ]

The browser can recognize the URN and look for its own internal implementation of the Torus node. If it does not recognize the URN, it goes to the next URL and searches for the specified prototype file. In this case, if the file is not found, it ignores the Torus. If more URLs are listed, the browser tries each one until it succeeds in locating an implementation for the node or it reaches the end of the list.

Naming Conventions

Check the "File Syntax and Structure" section of this standard for the rules on valid characters in names.

To avoid namespace collisions with nodes defined by other people, any of the following conventions should be followed.

  1. Anyone can pick names that include a suffix of an underscore followed by a domain name that you own with the periods changed into underscores. For example, a company owning foo.com could create an extension node "Cube_foo_com".
  2. If you are building a product-- for example, an authoring tool or a browser-- or defining a lot of new nodes, then you can apply for a short prefix. Email type_registry@vrml.org to register for the prefix. This will normally be accepted if it is the most significant part of a .com, .org, or .net address. In the above example, foo.com could register the extension "_foo" and create nodes of the form "Cube_foo".
  3. Extensions supported by several companies should be registered and use the "_X" extension.

Scripting

Logic is often necessary to decide what effect an event should have on the scene -- "if the vault is currently closed AND the correct combination is entered, THEN open the vault." These kinds of decisions are expressed as Script nodes that take in events, process them, and generate other events. A Script node can also keep track of some information between invocations, "remembering" what its internal state is over time.

The event processing is done by a program contained in (or referenced by) the Script node's behavior field. This program can be written in any programming language that the browser supports.

A Script node is activated when it receives an event. At that point the browser executes the program in the Script node's behavior field (passing the program to an external interpreter if necessary). The program can perform a wide variety of actions: sending out events (and thereby changing the scene), performing calculations, communicating with servers elsewhere on the Internet, and so on.

Two of the most common uses for scripts will probably be animation (using interpolators to smoothly move objects from one position to another) and network operations (connecting to servers to allow multi-user interaction).

Script Languages

Scripts can be written in a variety of languages, including Java, C, and Perl. Moving Worlds does not require browsers to support any particular language. See appendices to this specification for bindings to Java and C.

Execution Model

Every time a Script node receives an eventIn, it executes its script. (Scripts aren't executed at any other time, but they may start asynchronous threads that run concurrently with the browser.) First, all pending eventIn values are queued. For each queued event, in timestamp order from oldest to newest, the eventIn method or function that has the same name is called. (Any given eventIn calls exactly one method.) When the queue is empty, the eventsProcessed() method of the script is called to do any final post-processing that might be needed. For instance, the eventIn methods can simply collect data, leaving eventsProcessed() to process all the data at once, in order to prevent duplication of work.

After execution of the eventsProcessed() method, values stored during script execution as eventOuts are sent as events, one for each eventOut that was set at least once during script execution. At most one message is sent for each eventOut value, and all eventOuts have the same time stamp.

In languages that allow multiple threads, such as Java, you can use the standard language mechanisms to start new threads. When the browser disposes of the Script node (as, for instance, when the current world is unloaded), it calls the shutdown() method for each currently active thread, to give threads a chance to shut down smoothly.

If you want to keep static data in a script (that is, to retain values from one invocation of the script to the next), you can use instance variables--local variables within the script, declared private. However, the value of such variables can't be relied on if the script is unloaded from the browser's memory; to guarantee that values will be retained, you have to store them in fields of the Script node.

Nodes and Fields

The API provides a data type in the scripting language for every field type in VRML. For instance, the Java bindings contain a class called SFFloat, which defines methods for getting and setting the value of variables of type SFFloat. A script can get and set the value of its own fields using these data types and methods.

The API also provides a way to access other nodes in the scene. It allows getting the value of any exposed field of any node that the Script has access to.

Browser Interface

The API provides ways for scripts to find out and change information about the browser. When a browser reads in a scene, it determines certain information based on the fields of the scene's NavigationInfo node. If you want to change that information later, use these browser calls -- changing the fields of the NavigationInfo node via routes wouldn't work even if it were possible.

Here are descriptions of the functions/methods that the browser API supports. The syntax given is the Java syntax; bindings for other languages are not necessarily supported by all browsers.

  public static String getName();
  public static String getVersion();

The getName() and getVersion() methods get the "name" and "version" of the browser currently in use. These values are defined by the browser writer, and identify the browser in some (unspecified) way. They are not guaranteed to be unique or to adhere to any particular format, and are for information only. If the information is unavailable these methods return empty strings.

   public static float getCurrentSpeed();

The getCurrentSpeed() method returns the speed at which the viewpoint is currently moving, in meters per second. If speed of motion is not meaningful in the current navigation type, or if the speed cannot be determined for some other reason, 0.0 is returned.

  public static float getCurrentFrameRate();

The getCurrentFrameRate() method returns the current frame rate in frames per second. The way in which this is measured and whether or not it is supported at all is browser dependent. If frame rate is not supported, or can't be determined, 100.0 is returned.

  public static String getWorldURL();
  public static void loadWorld(String [] url);

The getWorldURL() method returns the URL for the root of the currently loaded world. loadWorld() loads one of the URLs in the passed string and replaces the current scene root with the VRML file loaded. The browser first attempts to load the first URL in the list; if that fails, it tries the next one, and so on until a valid URL is found or the end of list is reached. If a URL cannot be loaded, some browser-specific mechanism is used to notify the user. It's up to the browser whether to block on a loadWorld() until the new URL finishes loading, or whether to return immediately and at some later time (when the load operation has finished) replace the current scene with the new one.

  public static Node createVrmlFromURL( String[] url );
  public static Node createVrmlFromString( String vrmlSyntax );

The createVrmlFromString() method takes a string consisting of a VRML scene description and returns the root node of the corresponding VRML scene. The createVRMFromURL() asks the browser to load a VRML scene description from the given URL or URLs, returning the root node of the corresponding VRML scene.

  public void addRoute(Node fromNode, String fromEventOut,
    Node toNode, String toEventIn);
  public void deleteRoute(Node fromNode, String fromEventOut,
    Node toNode, String toEventIn);

These methods respectively add and delete a route between the given event names for the given nodes. An exception is generated if the given nodes do not have the given event names or if an attempt is made to delete a route that does not exist.

  public void bindBackground(Node background);
  public void unbindBackground();
  public boolean isBackgroundBound(Node background);

bindBackground() allows a script to specify which Background node should be used to provide a backdrop for the scene. Once a Background node has been bound, isBackgroundBound() indicates whether a given Background node is the currently bound one, and unbindBackground() restores the Background node in use before the previous bind. If unbindBackground() is called when nothing is bound, nothing happens. Changing the fields of a currently bound Background node changes the currently displayed background.

  public void bindNavigationInfo(Node navigationInfo);
  public void unbindNavigationInfo();
  public boolean isNavigationInfoBound(Node navigationInfo);

bindNavigationInfo() allows a script to specify which NavigationInfo node should be used to provide hints to the browser about how to navigate through a scene. Once a NavigationInfo node has been bound, isNavigationInfoBound() indicates whether a given node is the currently bound one, and unbindNavigationInfo() restores the NavigationInfo node in use before the previous bind. If unbindNavigationInfo() is called when nothing is bound, nothing happens. A script can change the fields of a NavigationInfo node using events and routes. Changing the fields of a currently bound NavigationInfo node changes the associated parameters used by the browser.

  public void bindViewpoint(Node viewpoint);
  public void unbindViewpoint();
  public boolean isViewpointBound(Node viewpoint);

In some cases, a script may need to manipulate the user's current view of the scene. For instance, if the user enters a vehicle (such as a roller coaster or elevator), the vehicle's motion should also be applied to the viewer. bindViewpoint() provides a way to bind the viewer to a given Viewpoint node. This binding doesn't itself change the viewer location or orientation; instead, it changes the fields of the given Viewpoint node to correspond to the current viewer location and orientation. (It also places the viewer in the coordinate space of the given Viewpoint node.) Once a Viewpoint is bound, the script can animate the transformation fields of the Transform that the Viewpoint is in (probably using an interpolator to generate values) and move the viewer through the scene.

Note that scripts should animate the Viewpoint's frame of reference (the transformation of the enclosing Transform) rather than the Viewpoint itself, in order to allow the user to move the viewer a little during transit (for instance, to let the user walk around inside the elevator while it's between floors). Fighting with the user for control of the viewer is a bad idea.

Note also that results are undefined for vehicle travel if the user is allowed to move out of the vehicle while the animation is running. This problem is best resolved by using collision detection to prevent the user leaving the vehicle while it's in motion. Another option is to turn off the browser's user interface during animation by setting the current navigation type to "none".

When the script has finished transporting the user, unbindViewpoint() releases the viewer from the influence of the currently bound Viewpoint, returning the viewer to the coordinate space of the previous viewpoint binding (or the base coordinate system of the scene if there's no previous binding). The fields of the now-unbound Viewpoint node return to the values they had before the binding.

And of course isViewpointBound() returns TRUE if the specified Viewpoint node is currently bound to the viewer (which implies that the fields of that Viewpoint node indicate the current position and orientation of the viewer). The method returns FALSE if the specified Viewpoint is not bound.

System and Networking Libraries

Scripts that need to use system and networking calls should use the scripting language's system and networking libraries. The VRML API doesn't provide such calls.

Scripting Example

A Script node that decided whether or not to open a bank vault might receive vaultClosed and combinationEntered messages, produce openVault messages, and remember the correct combination and whether or not the vault is currently open. The VRML for this Script node might look like this:

DEF OpenVault Script {
  # Declarations of what's in this Script node:
  eventIn SFBool vaultClosed
  eventIn SFString combinationEntered
  eventOut SFBool openVault
  field SFString correctCombination "43-22-9"
  field SFBool currentlyOpen FALSE

  # Implementation of the logic:
  scriptType "javabc"
  behavior "data:java bytecodes in base64 format go here"
}

The bytecodes in the behavior field might be a compiled version of the following Java source code:

import vrml;

class VaultScript extends Script {

  // Declare fields
  private SFBool currentlyOpen = (SFBool) getField("currentlyOpen");
  private SFString correctCombination = (SFString) getField("correctCombination");

  // Declare eventOuts
  private SFBool openVault = (SFBool) getEventOut("openVault");

  // Handle eventIns
  public void vaultClosed(ConstSFBool value, SFTime ts) {
    currentlyOpen.setValue(FALSE);
  }

  public void combinationEntered(ConstSFString combo, SFTime ts) {
    if (currentlyOpen.getValue() == FALSE &&
        combo.getValue() == correctCombination) {
      currentlyOpen.setValue(TRUE);
      openVault.setValue(TRUE);
    }
  }
}