VRML Behaviors

This paper proposes a way to add behaviors to VRML. It address mainly the extensions needed to VRML to author links to seperate behavior scripts.

This document is part of a collection of VRML2.0 history at http://www.mitra.biz/vrml/vrml2/mw_history.html
This version: Mitra <mitra@mitra.biz>, 25 Oct 95.


History and Dependencies

This proposal is a completely new rewrite of Mitra's behavior proposals. It replaces the previous papers for Behaviors [1] and Connectors, Sensors and Triggers [2].

This paper draws heavily on the proposals by Sony [6], [7] [8] and SDSC [9], and is an attempt to merge the best ideas from these and my own papers.

This proposal does not primarily address the API here. This proposal doesn't significantly constrain the API away from the general ideas that either SDSC, or my proposals cover. See the companion paper on APIs [3].

There is also a brief paper on a number of pseudo-nodes that allow behaviors to access browser state - this is independant from this paper. See Pseudo Nodes [4]

This paper also assumes that Separators change as anticipated for VRML1.1, and that the Interface proposal [5], or something like it, becomes part of VRML1.1.

Overview

Firstly - it appears that we are all looking for a Object-Oriented approach, but I think the proposals diverge from this to a certain extent. To be O-O the author should probably be thinking something like ...

An Object has:

If our O-O model is essentially that a Separator is our Object (since any lower level of detail may have been thrown away by the browser), then this could get fairly easy. Basically we have to:

The various Nodes in all three proposals composite some or all of three sections,

One syntax to do this.
Separator {
    behavior  ""  ; MFSTRING e.g. "http://foo.com/mycode.java"
    scriptType "" ; SFSTRING e.g. "java", the default "" means a ScriptNode   
    events {}     ; MFNODE list of EventHandlers       
}

EventHandler {
    eventOn   ""  ; SFSTRING Node name to watch, default to this Separator
    eventType ""  ; MFENUM  PICK|WORLDIN|WORLDOUT|GRAB|DRAG|RELEASE|FIELD"

    actionObject "" ; SFSTRING Node name to send method to 
                    ; defaults to this Separator
    actionMethod "" ; defaults to Null Event
    actionParameters [ ] ; MFFIELD e.g. [ SFColor 1 0 0 ]    
} 

Notes

Examples

The following examples are taken from various papers, and converted to this scheme, note that most of the examples in all of the existing proposals get syntactically more complex with the Interfaces proposal, and VRML1.1 style separators.

A cube that changes color when picked and again when released

This is an easy example because the action is performed on the same object on which the event occurs.
DEF foo Separator {
    behavior "change.tcl"
    scriptType "tcl"
    events { 
        EventHandler {
            eventType GRAB
            actionMethod "change_color"
            actionParameters "SFCOLOR 1 0 0"
        }
        EventHandler {
            eventType RELEASE
            actionMethod "change_color"
            actionParameters "SFCOLOR 0 0 1"
        }
   }
   Cube {}
}            

Turning the lights on when the switch is grabbed

DEF MyLight PointLight { 
    on FALSE
}
DEF MySwitch Separator { 
    events {
        EventHandler { 
            eventType PICK
            actionObject
            actionMethod "set SFBOOL on TRUE"  ; Trivial behavior
        }
    }
}

Inline behaviors

Inline behaviors can be specified as in Sony's proposal

They are pointed to by leaving ScriptType as the default, and specifying the name of a ScriptNode, or leaving it blank to point at some applicable one.

Open Issue: Where to put this? inline in the Behaviors, or a seperate node or what?

Trivial Methods

A tiny language can be embedded in the "actionMethod" field directly to describe some simple methods. For example, Only the following syntax can be used for describing method.

EventTypes

