figure1.gif (6319 bytes)

EAI what?

VRML-Bär meets the External Authoring Interface

figure2.gif (5035 bytes)

Don't you hate it when people throw acronyms into a conversation and you are clueless? EAI is one of the words that open the doors to your local VRML secret society. EAI stands for 'External Authoring Interface' and it is your bridge from HTML to VRML. Most of the time you are pretty happy with designing and coding VRML worlds that are self sustained, that can exist in their own window without any help from outside. But sometimes you think that you could use a slightly more conventional interface to your VRML application. This is especially true if you need keyboard input, or you want to provide the user with your own navigation controls rather than using the VRML browser's default ones.

The EAI was introduced by Chris Marrin (SGI) and at the time of this writing is still a proposal and not an official part of the VRML97 specification. However, both WorldView (www.intervista.com) and Cosmo Player (cosmosoftware.com) do support this interface and that makes it as good as a standard. With the EAI you can communicate to a VRML scene from a Java applet embedded on an HTML page ( Listing 1). The applet can be on the same page or in a frame. Of course you can do everything that an applet allows you to do like opening a socket to the host and feeding the VRML scene with network data.

For many programmers the EAI is the closest they can get to traditional 3D graphics programming using VRML. You can drive the scene entirely from a Java applet: The VRML browser delivers the geometry and the rendering, Java delivers the behavior and the logic. With this approach PROTOs and Scripts are replaced by Java classes and all routing is handled by the applet.

Some of the most complex VRML applications have been done with the EAI. Take a look at Hollyworlds (www.hollyworlds.com) which has designed some outstanding games based on VRML and the EAI.

The external classes

In the last issue you learned how to set up your VRML programming environment and you started with a simple JavaScript and Java example. This time we will take the same example and use the EAI (External Authoring Interface) to accomplish the same functionality. You will learn how to connect to the VRML browser, how to get access to a node and how to get eventIns. You will write an applet that provides the user with buttons to change the color and scale of a virtual Gummibär. The applet was tested with WorldView2.0 and Cosmo Player2.0.

If you are not yet familiar with Java applets you should probably walk through some Java tutorials first. I will not go into detail about standard applet coding since there is plenty of literature out there. The first notable difference from a regular applet is the import of VRML classes:

import vrml.external.*;

import vrml.external.field.*;

import vrml.external.exception.*;

These classes should be in your CLASSPATH, otherwise you will get an error message when you try to compile your applet. With these statements you import all the VRML classes that the browser needs to deal with VRML nodes. In Netscape3.x you could use the JSObject and plugin class to talk to the VRML browser. Since this does not work with Internet Explorer you should not import or use these classes if you want cross HTML browser compatibility.

The following table shows where the most common VRML browsers store their Java class files:

WorldView 2.0 and 2.1

C:\Program Files\WorldView for Netscape Navigator\classes

or

C:\Program Files\WorldView for Internet Explorer\classes

CosmoPlayer 2.0

C:\Program Files\Netscape\Communicator\Program\Plugins\Npcosmop.zip

Microsoft VRML 2.0 Viewer

C:\Windows\Java\Classes\Msvrml.zip

You can extract the classes and then add them to your CLASSPATH (see last issue for more information about the CLASSPATH). The Netscape classes can be found either in c:\netscape\program\java\classes\java_30.zip if you are using Netscape3.x or in c:\netscape\communicator\program\java\classes\java40.jar if you are using Netscape4.x. The source for this tutorial contains these classes for your convenience.

First get the VRML browser …

The first lines of the GBearApplet declare a couple of objects for later usage.

Browser myBrowser = null

EventInSFColor gbColor = null;

EventInSFVec3f gbScale = null;

'myBrowser' will hold a reference to the VRML browser, 'gbColor' will hold a reference to the 'set_diffuseColor' eventIn of the Bär's Material node, and 'gbScale' will hold a reference to the 'set_scale' eventIn of the Bär's main Transform.

Every Java applet has an 'init' method that is run the very first time the applet is loaded. For this example we just display six buttons right under the VRML browser (Figure 1). After a GridLayout with 2 rows and 3 columns is set, background color, foreground color, and the font are set. Then the six buttons are added to the layout manager ( Listing 2).

After the init method has finished, the start method is called. This method runs each time the applet is reloaded, e.g. if you come back to the applet later during the same browser session. The first thing you notice is a for() loop. We have to try to get a reference to the VRML browser and since the applet might load before the VRML browser. Getting a reference to the VRML browser may fail and our applet may have to wait for awhile and then try again to get the browser reference. Here we just wait half a second and let it loop twenty times. If this fails then there is probably something wrong. At this point you could inform the user about the problem and abort further actions ( Listing 3).

The getBrowser(this) method returns an instance of the Browser class. Once it returns anything else than null, the loop is broken and the applet can continue to get nodes from the browser. If you have the VRML browser and the applet in different frames you have to use the getBrowser(this, "vrml frame name", 0) method. 'this' refers to the applet, 'vrml frame name' is the name of the frame the VRML browser resides in, and '0' is the position of the VRML browser with regard to other embedded HTML objects. If the VRML browser is the only object in the frame its id is '0' which stands for the first position.

