HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

Java and VRML technologies change very quickly so by the time you read this article, the information in it may be outdated. However, that shouldn't deter you from learning about the synergies of Java and VRML because frankly, it is one of the most exciting areas of software development today. This article will explain the basics of VRML, what the VRML landscape looks like from a developer's perspective and give you an introduction to how Java and VRML can work together. Together, Java and VRML hold much promise for the future of the Web.

Everyone has high hopes that the combination of these technologies will make the Web a truly interactive medium. We are at the beginning of a new era in the development of the Web; Java and VRML are critical to that success. It is important to remember that these technologies are just out of beta, and as such, are only the first steps towards "a second Web." Applied Visions' development efforts in this field have put it in the vanguard of Java and VRML development and it is on this company's efforts that everything in this article is based.

For the purposes of this article, we assume that you're a programmer who is familiar with Java. In addition, we also assume that you have seen a VRML scene (either in a browser or in a movie) and realize that HTML and VRML are file formats and Java is a compiled object-oriented language.

What is VRML?
VRML stands for Virtual Reality Modeling Language. It is usually denoted with the *.wrl or *.wrl.gz extension (if it is compressed). VRML in many basic ways is like HTML. Both are ASCII-based and can be read by a browser. You can open and edit .wrl files in any text editor. They will be read by your browser's plug-in and displayed as a 3D scene (consisting of VRML objects).

In many ways, however, VRML is not like HTML, but more like HTML and JavaScript combined. You can define the behaviors of the scene within VRML much the same way it is possible to script HTML using JavaScript. In addition to creating, displaying and manipulating three-dimensional objects (VRML 1.0), VRML 2.0 allows for the behaviors of those objects to be programmed, specifically with respect to animation and interaction with the VRML world. Some of the concepts that were added to VRML in VRML 2.0 include the ability to perform various types of sensing, the ability to script animation and the ability to determine time (without reference to the system clock). Both Netscape and Microsoft support the VRML 2.0 standard, either through their own or third party plug-ins. VRML seems to be on a firmer footing than HTML was at the same time in its growth.