If the eventType field is to be an SFENUM then we need a complete list of possible events, the parameter field gives us some leeway to experiment later. This is a start of the list.
  1. PICK
    When the mouse is clicked on the object
  2. GRAB,RELEASE
    When the mouse is held down on the object, and when it is released.
    The OS will decide whether the mouse-click is short enough to send as a PICK event, or whether to send GRAB and RELEASE. Also that DRAG events only occur inside GRAB,RELEASE pairs.
  3. DRAG
    Sent when a GRAB-ed object is moved. The position and orientation of the object being moved are available as properties of the Separator.
  4. LOD_IN and LOD_OUT
    When the object is active, and inactive. Typically a behavior may use these events to suspend behavior, or to reduce the CPU cycles this behavior absorbs - for example a mobile object might keep track of where it was, but suspend updating the geometry.
  5. ENTER and LEAVE
    Are triggered when the users viewpoint enters or leaves the bounding box of the object.
  6. COLLISION
    Triggered when the user collides with the object, note this is independant of the changes being made to the Separator to incorporate collision detection. The Collision event is triggered when the collision detection logic prevents the user entering an object. It is never called in conjunction with Enter and Leave.
  7. WORLD_IN and WORLD_OUT
    (from Sony's paper) I believe these are when the world is loaded, and when it is unloaded. Note these are distinct from the Init and End methods which are called when the applet is loaded and unloaded.
  8. FRAME
    Sent once per frame.

Field events

The EventHandler structure doesn't support events which require parameters in order to be triggered. So a small set of extra nodes will need defining for more complex events. The FieldEvent is one example of this, it allows a behavior to be triggered when a field changes value.
FieldEvent {
    eventOn   ""  ; SFSTRING Node name to watch, default to this Separator
    field     ""  ; SFSTRING field to watch

    actionOn, actionMethod, actionParameters  ; as for EventHandler     
}
This could be extended to allow more complex tests - for example only trigger when this field goes to TRUE, however is is not clear that the added complexity is worth it, as compared to having the full power of a programming language available in the behavior. Typically the field being watched will be passed to the Applet in one of the actionParameters.

Timers

Two features facilitate timers indepndantly of functionality that may or may not be available in the language being used (e.g. Java probably has it, Perl probably doesn't).

_Time

A pseudo-object allows a behavior to read the time via GetField calls. The fields need more discussion, but there are probably several different time values that could be watched - so these are made available as seperate fields. The OpenInventor SFTIME type is specified, there might be a better class to use since SFTIME is specified in seconds, or alternatively a millisecond field could be added.
_Time {
    realTime    ; SFTIME - the time asserted by the machine's clock. This
                ; might not be accurate, especially on low-end machines.
    wallClock   ; SFTIME - in a simulation this is the time being simulated
                ; in most circumstances this will be the same as realTime.
    elapsedTime ; SFTIME - time since this simulation started, 
                ; or the world was loaded. (This might not be usefull)
}

TimerEvent

The TimerEvent can either be coded into a VRML file, or added by calls over the API.

One approach would be to add this via one of the ENUM's in the eventType field, however this would probably be hard to author correctly.

TimerEvent {
    type NONE ; SFENUM ONCE|PERIODIC|CALENDAR
    time 0 ; SFTIME   either how often, or at what time, or in how long.

    actionOn, actionMethod, actionParameters  ; as for EventHandler 
}

Further Work

Nasties

In the interests of full disclosure - I've spotted the following nasty features of this proposal that may need addressing.

Consider

References

  1. Obsoleted VRML Behaviors - an API
    Mitra mitra@mitra.biz
    Adding behaviors to VRML - an API between scripts and the VRML
  2. Obsoleted Sensors, Connectors and Triggers proposal
    Mitra mitra@mitra.biz
    Adds sensors to detect events like collisions and picking, connectors to tie fields together, and triggers to trigger an event from a field change.
    http://www.mitra.biz/vrml/vrml2/vrml-trigger.html
  3. VRML - API
    Mitra mitra@mitra.biz
    Defines the API between the browser and external Interpreter
    http://www.mitra.biz/vrml/vrml2/vrml-api.html
  4. Pseudo-Nodes
    Mitra mitra@mitra.biz
    Adding nodes to represent browser, world, and self characteristics
    http://www.mitra.biz/vrml/vrml2/vrml-pseudo.html
  5. Interface proposal
    Mitra mitra@mitra.biz
    Adds an interface to VRML1.1 style separators.
    http://www.mitra.biz/vrml/vrml2/vrml-interface.html
  6. Sony's extensions to the VRML 1.0 standard(V 1.2)
    Kouichi Matsuda matsuda@csl.sony.jp, Yasuaki Honda, honda@csl.sony.jp
    http://www.csl.sony.co.jp/project/VS/evrml1
  7. Comments on Interface Proposal and sensor/trigger proposal
    Kouichi Matsuda, Yasuaki Honda, Rodger Lea, {matsuda, honda, roger}@csl.sony.co.jp
    Sony Computer Science Laboratory Inc and Central Research Center
    http://www.csl.sony.co.jp/project/VS/proposal/comments.html
  8. Sony's approach to behavior and scripting aspects of VRML: an Object-Oriented perspective
    Kouichi Matsuda, Yasuaki Honda, Rodger Lea, {matsuda, honda, roger}@csl.sony.co.jp
    Sony Computer Science Laboratory Inc and Central Research Center
    http://www.csl.sony.co.jp/projects/VS/proposal/behascri.html
  9. Virtual Reality Behavior System (VRBS). A Behavior Language Protocol for VRML.
    David Nadeau, John Moreland of SDSC
    no date or URL on paper.