Using JVerge

After installing the class libraries and updating your CLASSPATH (if necessary) then using the JVerge classes are very simple.

The Package Structure

JVerge consists of three main packages and a few extra files. All three packages contain near identical APIs, which one you choose depends on where you are writing code for. The three packages are: There are also a number of classes that are being used as well. vlc.vrml.VrmlTypes defines the various type IDs that are used by all of the classes. Each interface package also includes a file called VrmlRoot.java which are examples on how to build a node that represents the root of the scenegraph. It also shows how you could derive the classes within JVerge to provide your own custom node.

Class Overview

The JVerge class heirarchy is based on a class called VrmlObject. All classes are derived from this. It outlines some of the basic fucntionality that is required of all nodes. Here you will find variables that indicate the type of the node, a reference to the appropriate Java Node which contains the actual node representation after the call to createVrmlFromString(). The other interesting thing to note is the static Browser reference that is there for the internal and external packages. This is so that you only need to set the browser reference once at the very start and then you can create the nodes without needing to cart around Browser references all through your application code.

There are then three main methods that are used:

The first is cleanup. Cleanup looks after the internal cleaning up, any reference counting and stuff like that. It should be called just before you remove any reference to this node when you are creating a subclass of VrmlObject. In normal day to day use of the classes there is no need for you to use this method at all. If your derived class contains MF/SFNodes then it should recursively call the cleanup methods of those nodes as well.

The second method is called writeReset. This is should be called immediately before starting to write this node to a file. Like cleanup, it is recursive and looks after any children nodes that might exist.

The final method is the abstract method writeToStream which takes two arguments. The first is a PrintStream and the second is the level of indent. For most applications this should start at zero and then let JVerge take care of the indenting internally.

For all the classes there is a default constructor supplied. This will create an instance of the node that is completely default as per the VRML 97 spec. For nodes where you want to supply non-defualt values for any field type fields then another constructor is provided for that. In the case where you have a number of different browsers there is also variants on the above two methods that include a Browser reference as the first argument. The other constructors use the static reference that is contained within the class.

Writing Code

Following is a series of example pieces of code that show how to use the JVerge packages.

Simplest approach

Simply add the import line at the top of the file and start creating nodes. For example, to create a Transform node within an applet:

import vlc.vrml.external.geometry.*;

public class myApplet extends applet
{
        Browser browser;

	public void start()
	{
		Browser = Browser.getBrowser(this);
		// etc
	}

	{
	        // in a method somewhere deep in the code....
		Transform tx = new Transform(Browser);

	        // then you need to add this to some
		// pre-existing node in the scene.
		some_SFNode_eventIn.setValue(tx.node);
	}
}
Note the use of the node reference from the Transform class when adding it into the scene.

An Alternative Constructor

Carting around Browser references is a real pain, especially in large applications. So JVerge allows you a way to circumvent this - use the static set_browser method. The previous example now becomes:

import vlc.vrml.external.geometry.*;

public class myApplet extends applet
{
        Browser browser;

	public void start()
	{
		browser = Browser.getBrowser(this);

		VrmlObject.set_browser(browser);
		// etc
	}

        // in a method somewhere deep in the code....
	{
		Transform tx = new Transform();

	        // then you need to add this to some
		// pre-existing node in the scene.
		some_SFNode_eventIn.setValue(tx.node);
	}
}
After the first call in the start method to set the browser reference there is no need to carry it anymore.

I recommend this approach is the better to use if you are going to be creating a lot of nodes. I would only use the former when I was running an applet that was talking to two or more browsers at the same time where the two Browser references will be different, depending on which one you are creating geometry for.

Combining nodes together

Once you have mastered creating a single node then combining them together is very simple. For each eventIn/eventOut/exposedField that is defined for a node in the VRML specification there is a matching method. To set the appearance value of an Appearance node there is a set_appearance method. The following example creates a red box with dimensions of x = 2, y = 3, z = 4.

import vlc.vrml.external.geometry.*;

public class myApplet extends applet
{
        Browser browser;

	public void start()
	{
		browser = Browser.getBrowser(this);

		VrmlObject.set_browser(browser);
		// etc
	}

        // in a method somewhere deep in the code....
	{
		float[] color = {1, 0, 0};

	        Shape shape = new Shape();
        	Box box = new Box(2, 3, 4);
	        Appearance app = new Appearance();
        	Material mat = new Material();

	        // set the material to red
        	mat.set_diffuseColor(color)

	        // now combine them all together
        	shape.set_geometry(box);
	        shape.set_appearance(app);
        	app.set_material(mat);

        // then you need to add this to some pre-existing node in the scene.
}

Printing Out the Scenegraph

Once you have built up a little bit of a scene you might want to generate the corresponding text. Jverge provides this capability. It is exspecially handy if you are writing a VRML editor like VermelGen.

JVerge is deliberately very lax about where it writes the data to. So long as a PrintStream is provided then that is all that is needed. Just open a stream connected to a socket or a file and off you go. The following code is taken from VermelGen that writes the output to a String.

import java.io.*;
import vlc.vrml.external.geometry.*;

public class VrmlScene
{
	private Browser		browser;
	private VrmlRoot	file_root;

	// lots of snipped code!

	public String getSceneDescription()
	{
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		PrintStream ps = new PrintStream(os);

		file_root.writeToStream(ps);

		String output = os.toString();

		try
		{
			ps.close();
			os.close();
		}
		catch(IOException e)
		{
			System.out.println("Error closing output streams");
		}

		return(output);
	}
}
Now file_root uses the following code:

import java.io.*;
import java.util.*;
import vlc.vrml.external.geometry.*;

public class VrmlRoot extends GroupingNode
{
	// lots of code snipped from here

	public void writeToStream(PrintStream fp)
	{
		Enumeration e = _children.elements();

		// firstly we need to reset the contents of the file
		for(; e.hasMoreElements();)
			((VrmlObject)(e.nextElement())).writeReset();

		fp.println("#VRML V2.0 utf8");
		fp.println("#");
		fp.println("# Generated by the VermelGen http://www.vlc.com.au/VermelGen/");
		fp.println("# GNU Software by The Virtual Light Company");
		fp.println("# Released under the GPL ftp://ftp.sunsite.edu/pub/GNU/copyinfo.txt");
		fp.println("");

		e = _children.elements();

		for(; e.hasMoreElements();)
			((VrmlObject)(e.nextElement())).writeToStream(fp, 0);
	}
}
From this you can see that you need firstly to open up a PrintStream of your choice (this could be System.out if you wanted) and then call the writeReset method so that the automatic DEF/USE system works correctly.

[ The Virtual Light Company ] [ Justin Couch ] [ Bug Report ]