The primary reason that this firmer footing exists is that the VRML Working Group planned for the extensibility of VRML within the VRML 2.0 "Moving Worlds" specification (http://www.vrml.org). The VRML 2.0 spec allows the programmer to create and determine the programmability of the atomic units that make up a VRML file. It not only is possible to program the behaviors of three-dimensional shapes, it is also possible to create entirely new relationships to three-dimensional objects while conforming to the VRML 2.0 specification. These relationships must be defined in the atomic units that make up a VRML file, which are known as nodes.

Nodes are the fundamental units of a VRML scene. In VRML, there are about 50+ standard nodes which perform certain roles within the VRML world. For example, there is a node called "Sphere" which creates a sphere. Every aspect of a given node need not be specified many nodes have default values. For example, this file consists of four nodes which create a VRML 2.0 world with a sphere at its center:

#VRML V2.0 utf8
Shape
{
appearance Appearance {
material Material { }
}
geometry Sphere { }
}

"appearance" is the field name. Each node has qualities that can be manipulated, called fields (there are no fields shown in the example above). "Appearance" is the name of the node associated with that field. The Shape node is the primary node in this scene. Appearance, Material and Sphere are all nodes that describe some feature of the node hierarchically above it, Sphere. The appearance field specifies the way a Shape node will look. The material field specifies the material that can make up the appearance (for example, you could use a JPEG image to specify the material field). In the sample applet/scene later in this article, we will modify certain fields within the Transform Node. Much of the power of VRML 2.0 comes from the dynamic manipulation of fields within nodes.

This is the most basic example of a VRML file. Rather than explaining the role of every node in VRML, we're only going to describe the nodes necessary to gain a basic understanding of VRML's relationship with Java. VRML has much functionality that can be exploited outside of this example and you are actively encouraged not to view the sample application as anything other than a basic beginning.

What Can VRML Do Well?
VRML's primary strength is its capacity to render detailed graphics over the Web using limited bandwidth. The VRML viewer and HTML browser do the heavy computation of translating a VRML file to a full-fledged world. These worlds consist of three-dimensional objects that may be used in many combinations. The objects, and the worlds that they inhabit, can have textures mapped onto them, allowing developers to specify a starry sky or a checkered floor for their VRML world. The hope is that VRML will become even less bandwidth-intensive.

The VRML Major Players
Before we go any further, we should go over who the major players are in the VRML arena. This will help you understand where VRML came from and where it may be heading.

You may view a VRML file using a variety of plug-ins available on the market.

  • WorldView (IE)
  • SGI/CosmoPlayer (Netscape)
  • Sony/Community Place
Sony has done a significant amount of work with VRML but it is more likely that you will target either Internet Explorer or Netscape with your Java applet/VRML world. Sony has a Web site devoted to its Community Place VRML effort at http://vs.spiw.com/vs/

One further note: Aside from the nature of plug-ins, there are several other inconsistencies over platforms the quality of Java Virtual Machines as well as the feature sets of each browser. There are many variables at work here. All of the work for this article was done in Netscape Communicator 4 with the SGI Cosmo Player 1.0 Plug-in on Windows95/NT4.0. Do not install NT4.0 service pack 3 or the sample applet/scene will not work. The current reality of VRML/Java development is that you now must develop not only for a particular platform, but a particular browser and plug-in combination as well. This is counter to the promise of the "write-once, run-anywhere" promise of Java, but it has just as much to do with the young nature of VRML 2.0 as the uneven quality of VMs across platforms.

Intervista is run by Tony Parisi, one of the creators of the initial VRML specification. Intervista markets its own plug-in for Windows95/NT and Macintosh, WorldView, for Netscape and Internet Explorer. It is a very good implementation of the VRML 2.0 spec and renders graphics exceedingly fast, relying on Microsoft's DirectX technology to do this. Microsoft licenses a significant amount of VRML technology from Intervista, which may explain why Microsoft's VRML plug-in looks very much like Intervista's.

DimensionX was among the first to license Java from Sun Microsystems. They have two products - Liquid Motion Pro and Liquid Reality. Liquid Motion Pro is an impressive Java-based multimedia tool. Liquid Reality is a Java-based implementation of a VRML browser and the Java development environment for VRML. Dimension X was up to their 18th beta version of Liquid Reality when they were bought by Microsoft. You can now get Liquid Reality with some editions of Visual J++. As a Java solution, LR was edging towards platform independence, although the latest versions are requiring Microsoft's DirectX API. It is an approach that seems especially ambitious, but after 18 betas, one fears that a solution is not within reach.

Silicon Graphics Open Inventor ASCII File Format is the file format on which the VRML 2.0 specification is based. They have a very good implementation of a VRML plug-in, Cosmo Player. Cosmo Player has just been formally released as a product and is free with Netscape Communicator 4.0. VRML on a Silicon Graphics 02 , you can imagine, is as close to real-time VRML as you're going to (currently) get. It's fast and smooth, and probably a bit expensive for the average developer. vrml.sgi.com continues to be a mainstay of the VRML community, where you can find the latest advances in VRML and implementations of experimental technologies. It is also the site where SGI actively promotes VRML. SGI has a suite of tools which is among the best available and you can read about them there.

How VRML Works with Java - Two Approaches

Figure 1

As we've mentioned before, VRML is inherently programmable and extensible. The current languages to use with VRML are VRMLScript, JavaScript and Java. When programming in Java, it is possible to access the class file from within the scene itself or from outside the scene. The first method, included in the VRML 2.0 specification, is colloquially known as the "Java Scripting Interface" (JSI). The second method, which is a proposed "Annex" to the VRML 2.0 is known as the External Authoring Interface.

VRMLScript is supported by a Script Node in VRML. VRMLscript is a subset of JavaScript which focuses, appropriately enough, on the activities which are most commonly done in VRML; for example, animation. If you want a bird in a VRML scene to change into an eagle when you touch it, this may be done entirely within VRML using the Script node.

It is also possible to use JavaScript to script events. This is helpful when you need the special features of a particular language. JavaScript is supported by both major VRML browsers and is a relatively safe bet for that reason. However, if your VRML browser supports Perl there is no reason theoretically why you couldn't use it, according to the VRML 2.0 specification. At this point, however, VRMLscript, JavaScript and Java are the only languages supported by the majority of VRML plug-ins. A Script node is constructed such that if a plug-in does not support a language, it can default to another laguage (and a third) if necessary. For example, Intervista's plug-in supports VBScript and it can be configured to default to JavaScript.

In VRML, you can change the fields in a node and monitor the change of values in a node if those fields you wish to monitor or change are exposed fields. If they are exposed, it means that they have a "get" and a "set" value, much like many other classes in Java. In order to set a value, you must specify the appropriate "set" method in either the EventIn or EventOut object. This will be thoroughly explained in the example. (In VRML, the actual syntax is "set_fieldname" and "fieldname_changed", respectively, for exposed fields).

Using Java in a Script Node
In order to use Java in VRML Script node, the VRML Script node must basically look like this:

Script
{
url["DoSomeThingCool.class"]
}

The Script Node contacts a class file by means of a URL. This example doesn't do anything, but it gives the overall idea. The Java class must import the following packages:

vrml.*
vrml.field.*
vrml.node.*

The API of these packages has been specified in the VRML 2.0 specification. It's certainly too big to get into here. The final spec for the API can be found at http://www.vrml.org/Specifications/vrml2.0/FINAL/spec/part1/java.html.

The Java Classes included with the VRML plug-ins must follow this API specification. There may be better documentation out on the market in the future, but this is all that currently exists.

These packages let you control and respond to changes in fields in individual nodes, as well as interact with the browser in critical ways. The Java package defines both a read-only (Const) class and a read/write class for each VRML field type; both kinds of classes define a getValue() method and the read/write classes define a setValue() method as well. Also, classes, depending on their function, provide "get" and "set" methods. For example, MFInt32 provides an addValue() method to add an SFInt32 value to a list. Classes have methods which handle Exceptions (from which you can descend).

To reference a field in a Script node, you must declare each field of the Script Node (using getField()) and each outgoing event (using getEventOut()) in the initialize() method.

When a Script receives a set of incoming events, it passes them to a Java method named processEvents(). processEvents()'s default behavior is to pass each event individually to your defined event handler, which much be called processEvent(). The processEvent() method receives a single object of the class Event.

A word of advice: if you need static data available from one use of a script to the next, don't count on the browser "knowing" the static values that were set the last time you referenced that class file unless you assign those static values to fields in that VRML node.

The External Authoring Interface
The External Authoring Interface was created because developers will need to communicate with a VRML scene from outside of that scene. Doing this has many advantages: the VRML scene is no longer at the center of the architecture, but is more of a resource upon which the primary program can act and to which it can respond. We have used the EAI extensively in our work. The EAI is not formally part of VRML, but a proposal for an "Informative Annex." vrml.sgi.com/moving-worlds/sec/ExternalInterface.html. To quote Chris Regan from the EAI FAQ (www.tomco.net/~raf/faqs/eaifaq.html):

"The choice between them is largely down to the taste of the programmer though many follow a fish bowl metaphor, using the script node for behaviours purely within the world and the external interface for behaviours linking outside. Within a WWW browser the EAI provides simple access from an applet on the same page as the VRML browser, currently using Live Connect."

The EAI is now fully implemented in Cosmo Player 1.0 and in Intervista's WorldView plug in.

The EAI is a large topic within itself to cover. We advise anyone interested in it to see the EAI proposal at vrml.sgi.com. In our example, we access the VRML scene through the EAI and change a few fields within the VRML file through a Java Applet. Again, this is a narrow example of the power of the External Authoring Interface. If you check out the specification, it quickly will become apparent that you can do a lot more than this.

The Anatomy of an Example
Note: The entire source code for this example is located at www.avi.com/jdj. There is not enough space to include the entire source code for this example here. Instead, we will discuss the basic parts of the applet's construction.

Let's first look at the VRML file, shown in Listing 1. This entire VRML scene consists of seven nodes. In order for Java to be able to manipulate VRML using the EAI, the easiest approach is to define the node using the keyword DEF. Main is a Transform node, which is a type of a grouping node: if you expect that a node and the nodes beneath it will have to be positionally manipulated according to the same behavior, you will want to group them within the same Transform node. A Transform node defines "a coordinate system for its children that is relative to the coordinate systems of its parents." ("The VRML 2.0 Handbook", Jed Hartman & Josie Wernecke, silicon Graphics, Inc. Addison Wesley, 1996) Also, note that we have defined the TouchSensor node in this example to be TOUCH. We will change the scale of the cube and the position of the cube in this example by allowing the Java Applet to change the values of the scale and rotation fields in the "Main" Transform node. Now take a break. It only gets more complex from here.

In order to create an applet which has access to these nodes, you must import the following packages:

import vrml.external.Node;import vrml.external.Browser;import vrml.external.exception.*;

Note that these are not the standard vrml.* packages, but EAI packages. These classes are included with both Netscape Communicator/Cosmo Player 1.0 and Intervista.

The following package is necessary because our example uses Netscape. You should set your classpath so that it can access the java40.jar file.

import netscape.javascript.JSObject;

EventIns and EventOuts in VRML are objects which handle specific events for a particular node. If a node generates a particular action, an EventOut is used. If you wish to effect a particular node, you must manipulate its EventIn object.

The following package handles the means of getting a handle to an EventOut.

import vrml.external.field.EventOut;

The following packages control the EventIn and EventOut states of the Rotation fields, the Time fields, the objects which define 3D Vectors (SFVec3f). The classes which control 3D vectors can be used to interact with many nodes which are defined in terms of a 3D vector. We use it here to change the scale of our cube.

import vrml.external.field.EventOutSFRotation;
import vrml.external.field.EventInSFRotation;
import vrml.external.field.EventInSFVec3f;
import vrml.external.field.EventOutSFVec3f;
import vrml.external.field.EventOutSFTime;

To receive notification when an eventOut is generated from the scene, the applet must first subclass the EventOutObserver class, implementing the callback() method. Next, the advise() method of EventOut is passed the EventOutObserver. Whenever an event is generated for that eventOut, the callback() method is executed and passed the value and timestamp of the event. The advise() method is also passed a user-defined object. This value is passed to the callback() method and can be used by the applet to pass user-defined data to the callback. It allows a single EventOutObserver subclass to handle events from multiple sources and is a subclass of the standard Object class so it can be used to hold any data.

import vrml.external.field.EventOutObserver;

The Setup
In addition to the packages outlined above, you'll want to import java.applet.* and java.awt.*. In Listing 2, we instantiate our objects for their first use. The EventOutObserver interface is implemented in order to set the stage to ensure that it follows the correct protocol in order to communicate with the browser.

The init Method
A Java applet communicates with a VRML world by first obtaining an instance of the Browser class. This class is the Java encapsulation of the VRML world. It contains the entire Browser Script Interface as well as the getNode() method, which returns a Node when given a DEF name string (now is it apparent why we defined the nodes in the VRML file?). Only DEF names in the base file are accessible. Since VRML files can have multiple occurrences of the same DEF name, only the node with the last occurrence of a given name is accessible.

Once a Node instance is obtained from the getNode() method of the Browser class, its EventIns and EventOuts can be accessed.

Next, the advise() method of EventOut is passed the EventOutObserver. Then, whenever an event is generated for that eventOut, the callback() method is executed and passed the value and timestamp of the event. When this happens, you can see the value appear in the TextArea at the bottom of the Applet. The advise() method is also passed a user-defined object. This value is passed to the callback() method and can be used by the applet to pass user defined data to the callback (see Listing 3).

The applet's interface is created (Simple AWT stuff) in Listing 4.

The netscape.javascript.JSObject allows Java to manipulate objects that are defined in JavaScript. The JSObject.getWindow returns the window in which the plugin (in this case, Cosmo Player) is embedded. getMember() retrieves a named member of a JavaScript object. embeds.getSlot() retrieves the member indexed at [0] of the JSObject, which is, in this case, our VRML scene.

JSObject win = JSObject.getWindow(this);
JSObject doc = (JSObject) win.getMember("document");
JSObject embeds = (JSObject) doc.getMember("embeds");
browser = (Browser) embeds.getSlot(0);

Get the node in the VRML scene you wish to engage. Create an object of the type that will create the interactivity you wish; for example, we use rotation so we create an object of EventInSFRotation. We set the field in the Main node by using Main.getEventIn("set_rotation"). Also, note that in order to demonstrate to the viewer that an event is taking place, we're accessing the TOUCH node and getting the time that an event took place (see Listing 5).

The Callback
The callback gets the time at which the sensor node was tripped. It is displayed in the TextArea (see Listing 6).

The handleEvent() method
The most significant thing to note in this method is that ScaleIn is an object of type EventInSFVec3f, consisting of three values (an array of three floats). These values are set and the scale changes when this call is made (see Listing 7).

Once the possibility exists that you can program a VRML world from outside that world, it presents an entirely new way of looking at VRML. It offers programmers a bit more flexibility in some areas and, depending upon their application, it may be an option that you want to use. The EAI hopefully will become part of the VRML 2.0 specification.

Java and VRML together offer the promise of functionality on the Web that is truly interactive and a magnitude more useable than the current Web. The technology that bridges VRML and Java is still quite erratic, but with the advances in Java technology, and the general agreement among all parties on the VRML 2.0 specification, it is possible that in a few years VRML, not HTML, may be the mainstay of the Web. Much work remains to be done, but we can remain hopeful that with the current investments many corporations are making in bandwidth technologies, a VRML-based Web - enhanced by Java - isn't that far away.

Other Sites to Check
www.intervista.com - Intervista's site
www.microsoft.com/dimensionx - DimensionX's site
cosmo.sgi.com - Cosmos creates VRML worlds and development environments
www.microsoft.com/vrmlwww.microsoft.com/vrml - Microsoft's VRML effort

About the Authors
Mark Larkin, Tim Vercruysse and Jon Steiner all work at Applied Visions with Java and VRML. Applied Visions was recently awarded an SBIR grant from the Air Force to implement Network Visualization Security strategies using VRML and Java. This article is based on Mark's and Tim's work. If you have any questions, please contact us at [email protected]

	

Listing 1. 

#VRML V2.0 utf8 
DEF Main Transform { 

      translation 0 0 0  
      rotation 5 3 2 1  
      scale 1 1 1 
       
      children [       
       
            Shape {          
               appearance Appearance { 
                  texture ImageTexture { 
                     url "avi.jpg" 
                     repeatS FALSE 
                     repeatT TRUE 
                                 } 
               material Material {    
                     diffuseColor 0.8 0.2 0.2 
                     shininess .99    
                                } 
                                } 
               geometry Box { 
                          size 2 2 2 
                            } 
            }, 
      DEF TOUCH TouchSensor {      } 
      ] 
      } 

Listing 2. 

 public class AVIAplt extends Applet implements EventOutObserver { 
  TextArea output = null; 
  Browser browser = null; 
           
  Node Main = null; 
  EventInSFRotation BoxRotation = null; 
  EventOutSFRotation outputRotation = null; 
  EventInSFVec3f ScaleIn = null; 
  EventOutSFVec3f ScaleOut = null; 
  EventOutSFTime touchTime = null; 
  boolean error = false; 
  java.awt.Scrollbar horizontalScrollbar1; 
  java.awt.CheckboxGroup checkboxGroup1; 
  java.awt.Label label1; 
  java.awt.Label label2; 
  

Listing 3. 

      // Get the Touch Sensor 
      Node sensor = browser.getNode("TOUCH"); 
      // Get its touchTime EventOut 
      touchTime = (EventOutSFTime) sensor.getEventOut("touchTime"); 
      // Set up the callback 
      touchTime.advise(this, new Integer(1)); 
      // Get its BoxRotation EventOut 
outputRotation = (EventOutSFRotation) Main.getEventOut("rotation"); 
      // Set up its callback 
      outputRotation.advise(this, new Integer(2)); 
    } 

  
public void init() { 

Listing 4. 

setLayout(new GridLayout(7,1)); 
addNotify(); 
     
//The Scrollbar 
horizontalScrollbar1 = new     
java.awt.Scrollbar(Scrollbar.HORIZONTAL,5,1,1,10); 
label1 = new java.awt.Label("Rotation Angle",Label.CENTER); 
label1.setFont(new Font("TimesRoman", Font.BOLD,14));  
add(label1); 
add(horizontalScrollbar1); 

//The CheckBoxes 
label2 = new java.awt.Label("This changes the Scale",Label.CENTER); 
label2.setFont(new Font("TimesRoman", Font.BOLD,14)); 
add(label2); 
checkboxGroup1 = new java.awt.CheckboxGroup(); 
add(new Checkbox("Big", checkboxGroup1, false)); 
add(new Checkbox("Medium", checkboxGroup1, true)); 
add(new Checkbox("Small", checkboxGroup1, false)); 

output = new TextArea(5, 40); 
add(output); 

Listing 5. 

// Now we've got the handle to the VRML Browser. 
try { 
  // Get the Main node... 
  Main = browser.getNode("Main"); 
  // Get the BoxRotation EventIn 
  BoxRotation = (EventInSFRotation) Main.getEventIn("set_rotation"); 
  // Get the Touch Sensor 
  Node sensor = browser.getNode("TOUCH"); 
  // Get its touchTime EventOut 
  touchTime = (EventOutSFTime) sensor.getEventOut("touchTime"); 
  // Set up the callback 
  touchTime.advise(this, new Integer(1)); 
  // Get its BoxRotation EventOut 
  outputRotation = (EventOutSFRotation) Main.getEventOut("rotation"); 
  // Set up its callback 
  outputRotation.advise(this, new Integer(2)); 
} 
catch (InvalidNodeException ne) { 
  add(new TextField("Failed to get node:" + ne)); 
  error = true; 
} 
catch (InvalidEventInException ee) { 
  add(new TextField("Failed to get EventIn:" + ee)); 
  error = true; 
} 
catch (InvalidEventOutException ee) { 
  add(new TextField("Failed to get EventOut:" + ee)); 
  error = true; 
}
 
Listing 6. 

public void callback(EventOut who, double when, Object which) { 
    Integer whichNum = (Integer) which; 
    if (whichNum.intValue() == 1) { 
      // Make the timestamp and new time show up in the textarea. 
      double val = touchTime.getValue(); 
      output.appendText("Got time " + val + " at time " + when + "\n"); 
    } 
    if (whichNum.intValue() == 2) { 
      // Make the new rotation of the box and timestamp 
      // show up in the textarea. 
      float[] val = outputRotation.getValue(); 
      output.appendText("Got rotation value " + val[0] + ", " + val[1] 
         + ", " + val[2] + "," +  val[3] + " at time " + when + "\n"); 
    } 

Listing 7. 

public boolean handleEvent(Event event) 
{ 
    if (error) 
      { 
   showStatus("Problems! Had an error during initialization"); 
   return true;  // Uh oh... 
      } 
    if (event.target instanceof Checkbox) 
   { 
         Checkbox b = (Checkbox) event.target; 
         if (b.getLabel() == "Small" && b.getState() == true) 
         {   
            showStatus("Small!"); 
            float[] val = new float[3]; 
            val[0] = .5f; 
            val[1] = .5f; 
            val[2] = .5f; 
            ScaleIn.setValue(val); 
            return true; 
         } 
         if (b.getLabel() == "Big" && b.getState() == true) 
         {   
            showStatus("Big!"); 
            float[] val = new float[3]; 
            val[0] = 3; 
            val[1] = 3; 
            val[2] = 3; 
            ScaleIn.setValue(val); 
            return true;           
         } 
         if (b.getLabel() == "Medium" && b.getState() == true) 
         {   
            showStatus("Medium!"); 
            float[] val = new float[3]; 
            val[0] = 1; 
            val[1] = 1; 
            val[2] = 1; 
            ScaleIn.setValue(val); 
            return true; 
         } 
       } 



 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.