Tricks of the Java Programming Gurus

Chapter 15: A Virtual Java - Creating VRML 2.0 Behaviours

The book that started this writing thing off. A quickfire chapter that was written litterally in 24hrs. It was a reasonable start, but it suffered from the problem of being written during the time when VRML was still in draft. The result was a chapter full of errors by the time the book came out.

The Changing VRML Spec

At the time the chapter was written, it was draft one of the VRML 2.0 specification. The weekend that I sent the chapter in, draft two came out and significantly changed things again. For example, VRML had TRUE and FALSE data types that were used instead of the Java boolean values. That got readers really confused! Anyway, after all of this work, for draft 3 of the spec, we literally rewrote the Java scripting spec four times in four days. This caused enormous problems for the book that I started writing as a result of this first effort.

In the final version of the VRML Java script bindings, there were many changes. Some of the more fundamental changes were to move many items from interfaces to abstract classes. I don't remember the exact motivation, but it made many things work much nicer in the end. Also, events now just formed part of the cycle of execution. No longer would you "post" events to other nodes, you either had event outs that were routed to your script, or you grabbed the field and used a setValue method to change the value.

After the specification was released as 2.0, moves were made to take it to ISO for real standardisation. As part of this work, a lot of attention was paid to the event model. Although there weren't many changes to the Java API's themselves, their interpretation and implementation within the greater VRML confines certainly did.


Book Updates

To right the matters, here's the examples re-coded to acurately reflect the current ISO version of the VRML specification. As with all of the updates, most of the text still remains current, just the implementation has changed. For these examples to work, make sure that you have a VRML browser installed.


A Colour Changing Box

Changing colour of a box is still the same process. The syntax of the scene has changed somwhat. The source of the file that you want is:
#VRML V2.0 utf8

Transform {
  children [
    Shape {
      geometry Box { size 1 1 1 }
      appearance Appearance {
        material DEF cube_material Material {
          diffuseColor 1 0 0
        }
      }
    } #end of shape definition

    DEF cube_sensor TouchSensor {}
  ]
}

DEF colour_script Script {
  url "colour_changer.class"
  field SFBool isRed TRUE
  eventIn SFBool clicked
  eventOut SFColor colour_out
}

ROUTE cube_sensor.isOver TO colour_script.clicked
ROUTE colour_script.colour_out TO cube_material.diffuseColor
The script changes quite radically. Instead of individual methods for each eventIn, there is now a single event processing method that gets called. (In the ECMAScript script binding, you still have one function call per eventIn). Now, there are also three different packages to write the script implementation with.

Probably the biggest change in style is that there really is no need to store the values for field variables in the script node itself. That causes a lot of overheads in java to native boundary crossing. It is much better to keep that sort of state information inside the Java class as private variables.

import vrml.*;
import vrml.node.*;
import vrml.field.*;

public class colour_changer extends Script
{
  private SFColor colour_out;

  private boolean red_set;

  private final static float[] RED = {1, 0, 0};
  private final static float[] BLUE = {0, 0, 1};

  /** setup all the field values */
  public void initialize()
  {
    SFBool isRed = (SFBool)getField("isRed");
    red_set = isRed.getValue();

    colour_out = (SFColor)getEventOut("colour_out");
  }

  /** Recieves the eventIns */
  public void processEvent(Event evt)
  {
    ConstSFBool is_clicked = (ConstSFBool)evt.getSource();

    if(is_clicked.getValue() == true)
      red_set = false;
    else
      isRed.setValue(true);

    /** End of event cascade event processing */
    public void eventsProcessed()
    {
      if(red_set == true)
        colour_out.setValue(RED);
      else
        colour_out.setValue(BLUE);
    }
  }
}
This all combines to create a working example


Script Execution Model

Well.... where do I start. This has changed so much, I might as well rewrite the entire section. This is a common theme across all of the books that I have written on VRML and Java as a result of the ISO process. To save myself a lot of extra writing, I've put the whole lot into a single page explaining the whole shebang.


Creating VRML on the Fly

Like the previous example, both the VRML and Java source need to have some surgery done to them. Here's the updated versions:

Listing 15.1

#VRML V2.0 utf8
#
# Demo dynamic world creation

# The first psuedo root node
DEF root_node Group {}

# The cube
Transform {
  translation 2 0 0
  children [
    DEF cube_sensor TouchSensor {}
    Shape {
      geometry Box { size 1 1 1 }
    }
    DEF box_script Script {
      url "Boxscript.class"
      directOutput TRUE
      eventIn SFBool isClicked
      eventIn MFNode newNodes
      eventOut MFNode childList
    }
  ]
}

ROUTE cube_sensor.isActive TO cube_sript.isClicked
ROUTE cube_script.childList TO root_node.addChildren

# The sphere
Transform {
  children [
    DEF sphere_sensor TouchSensor {}
    Shape {
      geometry Sphere { radius 0.5 }
    }
    DEF sphere_script Script {
      url "Spherescript.class"
      directOutput TRUE
      eventIn SFBool isClicked
      field SFNode root USE root_node
    }
  ]
}

ROUTE sphere_sensor.isActive TO sphere_script.isClicked

# The cone
Transform {
  children [
    DEF cone_sensor TouchSensor {}
    Shape {
      geometry Cone {
        bottomRadius 0.5
        height 1
      }
    }
    DEF sphere_script Script {
      url "Conescript.class"
      directOutput TRUE
      eventIn SFBool isClicked
      field MFString targetUrl "http://www.vrml.org/logo.wrl"
    }
  ]
}

ROUTE cone_sensor.isActive TO cone_script.isClicked
Listing 15.2
#VRML V2.0 utf8
#
# Sample load world
Transform {
  children Shape {
    geometry Box {}
}


[ Home ][ VRML ][ Java ][ Linux ][ Books ][ About ]