VRML Scripting Using Java


Written by: Hermes Roferos

Dynamic behavior can be incorporated into a VRML world by providing scripts in the VRML source code. Using scripts, the VRML world can provide higher levels of interaction with the user and with the outside world. A user, for example, can click on an object in the VRML scene and have the script take him to a different web site or to change the scene in some manner.

Scripts can take the form of JavaScript or ECMAScript, (either in a file or in-lined into the VRML code), or with Java .class byte-code. Here we will discuss how Java byte code is interfaced with the VRML world. This discussion will take the form of studying a piece of code on a VRML world and the corresponding Java code that is used to provide some behavior in the VRML world. Information on JavaScript and ECMAScript usage can be found on the web3d.org web page at http://www.web3d.org/vrml/vrml.htm.

The VRML Side. Let us take a look at what goes into the VRML code first. The following code snippet defines a script node called Populator which will populate the VRML world with nodes as defined by code in the Java SearchResultsWorld.class file. The rest of the VRML code, which generates the virtual world, is not shown here.

DEF Populator Script {
url "SearchResultsWorld.class"
directOutput TRUE
field SFString queryText "VRML"
eventIn SFTime getNextResult
eventOut MFNode newNode
eventOut SFBool isRunning
}
DEF Clock TimeSensor {
cycleInterval 2.0
loop TRUE
}
 
ROUTE Populator.newNode TO SearchResultsGroup.addChildren
ROUTE Clock.cycleTime TO Populator.getNextResult
ROUTE Populator.isRunning TO Clock.set_enabled

The url field defines the name of the file containing the script. A string field, called queryText, and event fields (getNextResult, newNode, isRunning) are defined. These are just variables and events that can be read/written by both the VRML code and the Java code. A timeSensor node, named Clock, is then defined. The last three lines connect the VRML nodes with the script variables that will control them. Here the script's newNode event is routed to an addChildren event for the SearchResultsGroup node (not shown), the clock's cycleTime event is routed to the script's getNextResult event, and the script's isRunning event is routed to the clock's set_enabled event.

* * *

The Java Side. A section of the corresponding Java code to communicate with the preceding VRML code is as follows (again, only the relevant code is shown). The Java Class documentation is also available.:

import vrml.*;
import vrml.field.*;
import vrml.node.*;
 
public class SearchResultsWorld extends Script {
private SFString queryText;
private MFNode newNode;
private Browser clientBrowser;
private SFTime getNextResult;
private SFBool isRunning;
queryText = (SFString)getField( "queryText");
newNode = (MFNode)getEventOut( "newNode" );
getNextResult = (SFTime)getEventIn( "getNextResult");
isRunning = (SFBool)getEventOut( "isRunning");
clientBrowser = this.getBrowser();
public void processEvent( Event e ) {
if ( e.getName().equals( "getNextResult" ) ) {
 
...// do user-defined processing
 
vrmlString.append(
"EXTERNPROTO SearchResultNode [" +
" field MFString title" +
" field SFTime age" +
" field SFColor hostIP" +
" field SFColor domainName" +
] \"SearchResultNode.wrl\"" );
 
newNode.setValue( clientBrowser.createVrmlFromString( vrmlString.toString() ) ); }

The java code imports the VRML namespace and creates a class that extends the VRML Script class. Variables are created and set up to point to the variables that were defined in the VRML code (for example, newNode = (MFNode)getEventOut("newNode")makes a connection between the Java code's newNode variable and the VRML eventOut named "newNode"). Inside the class' processEvent method, when the event associated with "getNextResult" (which was tied to the clock's cycleTime event, see the VRML code above) is received, a string consisting of VRML code that describes a graphical node object is created. Using the createVrmlFromString( )method, that string is used to create a graphical node in the VRML world through the world's newNode event.

To summarize the process, everytime a clock cycleTime event is generated by the VRML world, the java code receives the event and generates a VRML object which is routed to a node in the VRML world.

* * *

Issues Encountered. While developing the Java/VRML code for this project, some anomalies were discovered. There seems to be differences in how browsers handle VRML worlds. The code was tested on both Internet Explorer 4 and Netscape 4.5 with both running the Cosmo VRML player. The .class and .wrl files were stored on a PC running Microsoft PWS and were viewed over an intranet on a different PC. With this configuration, Netscape was able to display the VRML ld and run the Java code. Netscape, however, could not correctly execute java code which instantiated an InetAddress object. On the other hand, IE4 could not display the VRML world at all. The VRML code would get loaded but IE4 could not load (or find) the appropriate Java .class file for the script node. IE seems to treat our .class files differently from ones hat are normal applets (our java class extended Script and not the applet class). The only configuration that would make IE load the VRML world correctly was if the .class files were pre-copied to the /windows/java/classes directory. Even then, this only worked when the VRML world was loaded from the local drive and not over the intranet.


Created by: Hermes Roferos (hroferos@shrike.depaul.edu)