The Moving Worlds VRML 2.0 Specification

External API Bindings

Draft 2b, June 4, 1996

This section describes bindings for the external application programming interface to the VRML browser.

VRML 2.0 has a standard mechanism for interfacing to the outside world. Depending on the external environment a large variety of bindings to the VRML world are possible. This document separates these into 2 major categories: language bindings and network bindings.

Language Bindings

Binding to a VRML world through a language interface will be a common means of communication. This can be done as a standalone application or as part of a plug-in style archtecture such as Netscape or Internet Explorer.

Java

Java provides its own environment. Communicating with a VRML world first involves loading of that world. This can be done with a some sort of VRML class library or, in the case of Java-within-Netscape, through the document interface. In either case a pointer to the world allows events to be sent to accessible nodes within the world.

To Be Completed...

JavaScript

Netscape is defining a general mechanism for interfacing JavaScript on an HTML page to a plug-in. This is done with a JavaScript object for each plug-in. The methods defined for an object is plug-in specific. A VRML Browser has the following API.

The name of the frame containing the VRML world is used to access the world. This object contains a sendEventIn() method for sending events to the world and a getEventOut() method for getting the current value of an eventOut. For instance, take this VRML world:

    #VRML V2.0 ...

    DEF Camera Viewpoint { }
    DEF MySphere Transform { 
        children [
            Shape { 
                appearance Appearance { 
                    material Material { diffuseColor 0 0 1 }
                }
                geometry Sphere { }
            }
        ]
     }

If this world is in a Netscape frame named "vrml" a JavaScript author can translate the Sphere by a relative amount by embedding the following JavaScript in the HTML page:

    function myTranslator(x, y, z) {
        translate = document.vrml.
                    getEventOut("MySphere", "translation_changed");
        translate[0] += x;
        translate[1] += y;
        translate[2] += z;
        document.vrml.
            sendEventIn("MySphere", "set_translation", translate);
     }

To change the authored position of the camera in the above scene use the following JavaScript:

    function myCameraMover(x, y, z) {
        translate = document.vrml.
                    getEventOut("Camera", "position_changed");
        translate[0] += x;
        translate[1] += y;
        translate[2] += z;
        document.vrml.
            sendEventIn("Camera", "set_position", translate);
    }

Handling an eventOut from JavaScript requires a bit more work. First interest must be expressed in a particular eventOut with the expressInterest() method. This not only indicates which eventOut JavaScript wishes to handle but also gives the function that should be called when the eventOut is generated in the VRML world. For instance, given this world:

    #VRML V2.0 ...

    Shape { ... geometry for a cup ... }
    DEF Cup TouchSensor { }

and this JavaScript:

    function handleEventOut(value, timestamp, node, event) {
        ... handle value event ...
    }

    function mySetup() {
        document.vrml.
        expressInterest("Cup", "isActive", handleEventOut);
    }

When the mySetup() function the handler is set up. Now when the user presses the mouse button over the cup in the VRML world the the function handleEventOut() is called. Another event is generated when the user releases the mouse. The value parameter is set to the boolean value of the isActive field. Also, timestamp is set to the time when the mouse was pressed or released and the node and event parameters are set to the strings corresponding to the DEF name and eventOut of the event generated. These 2 values allow one function to handle multiple events. They are placed last so they can be omitted in the simple case of the function handling a single event.

Integrating Javascript Control with VRML Functionality

Interacting with the scene using the above interface allows simple manipulation of specific nodes. For more complex interaction JavaScript can send events to a Script node in the VRML scene which performs complex scene control. Here is a simple JavaScript function which starts an interpolated animation in the VRML scene:

    function myStartAnimation() { 
        document.vrml.sendEventIn("Interface", "start", true); 
    }

The VRML scene looks like this:

    ...
    DEF Interface Script {
        eventIn SFBool start
        eventOut SFTime startTime

        url "vrmlscript: 
             function start(value, timestamp) { 
                 startTime = timestamp; 
             }"
    }

    DEF PI PositionInterpolator {
        keys [ ... keys ... ]
        values [ ... position values ... ]
    }

    DEF TS TimeSensor { cycleInterval 5 } # 5 second animation

    DEF T Transform {
        children [ ... geometry to animate ... ]
    }

    ROUTE Interface.startTime TO TS.startTime
    ROUTE TS.fraction TO PI.set_fraction
    ROUTE PI.outValue TO T.translation
    ...

The Script can then send multiple messages to start combinations of operations.

With this interface a VRML scene can be completely controlled from external Javascript functions or the external controls can simply stimulate the VRML scene to do more complex functions internally.

Browser API

The Browser API of VRML is accessible as methods on the plug-in object ("vrml" in our example). For example, constructing the first scene above could be done in JavaScript using the Browser API:

    function mySceneBuilder {
       with (document.vrml) {
           // create the 2 root nodes
           scene[0] = createVRMLFromString("DEF Camera Viewpoint { }");
           scene[1] = createVRMLFromString("DEF MySphere Transform { }");
 
           // create the shape and its children
           shape = createVRMLFromString("Shape { }");
           appearance = createVRMLFromString("Appearance { }");
           sendEventIn(shape, "set_appearance", appearance);
           geometry = createVRMLFromString("Sphere { }");
           sendEventIn(shape, "set_geometry", geometry);
 
           // add a material to the appearance
           material = createVRMLFromURL("Material { }");
           color[0] = 0; color[1] = 0; color[2] = 1;
           sendEventIn(material, "set_diffuseColor", color);
           sendEventIn(appearance, "set_material", material);

           // add the shape to the Transform
           sendEventIn(scene[1], "add_children", shape);

           // make this the vrml scene
           replaceWorld(scene);
       }
    }

Now the scene can be controlled as in the early examples.

Network Bindings

TBD

 Contact rikk@best.com , cmarrin@sgi.com, or gavin@acm.org with questions or comments.
This URL: http://vrml.sgi.com/moving-worlds/spec/scriptref.html.