… and then the nodes and eventIns

In order to change the color of the Bär we first need to get the Material node. In the VRML file we gave the material a name:

DEF gummibearMaterial Material {...}

We can use this definition of the Material node to get to it with a myBrowser.getNode() call ( Listing 4):

Node gbMaterial = myBrowser.getNode("gummibearMaterial");

The getNode() method returns an object of type Node which is called 'gbMaterial'. Now that we have the Node we can get to its eventIns. The material node 'gbMaterial' is asked for its eventIn 'set_diffuseColor':

... gbMaterial.getEventIn("set_diffuseColor");

A brief look at the Material node in the VRML97 specification reveals all its exposedFields (short cuts for a field, an eventIn, and an eventOut). In this case we want to change the diffuseColor so we use the corresponding eventIn 'set_diffuseColor'. At this point all we have is a handle to an eventIn. Next we cast this eventIn into an EventInSFColor field and assign it to the EventInSFColor object 'gbColor':

gbColor = (EventInSFColor) gbMaterial...

Another quick look at the EAI reference tells you that the getEventIn method can throw an exception. We take care of it with a try{} - catch{} statement:

try { the getEventIn call lives here } catch (InvalidEventInException iee) { ... }

A similar procedure has to be undergone with the 'set_scale' eventIn. Scale is a field of the Transform node and is of type SFVec3f. As with the Material node we first get the Transform node of the to be scaled object:

Node gbMaterial = myBrowser.getNode("gummibearTransform");

The corresponding eventIn for the exposedField scale is 'set_scale'. We get it by calling getEventIn("set_scale").

try {

gbScale = (EventInSFVec3f) gbTransform.getEventIn("set_scale");

} catch (InvalidEventInException iee) { ... }

Now there are two eventIns at our disposal: 'gbColor' and 'gbScale'. Both can be used by other applet methods during program execution.

The stop method is called whenever you leave the applet. To ensure that we will get a valid instance of the browser and the eventIns the next time we load the applet, we set these objects to null before we leave. ( Listing 5)

Where is the action?

The action method is run whenever the applet experiences some kind of user input like clicking or dragging. The action method takes a parameter of type java.awt.Event; however, there is also a class vrml.Event in the JSAI which can confuse the Java compiler. This is why the fully-qualified class name java.awt.Event is used. If the source of the action is a button you first get the label of the very same:

String buttonName = (String) arg;

Then a set of if{}-else if{} statements is applied since we have six buttons with six different actions. Let's have a closer look at the red Gummibär and walk through each line ( Listing 6).

During initialization the applet could (hopefully) get a reference to the 'set_diffuseColor' and the 'set_scale' eventIns. Before you can assign a new color you first need to create one. A third quick look at the EAI reference shows you that the class EventInSFColor has a method setValue(float[]). This method takes a float array of the new color values and applies it to the eventIn. The new color array is declared at the beginning of the applet:

float bearColor[] = new float[3];

In the red button action this array is set up for a fully saturated red:

bearColor[0] = 1; bearColor[1] = 0; bearColor[2] = 0;

VRML uses the red-green-blue color space. The first array element takes the amount of red, here we assign a 1 which is the highest value. We don't want any green or blue components so you just set them to zero. Embedded into a try{} catch{} statement you can finally set the color value:

try { gbColor.setValue(bearColor);

} catch (IllegalArgumentException iae) { ... }

For the scale buttons we declared a

float bearScale[] = new float[3];

statement at the beginning of the applet. The scale action sets an eventIn of type SFVec3f with a float array of three elements. The first element (0) takes the x value, the second (1) the y value, and the third (2) the z value. If you want to scale an object only in its x direction you will only change the x value and leave y and z at their default of 1:

bearScale[0] = 0.5f; bearScale[1] = 1f; bearScale[2] = 1f;

A scale value of 0.5 will scale the object to half of its original size. Finally you can set the new scale value and squeeze the Bär in its x direction (horizontal).

try {

gbScale.setValue(bearScale);

} catch (IllegalArgumentException iae) { ... }

Conclusion

In this lesson you learned how to get to nodes in your VRML scene and how to manipulate them by setting their eventIns. With the EAI you can take advantage of Java features like keyboard input and manipulate your VRML world directly from a powerful programming language. You could move the user's viewpoint back and forth when the up and down arrow keys are pressed. Or you could let the user type his/her name into a text box and greet him/her with a personalized VRML message.

The Java EAI might be intimidating at first but it is definitely an important enhancement to VRML. You can take a look at SGI's site (vrml.sgi.com) for more examples and detailed information about the EAI.

 

Markus Roskothen is a multimedia consultant with infoplasm. He specializes in the design of interactive information spaces and can be reached at markus@vruniverse.com. The Bär was modeled by Michael Siebielec. Special thanks to Gary Grossman (garyg@intervista.com) for the sanity check.

URLs:

Tutorial source:

http://www.vruniverse.com/vrdj/article2/tutorial2.html

EAI Information:

http://http://cosmosoftware.com

EAI faq:

http://EAI faq


Copyright © 1996-98 Markus Roskothen. All rights reserved.