VRML97 logo

Annex B
(normative)

Java language binding

 

--- VRML separator bar ---

B.1 Table of contents and introduction

B.1.1 Introduction

This annex provides a detailed description of the Java language binding to the services defined in this standard. Note that support for the Java platform is not required by this standard but any access of the Java platform as an external application to a VRML browser  shall conform with the requirements specified in this annex.

The Javatm platform is an object-oriented, hardware and operating system independent, multi-threaded, general-purpose application environment developed by Sun Microsystems, Inc. The Java platform consists of the language, the virtual machine, and a set of core class libraries. A conforming Java platform implements all three components according to their specifications. See 2.[JAVA] for a description of the language, the virtual machine, and the three core classes java.lang, java.util, and java.io. The other core class libraries, which are not used in this annex, are described in ISO/IEC 14772-1 E.[JAPI].

For historical reasons, the Java language binding to the EAI does not implement the full set of capabilities defined in the main specification. It implements the minimum requirements (see 7.3 Minimum Support Requirements). Restrictions imposed by this implementation on the services specification are noted individually in B.5 Services Binding.

B.1.2 Table of contents

See Table B.1 for the contents of this annex.

Table B.1 — Table of contents

B.1 Table of contents and introduction 
 B.1.1 Introduction 
 B.1.2 Table of contents 
 B.1.3 Conventions 

B.2 Concepts 
 B.2.1 The browser script interface 
 B.2.2 Relationship to ISO/IEC 14772-1, Annex B Java platform scripting interface 
 B.2.3 Scope of specification 
 B.2.4 Conformance 
 B.2.5 Types of Java browsers 
 B.2.6 Implementation dependencies 

B.3 Data type implementation 
 B.3.1 Data type Definitions 
  B.3.1.1 EAIAction 
  B.3.1.2 EAIBrowserApp 
  B.3.1.3 EAIBrowserName 
  B.3.1.4 EAIBrowserRef  
  B.3.1.5 EAIBrowserVersion 
  B.3.1.6 EAIFieldAccess  
  B.3.1.7 EAIFieldID  
  B.3.1.8 EAIFieldName  
  B.3.1.9 EAIFieldType  
  B.3.1.10 EAIFieldValue  
  B.3.1.11 EAIFrameRate 
  B.3.1.12 EAINavSpeed 
  B.3.1.13 EAINodeID  
  B.3.1.14 EAINodeType  
  B.3.1.15 EAIParameterList 
  B.3.1.16 EAIPropertyList 
  B.3.1.17 EAIRequestorID 
  B.3.1.18 EAIURL 
  B.3.1.19 EAIString 
 B.3.2 Error data types 
  B.3.2.1 EAIError 
  B.3.2.2 EAI_BROWSER_UNAVAILABLE 
  B.3.2.3 EAI_CONNECTION_ERROR 
  B.3.2.4 EAI_DISPOSED 
  B.3.2.5 EAI_INVALID_ACCESS_TYPE 
  B.3.2.6 EAI_INVALID_BROWSER 
  B.3.2.7 EAI_INVALID_NAME 
  B.3.2.8 EAI_INVALID_NODE 
  B.3.2.9 EAI_INVALID_FIELD 
  B.3.2.10 EAI_INVALID_URL 
  B.3.2.11 EAI_INVALID_VRML 
  B.3.2.12 EAI_URL_UNAVAILABLE 
 B.3.3 Event Types 
  B.3.3.1 Concepts 
  B.3.3.2 EAIBrowserEvent 
  B.3.3.3 EAI_B_Initialized 
  B.3.3.4 EAI_B_Shutdown 
  B.3.3.5 EAI_B_ConnectionError 
  B.3.3.6 EAI_B_URLError 
  B.3.3.7 EAIFieldEvent 

B.4 Language specific concepts 
 B.4.1 Class implementation 
  B.4.1.1 Introduction 
  B.4.1.2 Provision of classes 
  B.4.1.3 Required Java version 
  B.4.1.4 Package Structure 
 B.4.2 Sessions 
  B.4.2.1 Introduction 
  B.4.2.2 Component 
  B.4.2.3 Web browser plugin 

 B.4.3 Identifiers 
  B.4.3.1 Identifier equivalence 
  B.4.3.2 Data storage 
 B.4.4 Serialization 
 B.4.5 Relative URLs 
  B.4.5.1 Introduction 
  B.4.5.2 Java applications 
  B.4.5.3 Applets 
  B.4.5.4 Remote applications 
 B.4.6 Field access 
  B.4.6.1 NULL nodes 
  B.4.6.2 Setting MFNode fields 
  B.4.6.3 Array representations 
  B.4.6.4 set1Value 
 B.4.7 Disposing of resources

B.5 Services Binding 
 B.5.1 Establishing browser connections 
  B.5.1.1 BrowserFactory 
  B.5.1.2 getBrowser 
   B.5.1.2.1 Web plugin browser  
    B.5.1.2.2 Remote browser 
  B.5.1.3 createBrowser 
   B.5.1.3.1 AWT Component browser 
 B.5.2 Browser services 
  B.5.2.1 getName 
  B.5.2.2 getVersion 
  B.5.2.3 getCurrentSpeed 
  B.5.2.4 getCurrentFrameRate 
  B.5.2.5 getWorldURL 
  B.5.2.6 replaceWorld 
  B.5.2.7 loadURL 
  B.5.2.8 setDescription 
  B.5.2.9 createVrmlFromString 
  B.5.2.10 createVrmlFromURL 
  B.5.2.11 Dynamic Route Handling 
  B.5.2.12 Update Control 
  B.5.2.13 Register Browser Interest 
  B.5.2.14 getNode 
  B.5.2.15 Dispose 
 B.5.3 Node services 
  B.5.3.1 Node Representation 
  B.5.3.2 getName/getType 
  B.5.3.3 getField 
  B.5.3.4 Dispose 
 B.5.4 Field services 
  B.5.4.1 Field Representation 
  B.5.4.2 getAccessType 
  B.5.4.3 getType 
  B.5.4.4 getName 
  B.5.4.5 getValue 
  B.5.4.6 setValue 
  B.5.4.7 Register Field Interest 

B.6 Java Class Hierarchy 
 B.6.1 Establishing browser connections 
 B.6.2 Browser services 
 B.6.3 Node services 
 B.6.4 Field services 
 B.6.5 Class hierarchy/package arrangements 

B.7 Examples 

 

B.1.3 Conventions

The following type-setting conventions are used to indicate a particular meaning to the text in this document.

name

Words written in monospaced font are direct description of a particular Java class, field or property. This text may also provide a link to the specific documentation (provided in javadoc style documentation) to provide greater definition of the information

methodName()

Indicates a particular java method call. This may be representative of the general method name (where there are overloaded versions of the method) or just the method. No arguments definitions are provided unless needed in context to define the particular method specifically. The capitalization of the method name exactly follows the name of the method

ClassName.methodName()

The first word indicates the name of the class and is qualified with the method name. The capitalization of the class name follows the exact naming of the class. The method argument presentation is the same as that for the plain method name.

package.name.ClassName

All words up to the class name represent the package definition that the class belongs to. Referred to as the fully qualified class name. The last word is the name of the class. Capitalization follows the exact definition of the class and package.

 

--- VRML separator bar ---

B.2 Concepts

B.2.1 The Browser script interface

As with scripts within the VRML scene, the EAI allows access to the full functionality of the Browser script interface. Browser state can be queried, routes can be added and deleted, and new nodes can be created. The EAI extends the basic browser interface with a number of extra capabilities such as retrieving node references and registering interest in browser events. This annex provides an implementation in the Java language.

B.2.2 Relationship to ISO/IEC 14772-1 Annex B Java platform scripting reference

Annex B Java platform scripting reference of 2.VRML defines a Java specification to the script interface. Due to the differing capabilities of the EAI and scripting interface, the browser interfaces are not interchangeable between the two environments. This applies to all of the classes defined in ISO/IEC 14772-1 B Java platform scripting reference.

B.2.3 Scope of specification

The Java platform provides an implementation of the EAI specification. It provides a complete binding to the specification within the restrictions and implementation specific capabilities as defined in this standard. The specification provides a browser implementation independent way of accessing the browser capabilities through the Java language.

B.2.4 Conformance

Java support is not required for a conforming implementation of the EAI. If a browser supports a Java language interface from an external environment, it shall conform with all of the requirements specified in this annex.

An implementation shall not modify the classes defined in this specification with their own specific methods or additional methods. The Java reflection APIs shall be used to test this aspect of conformance.

B.2.5 Types of Java browsers

A VRML browser that can be accessed through a Java API can take one of two forms. The first form is as a plugin to a web browser. The Java code exists as an applet and accesses the plugin. The second form is a component that is available to be directly embedded in the Java framework. This form will subclass the Java Component class found in java.awt.Component.

B.2.6 Implementation dependencies

Implementation dependent for the scope of this annex is defined to be the browser writer implementation of the Java classes and how they interact with the environment and the VRML browser.

This specification does not implement the full capabilities of the EAI specification. Additional capabilities may be provided by individual implementations but shall not form part of the standard vrml.eai package hierarchy and classes as defined in this specification. Any implementation dependent provision of these capabilities shall be provided under a non-VRML package such as the vendor's own hierarchy. The listing of the implementation of all Java classes used for binding to the services is provided in B.6 Java Class Hierarchy.

--- VRML separator bar ---

B.3 Data Type Implementation

B.3.1 Data type Definitions

B.3.1.1 EAIAction

The action type is dependent on the method used. Table B.2 defines the mapping between each service, the valid action types for that service and the Java implementation of that action. Actions are mapped as method names describing the action rather than strict primitive types.

Table B.2 — EAIAction to Java implementation mapping

Service

Action Type

Java Implementation

Dynamic Route Handling

Add Route

Browser.addRoute()

Delete Route

Browser.deleteRoute()

Update Control

Begin Update

Browser.beginUpdate()

 

End Update

Browser.endUpdate()

Register Browser Interest

Add

Browser.addBrowserListener()

 

Remove

Browser.removeBrowserListener()

Register Event Interest

Add

EventOut.addVrmlEventListener()

 

Remove

EventOut.removeVrmlEventListener()

B.3.1.2 EAIBrowserApp

The data type is implemented as the class vrml.eai.VrmlComponent. The capability to obtain a EAIBrowserRef is implemented in the getBrowser() method which returns an instance of the  vrml.eai.Browser class.

B.3.1.3 EAIBrowserName

The data type is implemented as a java.lang.String.

B.3.1.4 EAIBrowserRef

The browser reference type is defined to be an instance of the vrml.eai.Browser class. The Browser class is defined as an implementation independent Java interface which is then subclassed to provide vendor specific

B.3.1.5 EAIBrowserVersion

The data type is implemented as a java.lang.String. The NULL value is defined as the Java null primitive type.

B.3.1.6 EAIFieldAccess

Field access is defined by the hierarchy of inheritance of classes used to represent the EAIFieldID. The base class vrml.eai.field.BaseField defines the basic field properties which are then subclassed. These subclasses vrml.eai.field.EventIn and vrml.eai.field.EventOut provide representations of the access types.

There is a distinct difference between the access type of the underlying field that was retrieved from the node and how it is represented by the subclasses. A request is made of the node to access any field to be viewed as either an eventIn (see Node.getEventIn()) or and eventOut (see Node.getEventOut()). The node implementation then either returns the type or generates an error condition. The acceptable conditions for successful completion of the request are defined in Table B.3

Table B.3 — Rules for mapping VRML Field types to Java field classes

 

 

Java Classes

 

 

EventIn

EventOut

VRML Field Types

field

Error

Error

eventIn

yes

Error

eventOut

Error

yes

exposedField

yes

yes

B.3.1.7 EAIFieldID

The field identifier is represented as an instance of the class vrml.eai.field.BaseField. Note that since the Java class hierarchy design allows two representations of a field using the EventIn and EventOut classes, it is possible to have two disparate references to the same field. The only time that this occurs is when referencing an exposedField of a node. The class implementation shall override the equals() method such that checking for equality in the above case shall return a result of true.

The following example illustrates the correct behaviour associated with this. The node reference has been obtained to a transform node.

Node transform;  // value has been assign previously
EventIn set_translation = transform.getEventIn("set_translation");
EventOut translation_changed = transform.getEventOut("translation_changed");
Boolean same_event_in;

same_event_in = set_translation.equals(translation_changed);
System.out.println("Checking set translation equals " +
                   "translation changed: " +
                    same_event_in);

// now check the reverse case
same_event_in = translation_changed.equals(set_translation);
System.out.println("Checking translation changed equals " +
                   "set translation: " +
                    same_event_in);

The resulting execution of this code segment should produce on standard output

Checking set translation equals translation changed: true
Checking translation changed equals set translation: true

B.3.1.8 EAIFieldName

The name of the field is implemented as a java.lang.String.

B.3.1.9 EAIFieldType

The field type may be represented in two alternative fashions.

The first alternative is provided through getType() method provided in the BaseField class. This returns an int which has one of the values defined by the constant types also defined in that class as shown in Table B.4.

Table B.4 — Mapping of VRML Field type to Java representation

VRML Field type

Java representation

MFColor

static final int MFColor

MFFloat

static final int MFFloat

MFInt32

static final int MFInt32

MFNode

static final int MFNode

MFRotation

static final int MFRotation

MFString

static final int MFString

MFTime

static final int MFTime

MFVec2f

static final int MFVec2f

MFVec3f

static final int MFVec3f

SFBool

static final int SFBool

SFColor

static final int SFColor

SFFloat

static final int SFFloat

SFImage

static final int SFImage

SFInt32

static final int SFInt32

SFNode

static final int SFNode

SFRotation

static final int SFRotation

SFString

static final int SFString

SFTime

static final int SFTime

SFVec2f

static final int SFVec2f

SFVec3f

static final int SFVec3f

The second alternative is provided by the class hierarchy. The EventIn and EventOut classes are further derived to provide implementations of the exact field type. These classes are defined in the vrml.eai.field package. A list of all the classes for each field type and access type is provided in B.5.4 Field Services.

B.3.1.10 EAIFieldValue

The field value is defined on a per class and per field type instance. See the definitions of the classes in the vrml.eai.field package for the exact definition of each type.

B.3.1.11 EAIFrameRate

The data type is implemented as the Java primitive type float. A null value is defined as the value 0.0f.

B.3.1.12 EAINavSpeed

The data type is implemented as the Java primitive type float. A null value is defined as the value 0.0f.

B.3.1.13 EAINodeID

The node identifier is represented as an instance of vrml.eai.Node.

B.3.1.14 EAINodeType

The node type is represented as a java.lang.String.

B.3.1.15 EAIParameterList

The data type is represented by the values in the Table B.5. The table defines the services that use the data type, the method of the BrowserFactory class  and the lists of argument types that method takes.

Table B.5 — Mapping of EAIParameterList to Java parameter lists

Service

method

Java Parameters

getBrowser

getBrowser()

java.applet.Applet

getBrowser()

java.applet.Applet, String, int

getBrowser()

java.net.InetAddress, int

createBrowser

createVrmlComponent()

None

 

B.3.1.16 EAIPropertyList

The data type is implemented as an array of java.lang.String. Key/Value pairs are declared in a single string in the following format with the '=' character as the separator. Whitespace surrounding the key and value are ignored although whitespace inside the key and value are legal.

The following are considered valid values (as well as permutations of the given examples):

"key=value"
"key = value "
" key = value"
"a key= some value"
"a key     =some value"

B.3.1.17 EAIRequesterID

The requestor ID is represented as an instance of one of two classes depending on what information is being requested.

The requestor ID is an instance of the class implementing the interface vrml.eai.event.BrowserListener when the service request is browser_event_interest.

The requestor ID is an instance of the class implementing the interface vrml.eai.event.VrmlEventListener when the service request is field_event_interest.

B.3.1.18 EAIURL

The URL is implemented as a java.lang.String.

B.3.1.19 EAIString

The string is implemented as a java.lang.String.

B.3.2 Error data types

B.3.2.1 EAIError

Java implementations of the errors rely on a set of derived classes based on the EAIError type.

The error type is implemented as the class vrml.eai.VrmlException. This exception is in turn derived from the standard Java error type of java.lang.RuntimeException. All exceptions(errors) defined in this specification shall be derived from VrmlException.

B.3.2.2 EAI_BROWSER_UNAVAILABLE

The error type is implemented as the class vrml.eai.NoSuchBrowserException.

B.3.2.3 EAI_CONNECTION_ERROR

The error type is implemented as the class vrml.eai.ConnectionException.

B.3.2.4 EAI_DISPOSED

The error type is implemented as two separate dual purpose exception classes depending on their scope.

vrml.eai.InvalidBrowserException is used to indicate an EAIBrowserRef has been disposed of.
vrml.eai.InvalidNodeException is used to indicate an EAINodeID has been disposed of.

B.3.2.5 EAI_INVALID_ACCESS_TYPE

The error type is implemented as two separate exceptions based on the implementation of EAINodeID and the rules defined in Table B.2. These classes also derive from vrml.eai.field.InvalidFieldException.

vrml.eai.field.InvalidEventInException is used to indicate the named field is not accessible as an eventIn from the Node.getEventIn() method.

vrml.eai.field.InvalidEventOutException is used to indicate the named field is not accessible as an eventOut from the Node.getEventOut() method.

B.3.2.6 EAI_INVALID_BROWSER

The error type is implemented as the class vrml.eai.InvalidBrowserException.

B.3.2.7 EAI_INVALID_NAME

The error type is expressed as different exceptions dependent on the situation. The Browser.getNode() method uses the InvalidNodeException. The Node class getEventIn() and getEventOut() methods use the InvalidEventInException and InvalidEventOutException types respectively.

B.3.2.8 EAI_INVALID_NODE

The error type is implemented as the class vrml.eai.InvalidNodeException.

B.3.2.9 EAI_INVALID_FIELD

The error type is implemented as the class vrml.eai.field.InvalidFieldException. Note that there are two derived classes from this class (InvalidEventInException and InvalidEventOutException) that may be used at times where this error may be generated.

B.3.2.10 EAI_INVALID_URL

The error type is implemented as the class vrml.eai.InvalidURLException.

B.3.2.11 EAI_INVALID_VRML

The error type is implemented as the class vrml.eai.InvalidVrmlException.

B.3.2.12 EAI_URL_UNAVAILABLE

The error type is implemented as the class vrml.eai.URLUnavailableException.

B.3.3 Event Types

B.3.3.1 Concepts

The Java implementation of the event handling and types is based around the Java 1.1 AWT event listener model. A single event class is used to encapsulate the type of event and then parameters defining the actual event item that occurred.

B.3.3.2 EAIBrowserEvent

vrml.eai.event.BrowserEvent

The event type is implemented in the class vrml.eai.event.BrowserEvent. Each of the individual events are expressed as actions that the event then passes to the registered listeners. The action type of the individual event is available through the getID() method.

B.3.3.3 EAI_B_Initialized

The event type is implemented as the INITIALIZED value for the browser event ID.

B.3.3.4 EAI_B_Shutdown

The event type is implemented as the SHUTDOWN value for the browser event ID.

B.3.3.5 EAI_B_ConnectionError

The event type is implemented as the CONNECTION_ERROR value for the browser event ID.

B.3.3.6 EAI_B_URLError

The event type is implemented as the URL_ERROR value for the browser event ID.

B.3.3.7 EAIFieldEvent

The event type is implemented as the class vrml.eai.event.VrmlEvent. This class contains methods for obtaining the source of the event, the time (in VRML time) and any user defined data that occurred with the event.

--- VRML separator bar ---

B.4 Language specific concepts

B.4.1 Class implementation

B.4.1.1 Introduction

This specification provides a set of implementation independent base classes that represent the possible interactions with the VRML scene through the External Authoring Interface. Browser specific implementation dependencies shall to remain hidden to the general user. Where classes are declared to be abstract, it is expected that the browser specific implementation shall derive from these classes as required.

An implementation shall not modify these base classes with their own specific methods or additional methods.

The difference between the two forms of the browser is limited to how to initially obtain the browser reference. Once this has been obtained, the services provided shall not differ. The term application is used to describe the Java code that wishes to access the VRML browser, regardless of how the initial reference to the browser was obtained.

B.4.1.2 Provision of Classes

A browser that supports the EAI Java implementation may supply the base classes as part of the distribution. The design of the classes is such that only one copy of the classes defined by this application needs to be placed on the machine although multiple copies are permitted. Implementation dependent classes need only to be supplied with the browser and accessed by setting the CLASSPATH to point to the appropriate implementation dependent classes.

It is recommended that the implementation of the classes defined by this specification are placed in either a zip file or Java Archive (JAR file) under the <JAVAHOME>/lib directory.

B.4.1.3 Required Java version

Where a VRML browser is supplied as a standalone application, the minimum required version of Java Virtual Machine support is version 1.1.

VRML Browsers that operate as a plugin to general purpose web browsers may support whatever version of Java that the web browser supports. In the case where the web browser does not support any Java, or multiple versions, the minimum of version 1.1 shall be required.

B.4.1.4 Package Structure

The Java bindings to the EAI shall be provided under the vrml.eai top level package structure and are organized in the following manner.

vrml.eai

The basic working classes for the interface to the browser and nodes. 

vrml.eai.event

Event classes and listener interfaces

vrml.eai.field

Classes for accessing fields

B.4.2 Sessions

B.4.2.1 Introduction

A session for Java based communications is dependent on the type of handle established: applet or component.

The difference between the two forms of the browser is limited to how to initially obtain the browser reference. Once this has been obtained, the services provided shall not differ. The term application is used to describe the Java code that wishes to access the VRML browser, regardless of how the initial reference to the browser was obtained.

B.4.2.2 Component

A VRML browser established by creating a new instance of the vrml component class. This instance may then be inserted into the Java GUI framework following any Java restrictions that may be imposed on the class as a result of adding it to an AWT Container.

At the point where the browser object is instantiated, it contains no scene graph. To load the initial scene the loadURL() method is called. If the application has registered as a listener for browser events, it shall receive the initialize event as specified in the EAI specification.

Components follow the normal rules for any class derived from java.awt.Component. It may be freely added to any container and have extra components added that may partially or completely obscure the area of the window that is being used to render the VRML world. At no time shall the actions of other components that partially or complete obscure the VRML browser cause execution of the VRML event model to suspend or complete.

Note that this allows application code to draw over the top of the VRML window and attach any Java.awt.event listener as it requires without modifying the functionality of the VRML browser and vice versa.

B.4.2.3 Web Browser Plugin

When the VRML browser exists as an element embedded in a HTML page to which a Java applet has access, it must use the underlying web browser APIs to access the plugin. The session is defined to last as long as that particular plugin instance is associated with a currently active page. A factory class shall be provided to obtain a reference to a VRML browser plugin in an implementation independent manner.

The browser shall also provide notification to the listening applications of when the world is no longer displayed on the page. When the browser is removed from visibility it shall generate a shutdown event to all registered listeners. If the browser becomes visible again an initialized event shall be generated. If a new page is loaded with a VRML browser as part of it, it will contain a different Browser reference and hence the applet will not receive any such notification of its presence.

B.4.3 Identifiers

B.4.3.1 Identifier equivalence

Due to the nature of Java to native code interaction, it is possible that two instances of a Java class may refer to the same node or field inside the vrml scene (that is, using the == comparison will be false). For this reason, an identifier of a node or field cannot be implied to mean the same instance reference of the class representation. The representation of an Identifier in Java classes is implementation dependent. However, class instances may be checked for equivalence by calling the equals() method of the appropriate class. Implementations of the classes shall override the equals() method so that comparing two nodes, fields or other classes that require an identifier will return the correct result.

B.4.3.2 Data Storage

In the class structure, it is possible to associate user definable data references with each field of a node and with the node itself. If one reference to a node has data associated with it,, this information shall be available to all references to that node at all times. For example, if a field has data associated with it, is then disposed and a later application references that node, the data shall still remain (if that other application is Java based). There is no requirement to store this information if the node/field is no longer referenced by external applications or the internal scene graph, or if the external application is not Java based.

B.4.4 Serialization

Java serialization may be used to either store the state of the scene graph (for example in a database or file) or communicate between two applications/applets interfacing with the same browser. Because serialization does not maintain the same Java reference, calls to the equals() method shall produce the correct result. The specification has not defined classes to be serializable. This is implementation dependent.

B.4.5 Relative URLs

B.4.5.1 Introduction

Due to the different environments that a Java based VRML may find itself in, this binding defines the following additional behaviour for Java implementations.

B.4.5.2 Java applications

For standalone Java applications, the current working directory is determined by using the user.dir system property of the application. If a RURL is passed to the browser, it shall be resolved in equivalent terms to the following statements:

String url_base = System.getProperty("user.dir");
String complete_url = "file://" + url_base + <relative_url> ;
java.net.URL url = new URL(complete_url);

B.4.5.3 Applets

The base document of the browser is considered to be the web page in which the browser is embedded if the VRML Browser does not have a VRML world loaded.

If the applet also creates a component-based VRML browser, the base document determination shall be treated in exactly the same manner as B.4.5.2 Java applications if there is not a base world already loaded. Note that this normally will produce different base documents if an applet accesses both a plugin and a component-based browser simultaneously.

B.4.5.4 Remote applications

If a browser is located remotely to the application using it (for example using an RMI implementation), the base url is considered to be the base URL of the world. If no world URL has yet been set, the appropriate action shall be either of the previous two sections depending on how the browser was started.

B.4.6 Field access

B.4.6.1 NULL nodes

The Java null reference to an object shall be treated as the equivalent of the VRML NULL value. Where an SFNode field has its value set to null, this shall clear the field of the node reference causing the default behaviour defined by the parent node to be used for that field. When reading a value of an SFNode field where it is empty, the return value shall be null.

B.4.6.2 Setting MFNode fields

MFNodes are represented as an array of Node instances. It is possible that during the creation of the array some or all of contents may contain null references. How the browser treats a null reference is implementation dependent. That is, it is permissible to read back the field value and have it not contain the null node references, or to maintain them in the order they were sent.

B.4.6.3 Array representations

In MF fields, arrays are used to represent the data contained in the VRML field. Setting the value of that field with an array of length 0 shall result in the contents of the field being cleared and is the equivalent of the VRML text file declaration of

SomeNode {
  MFField []
}

An empty MF field shall return an array of length zero if queried about its value. The size() method of the MFField base class shall return a value of 0.

Attempting to set the value of the field with null shall generate an IllegalArgumentException.

B.4.6.4 set1Value

MFField classes contain a set1Value() method for setting an individual value in the field.

If beginUpdate() has been called and multiple set1Value() methods have been called on that field, the result when endUpdate() is called shall be a single event with all of the individual values set. If two calls are made to set a particular array index, the last value written shall be used.

If beginUpdate()has not been called, the result shall be an event that contains the entire field value with the individual value changed. Multiple set1Value() calls to the field shall result in the equivalent number of events being generated inside the VRML browser.

B.4.7 Disposing of Resources

Of particular concern to Java implementations is the disposal of resources used by the Java environment. The garbage collection environment creates problems when dealing with native code implementations of the VRML browser. An explicit dispose() method is provided with all classes representing VRML entities so that the application can explicitly dispose of the resources used by the browser implementation.

For safety purposes, where a class defines a dispose() method, it shall also override the default finalize() method provided by java.lang.Object and call the dispose() method. This shall ensure that even if the user has not explicitly called dispose on objects, when the object reference goes out of scope, all resources shall be freed regardless avoiding potential memory leaks.

Once a node has had the dispose method of, method calls on the node shall generate an InvalidNodeException.

--- VRML separator bar ---

B.5 Services Binding

B.5.1 Establishing browser connections

B.5.1.1 BrowserFactory

vrml.eai.BrowserFactory

Creating a reference to a VRML browser must deal with a number of different scenarios: Java applet to VRML plugin in a web browser, server application talking to a browser on a separate machine or a component in a standalone Java application. Each of these requires a separate solution in order to maintain implementation dependence.

The method of access a VRML browser shall be through a single factory style class. This class contains methods for each type of access. To provide implementation independence the vrml.eai.BrowserFactoryImpl interface for the implementation dependent parts is defined. Browsers shall subclass this interface to provide the necessary dependent code. This interface is loaded by the vrml browser factory using dynamic methods or by having the code explicitly set.

A properties file called vrml.properties, if resident in the user's CLASSPATH shall be used to determine the name of the class to be loaded. The name of the property in the properties file shall be

vrml.eai.factory.class

which shall be set to the fully qualified name of the browser factory class implementation to be loaded. The implementation of this class shall not reside within the vrml.* class hierarchy but shall reside in the browser writer's own class hierarchy. The browser factory shall also contain a setBrowserFactoryImpl() method to allow an explicit setting of the factory implementation. If this method is the first method called of all the factory methods, it shall be used as the factory implementation. If any other method is called prior to calling this method, the name of the factory implementation shall be drawn from the properties file and loaded. Any attempt to call the set implementation method shall result in a vrml.eai.VrmlException being generated.

The factory implementation shall return the appropriate subclasses for each of the methods. If the implementation does not support the particular connection requested, it shall generate a vrml.eai.NotSupportedException. If it is supported, it shall return the appropriate subclass of the object for that method.

B.5.1.2 getBrowser

B.5.1.2.1 Web Plugin browser

Browser BrowserFactory.getBrowser(Applet)
Browser BrowserFactory.getBrowser(Applet, String, int)

A browser that operates as part of a web browser requires a number of different parameters for correct determination of the plugin to access. Due to the nature of web pages, it is possible that an applet on one page may access either more that one VRML plugin or that the plugin exists in another HTML frame. The applet form of the getBrowser() method requires a reference to the accessing applet, the name of the frame and the index of the frame in the nominated frame. The frame name is a string representing the name of the frame. The index is the number of the VRML browser in the page (where there might be more than one) starting from 0.

B.5.1.2.2 Remote browser

Browser BrowserFactory.getBrowser(InetAddress, int)

An application server may wish to access browsers on client machines. The third variant of the getBrowser request requires an IP address (or machine name) and a port number. The server application requests the browser reference of the remote machine. Once the browser reference is returned, the server application may manipulate the browser contents like any other EAI using application.

The port number of the protocol may be any port number. There is no defined default port to which a browser will listen. The protocol between the application and the browser is also not defined.

B.5.1.3 createBrowser

B.5.1.3.1 AWT Component browser

VrmlComponent BrowserFactory.createVrmlComponent(String[])

The component browser is required to fit into the standard java.awt.Component model and is implemented as a subclass of vrml.eai.VrmlComponent. It shall derive from java.awt.Component and also provide a getBrowser() method that returns a reference to a standard vrml.eai.Browser object. The component implementation may implement the component in any manner it requires. Both lightweight components (all rendering performed in Java) and heavyweight components (with peer interfaces extending from java.awt.peer.ComponentPeer) are permitted. These details shall be hidden within the implementation specific classes and not accessible to the general API user.

The factory class shall include a method that generates an instance of this component class. Each call to the component shall result in a new independent instance of a VRML browser capable of running as a component. The browser shall be capable of running either within a web browser environment (e.g., Java applet window with a VRML browser in it) or in standalone applications with the restrictions appropriate to the underlying environment. It shall also use whatever hints are supported in the parameter argument passed to it. These hints are in the same form as those passed to loadURL.

B.5.2 Browser services

B.5.2.1 getName

String Browser.getName()

The name returned is a String representing the name of the browser. If this is not supported, null shall be returned.

B.5.2.2 getVersion

String Browser.getVersion()

The version returned is a String representing the version number of the browser. If this is not supported, null shall be returned.

B.5.2.3 getCurrentSpeed

float Browser.getCurrentSpeed()

The speed value returned shall be a floating point number or 0.0 if is not supported.

B.5.2.4 getCurrentFrameRate

float Browser.getCurrentFrameRate()

The frame rate value shall be a floating point number or 0.0 if it is not supported.

B.5.2.5 getWorldURL

String Browser.getWorldURL()

The world URL shall be a string indicating the complete world URL as defined in 6.3.11 getWorldURL.

B.5.2.6 replaceWorld

void Browser.replaceWorld(Node[])

The parameter shall be an array of Node instances which shall be used to replace the currently loaded world. If one or more of the node instances have been disposed of, an IllegalArgumentException shall be generated.

B.5.2.7 loadURL

void Browser.loadURL(String[], String[])

The parameters shall be an array of strings for the URL list and an array of Strings for the parameters. If the browser determines that it cannot load any of the URLs passed, the browser event listener shall receive an event notifying it of an error.

If the parameters list is a zero length array or is null, the action is to replace the world in the current browser. The properties defined in Table B.6 are standard values that shall be supported.

Table B.6 — Property list for loadURL

Key

Value

Description of Function

replace

true

Replaces the entire page that browser is embedded in. If the browser is a standalone browser  this shall have no effect.

false

The browser shall replace the contents of the currently loaded world with the new world specified by the URL argument. The same effect as providing no value to the parameters argument.

target

<frameName>

The name of the frame shall be used to load the browser as the contents of the named HTML frame.

Individual browser implementations may support extra property definitions.

B.5.2.8 setDescription

void Browser.setDescription(String)

This service sets the description string of the browser. If the browser is running as a plugin, this shall set the title of the page (if the containing web browser supports this). For component browsers the result shall be implementation dependent.

B.5.2.9 createVrmlFromString

Node[] Browser.createVrmlFromString(String)

The parameter shall be a string that contains legal syntax as defined in ISO/IEC 14772-1. The only difference is that the file header #VRML V2.0 utf8 need not be present as the first line in the string. If the string does not contain legal VRML97 syntax, an InvalidVrmlException shall be generated. Returned is an array of the top level Nodes  in the order that they are declared in the string parameter.

B.5.2.10 createVrmlFromURL

void Browser.createVrmlFromURL(String[], Node, String)

The parameter list shall consist of an array of Strings describing the list of URLs, a reference to a destination Node and a String which is the name of the eventIn to send the loaded URL nodes to.  If the browser determines that it cannot load any of the URLs passed, the browser event listener shall receive an event notifying it of an error.

B.5.2.11 Dynamic Route Handling

void Browser.addRoute(Node, String, Node, String)
void Browser.deleteRoute(Node, String, Node, String)

This service is split into two separate methods: addRoute and deleteRoute. They both take the same argument list. The first parameter is a Node reference that the event will leave from. The second is a String describing the name of the eventOut. Third and forth parameters are the destination node reference and the eventIn as a String. If either of the Node references have been disposed of, an InvalidNodeException shall be generated. If either of the nodes do not contain the nominated eventIn/eventOut, an InvalidEventIn/EventOutException shall be generated appropriately.

B.5.2.12 Update Control

void Browser.beginUpdate()
void Browser.endUpdate()

This service is split into two separate methods beginUpdate and endUpdate. The functionality remains as described in 6.3.16 Update Control.

B.5.2.13 Register Browser Interest

void Browser.addBrowserListener(BrowserListener)
void Browser.removeBrowserListener(BrowserListener)

Registering interest in browser events is through a browser event listener. The listener is an interface which is passed browser events when the state of the browser changes or asynchronous error messages must be sent (for example, inability to load any of the requested URLs). Methods shall be provided to allow listeners to be added and removed dynamically. A separate event class shall be used to indicate the event information. This class has a predefined number of events although specific browser implementations may send more events than the defined values. The toString() method shall be overridden in this case to provide more information to the user in determining the extra event types to deal with them. Any extra event types must not have values below the figure defined by LAST_IDENTIFIER.

B.5.2.14 getNode

Node Browser.getNode(String)

The return value is a Node reference. The parameter is a String defining the DEF name of the required node. If the browser cannot find the node name, an InvalidNodeException shall be generated.

B.5.2.15 Dispose

void Browser.dispose()

Dispose shall notify the browser that the Java implementation is no longer interested in the VRML browser. Any further requests to methods of this instance of the browser interface shall generate an InvalidBrowserException.

B.5.3 Node services

B.5.3.1 Node Representation

vrml.eai.Node

The ability to list all of the fields of a node reference and their values is not available as part of the standard implementation. It is not possible to get the name of the node. The implementation of the node services is implemented as the class vrml.eai.Node.

B.5.3.2 getName/getType

String Node.getType()

The 6.4.5 getType and 6.4.4 getName services are combined into a single method request getType() that returns the name of the node as a String.

B.5.3.3 getField

EventIn Node.getEventIn(String)
EventOut Node.getEventOut(String)

6.4.3 getField service is implemented as two separate methods getEventIn() and getEventOut() which allows access to eventIns and eventOuts but not to fields. An exposedField may be accessed as either the eventIn or eventOut portion separately through these two methods. The normal field name or with the set_ modifier may be used with the getEventIn method. The normal field name or the _changed modifier may be used with the getEventOut method.

B.5.3.4 Dispose

void Node.dispose()

Dispose shall notify the browser that the Java implementation is no longer interested in this node instance and it is free to do as required with the node representation. Any further requests to methods of this instance of the node reference shall generate an InvalidNodeException. If two separate instances of the same class represent the same node (as defined by the equals() method returning true) and one has dispose called, this shall not effect the other instance.

B.5.4 Field services

B.5.4.1 Field Representation

vrml.eai.field package
vrml.eai.field.BaseField and subclasses.

The Java implementation of the field services does not directly follow the model outlined in 6.5 Field Services. Instead, it makes heavy use of the Object Oriented nature of Java to provide directly the capabilities suggested by the services specified. All the services are implemented in the classes provided in the vrml.eai.field package.

The following outlines how the Java binding conforms to the requirements of the EAI.

B.5.4.2 getAccessType

6.5.2 getAccessType is not a directly callable method in the Java implementation. The access type is implied by the class that represents the field. For example, calling

EventIn trans = some_transform.getEventIn("set_translation");

will return an EventIn class reference. From this the implication is that the access type of this field is an eventIn.

B.5.4.3 getType

int BaseField.getType()

The getType() method of vrml.eai.field.BaseField returns an identifier of the type of field that the instance of the class represents. The list of legal type identifiers is included as public final variables in the class. The return value of the getType() method shall be one of these values.

The class instance is also used as an alternative type of representation of the node type. There shall be one class for each type of VRML field, one derived from EventIn and one derived from EventOut. The class reference returned from a call to Node.getEventIn() or Node.getEventOut() shall return an instance of one of these classes respectively.

B.5.4.4 getName

The 6.5.3 getName service is not supported by the Java language bindings

B.5.4.5 getValue

The getValue() method of vrml.eai.field.BaseField is supported only on classes derived from eventOut. It is not possible to read values from eventIn as there is no method to support this operation. On fields which are exposedFields, an eventOut derived class will be needed to access the field to read its value.

The getValue() method returns values in a format appropriate to the individual field type. If the method returns an array of values, the array shall be guaranteed to be created on each call. The implementation shall not reuse return value references between calls to the methods. This is to guarantee thread-safe data integrity.

To provide similarity to ISO/IEC 14772-1 B Java platform scripting reference, a get1Value() method is provided for MF fields. This allows access to a single value out of the many values. When an attempt is made to access a value at an index greater than the number of items in that eventOut, a java.lang.ArrayIndexOutOfBoundsException shall be generated. Each time the getValue() method is called, a new instance of the returned array shall be generated.

An alternate form of the getValue()and get1Value() methods shall be available for the MF eventOuts. These forms shall take arrays as parameters that can be used to write values in. See the javadoc outline of each class for proper definitions of what methods are to be provided.

B.5.4.6 setValue

The setValue() method of vrml.eai.field.BaseField is supported only on classes derived from EventIn. It is not possible to write values from eventIn as there is no method to support this operation. On fields which are exposedFields, an EventIn derived class will be needed to write a new value.

To provide similarity with ISO/IEC 14772-1 B Java platform scripting reference, a set1Value() method is provided for MFFields. This allows the ability to change a single value of a field without having to re-create the entire array of values. When an attempt is made to set a value at an index greater than the number of items in that eventIn, a java.lang.ArrayIndexOutOfBoundsException shall be generated. See B.4.6.4 set1Value for other behavioural aspects of this method.

B.5.4.7 Register Field Interest

void EventOut.addVrmlEventListener(VrmlEventListener)
void EventOut.removeVrmlEventListener(VrmlEventListener)

The shall be no capabilities to attach listeners to eventIns. Listening to eventOuts is available. This restriction is implemented as part of the Java API implementation which has separate classes for eventIn and eventOut representation. Where a field is declared to be an exposedField, listeners can only be attached to the eventOut portion.

--- VRML separator bar ---

B.6 Java Class Hierarchy

B.6.1 Establishing Browser Connections

Classes/Interfaces

vrml.eai.Browser
vrml.eai.BrowserFactory
vrml.eai.BrowserFactoryImpl
vrml.eai.VrmlComponent

Exceptions

vrml.eai.NoSuchBrowserException
vrml.eai.NotSupportedException
java.net.UnknownHostException

B.6.2 Browser Services

Classes/Interfaces

vrml.eai.Browser
vrml.eai.Node
vrml.eai.event.BrowserListener
vrml.eai.event.BrowserEvent

Exceptions

vrml.eai.InvalidBrowserException
vrml.eai.InvalidVrmlException
vrml.eai.InvalidNodeException
vrml.eai.InvalidURLException
vrml.eai.URLUnavailableException
vrml.eai.field.InvalidEventInException
vrml.eai.field.InvalidEventOutException

B.6.3 Node Services

Classes/Interfaces

vrml.eai.Node
vrml.eai.field.EventOut
vrml.eai.field.EventIn

Exceptions

vrml.eai.InvalidNodeException
vrml.eai.field.InvalidEventInException
vrml.eai.field.InvalidEventOutException

B.6.4 Field Services

Classes/Interfaces

vrml.eai.field.BaseField
vrml.eai.field.EventIn
vrml.eai.field.EventInMFColor
vrml.eai.field.EventInMFFloat
vrml.eai.field.EventInMFInt32
vrml.eai.field.EventInMFNode
vrml.eai.field.EventInMFRotation
vrml.eai.field.EventInMFString
vrml.eai.field.EventInMFTime
vrml.eai.field.EventInMFVec2f
vrml.eai.field.EventInMFVec3f
vrml.eai.field.EventInSFBool
vrml.eai.field.EventInSFColor
vrml.eai.field.EventInSFFloat
vrml.eai.field.EventInSFImage
vrml.eai.field.EventInSFInt32
vrml.eai.field.EventInSFNode
vrml.eai.field.EventInSFRotation
vrml.eai.field.EventInSFString
vrml.eai.field.EventInSFTime
vrml.eai.field.EventInSFVec2f
vrml.eai.field.EventInSFVec3f
vrml.eai.field.EventOut
vrml.eai.field.EventOutMField
vrml.eai.field.EventOutMFColor
vrml.eai.field.EventOutMFFloat
vrml.eai.field.EventOutMFInt32
vrml.eai.field.EventOutMFNode
vrml.eai.field.EventOutMFRotation
vrml.eai.field.EventOutMFString
vrml.eai.field.EventOutMFTime
vrml.eai.field.EventOutMFVec2f
vrml.eai.field.EventOutMFVec3f
vrml.eai.field.EventOutSFBool
vrml.eai.field.EventOutSFColor
vrml.eai.field.EventOutSFFloat
vrml.eai.field.EventOutSFInt32
vrml.eai.field.EventOutSFNode
vrml.eai.field.EventOutSFRotation
vrml.eai.field.EventOutSFString
vrml.eai.field.EventOutSFTime
vrml.eai.field.EventOutSFVec2f
vrml.eai.field.EventOutSFVec3f
vrml.eai.event.VrmlEvent
vrml.eai.event.VrmlEventListener

Exceptions

vrml.eai.field.InvalidFieldException
vrml.eai.field.InvalidEventInException
vrml.eai.field.InvalidEventOutException

B.6.5 Class Hierarchy/Package Arrangements

Package vrml.eai
 
   +- vrml.eai.Browser
 
   +- vrml.eai.BrowserFactory
 
   +- vrml.eai.Node
 
   +- vrml.eai.BrowserFactoryImpl
 
   +- vrml.eai.VrmlComponent
 
   +- vrml.eai.VrmlException
 
     +- vrml.eai.InvalidBrowserException
 
     +- vrml.eai.InvalidVrmlException
 
     +- vrml.eai.InvalidNodeException
 
     +- vrml.eai.InvalidURLException
 
     +- vrml.eai.NoSuchBrowserException
 
     +- vrml.eai.NotSupportedException
 
     +- vrml.eai.URLUnavailableException
 
 
 
Package vrml.eai.event
 
   +- vrml.eai.event.BrowserListener
 
   +- vrml.eai.event.BrowserEvent
 
   +- vrml.eai.event.VrmlEvent
 
   +- vrml.eai.event.VrmlEventListener
 
 
 
Package vrml.eai.field
 
   +- vrml.eai.field.BaseField
 
      +- vrml.eai.field.EventIn
 
      |  +- vrml.eai.field.EventInMFColor
 
      |  +- vrml.eai.field.EventInMFFloat
 
      |  +- vrml.eai.field.EventInMFInt32
 
      |  +- vrml.eai.field.EventInMFNode
 
      |  +- vrml.eai.field.EventInMFRotation
 
      |  +- vrml.eai.field.EventInMFString
 
      |  +- vrml.eai.field.EventInMFTime
 
      |  +- vrml.eai.field.EventInMFVec2f
 
      |  +- vrml.eai.field.EventInMFVec3f
 
      |  +- vrml.eai.field.EventInSFBool
 
      |  +- vrml.eai.field.EventInSFColor
 
      |  +- vrml.eai.field.EventInSFFloat
 
      |  +- vrml.eai.field.EventInSFImage
 
      |  +- vrml.eai.field.EventInSFInt32
 
      |  +- vrml.eai.field.EventInSFNode
 
      |  +- vrml.eai.field.EventInSFRotation
 
      |  +- vrml.eai.field.EventInSFString
 
      |  +- vrml.eai.field.EventInSFTime
 
      |  +- vrml.eai.field.EventInSFVec2f
 
      |  +- vrml.eai.field.EventInSFVec3f
 
      +- vrml.eai.field.EventOut
 
         +- vrml.eai.field.EventOutMField
 
            +- vrml.eai.field.EventOutMFColor
 
            +- vrml.eai.field.EventOutMFFloat
 
            +- vrml.eai.field.EventOutMFInt32
 
            +- vrml.eai.field.EventOutMFNode
 
            +- vrml.eai.field.EventOutMFRotation
 
            +- vrml.eai.field.EventOutMFString
 
            +- vrml.eai.field.EventOutMFTime
 
            +- vrml.eai.field.EventOutMFVec2f
 
            +- vrml.eai.field.EventOutMFVec3f
 
            +- vrml.eai.field.EventOutSFBool
 
            +- vrml.eai.field.EventOutSFColor
 
            +- vrml.eai.field.EventOutSFFloat
 
            +- vrml.eai.field.EventOutSFInt32
 
            +- vrml.eai.field.EventOutSFNode
 
            +- vrml.eai.field.EventOutSFRotation
 
            +- vrml.eai.field.EventOutSFString
 
            +- vrml.eai.field.EventOutSFTime
 
            +- vrml.eai.field.EventOutSFVec2f
 
            +- vrml.eai.field.EventOutSFVec3f
 
   +- vrml.eai.VrmlException
 
      +- vrml.eai.field.FieldException
 
      +- vrml.eai.field.InvalidEventInException
 
      +- vrml.eai.field.InvalidEventOutException

B.7 Examples

The following is an example Java EAI script that finds a Material node called BoxMaterial in the scene graph and changes its diffuseColor field to be 0 1 0. This has the effect of changing the box from its original red color to green. To view this example within a web browser, the following HTML segment is used.

index.html

  <embed src="box.wrl" height="300" width="300">
  <applet code="box.class" mayscript height="1" width="1">
  </applet>
 
box.wrl
  #VRML V2.0 utf8
 
  Shape {
     appearance Appearance {
        material DEF BoxMaterial Material {
          diffuseColor 1 0 0
        }
     }
     geometry Box { size 2 2 2 }
  }
 
box.java
  import java.applet.*;
  import vrml.eai.field.*;
  import vrml.eai.Node;
  import vrml.eai.BrowserFactory;
  import vrml.eai.Browser;
 
  public class box extends Applet {
 
    public void init() {
      super.init();
    }
 
    public void start() {
      Browser browser = null;
      Node material = null;
      EventInSFColor boxcolor = null;
 
      // Get the VRML Browser - try 10 times
 
      for (int count = 0; count < 10; count++) {
        browser = BrowserFactory.getBrowser(this);
        if (browser != null) break;
        try {
          Thread.sleep(200);
        } catch (InterruptedException ignored) {}
      }
 
      // Get the diffuseColor eventIn of the DEF'd material node
 
      try {
        material = browser.getNode("BoxMaterial");
        boxcolor = (EventInSFColor) material.getEventIn("set_diffuseColor");
      } catch (vrml.eai.InvalidNodeException ignored) {}
 
      // Sleep for 1 second
 
      try {
        Thread.sleep(1000);
      } catch ( InterruptedException ignored ) {}
 
      // Change the material's diffuse color to green (0,1,0)
 
      float[] newcolor = new float[3];
      newcolor[0] = 0.0f;  newcolor[1] = 1.0f;  newcolor[2] = 0.0f;
      boxcolor.setValue(newcolor);
    }
  }

The next example shows how to create new geometry and add this to an existing scene using the EAI. In this case, the VRML file contains a red cuboid and the EAI script creates and overlays a blue sphere. The HTML segment for embedding this example in a web browser is as follows.

Figure B.1 — CreateVrmlFromString example

index.html

  <embed src="create.wrl" height="300" width="300">
  <applet code="create.class" mayscript height="1" width="1">
  </applet>
create.wrl
  #VRML V2.0 utf8
 
  DEF NewNode Group {}
 
  Shape {
     appearance Appearance {
        material DEF BoxMaterial Material {
          diffuseColor 1 0 0
        }
     }
     geometry Box { size 2 2 1 }
  }
create.java
  import java.applet.*;
  import vrml.eai.field.*;
  import vrml.eai.Node;
  import vrml.eai.BrowserFactory;
  import vrml.eai.Browser;
 
  public class create extends Applet {
 
    public void init() {
      super.init();
    }
 
    public void start() {
      Browser       browser  = null;
      Node          rootnode = null;
      EventInMFNode children = null;
 
      // Get the VRML Browser - try 10 times
 
      for (int count = 0; count < 10; count++) {
        browser = BrowserFactory.getBrowser(this);
        if (browser != null) break;
        try { Thread.sleep(200); } catch (InterruptedException e) {}
      }
 
      // Get the set_children eventIn of the DEF'd Group node
 
      try {
        rootnode = browser.getNode("NewNode");
        children = (EventInMFNode) rootnode.getEventIn("set_children");
      } catch (vrml.eai.InvalidNodeException ignored) {}
 
      // Create a new blue Sphere Shape node
 
      String newvrml =
        "#VRML V2.0 utf8\nShape { appearance Appearance { material " +
        "Material { diffuseColor 0 0 1 } } geometry Sphere { radius 1 } }";
 
      // Create and add the new node to the scene graph
 
      children.setValue( browser.createVrmlFromString( newvrml ) );
    }
  }

This example illustrates cycling between different cameras in a scene using the EAI. The VRML file contains a yellow cone with three Viewpoint nodes specified. The EAI script then continually binds each viewpoint in succession with a 1 second delay between each switch. The HTML segment for embedding this example in a web browser is as follows.

index.html

  <embed src="viewswitch.wrl" height="300" width="300">
  <applet code="viewswitch.class" mayscript height="1" width="1">
  </applet>
viewswitch.wrl
  #VRML V2.0 utf8
 
  DEF View1 Viewpoint {
     position 0 -3 6
     orientation 1 0 0 0.46
     description "Viewpoint 1"
  }
 
  DEF View2 Viewpoint {
     position 0 7 0
     orientation 0 -.707 -.707 3.1416
     description "Viewpoint 2"
  }
 
  DEF View3 Viewpoint {
     position 0 0 10
     orientation 0 0 1 0
     description "Viewpoint 3"
  }
 
  Shape {
     appearance Appearance {
        material DEF BoxMaterial Material {
          diffuseColor 1 1 0
        }
     }
     geometry Cone {}
  }
viewswitch.java
  import java.applet.*;
  import vrml.eai.field.*;
  import vrml.eai.Node;
  import vrml.eai.BrowserFactory;
  import vrml.eai.Browser;
 
  public class viewswitch extends Applet {
    public void init() {
      super.init();
    }
 
    public void start() {
      Browser browser = null;
      EventInSFBool bind1 = null;
      EventInSFBool bind2 = null;
      EventInSFBool bind3 = null;
 
      // Get the VRML Browser - try 10 times
 
      for (int count = 0; count < 10; count++) {
        browser = BrowserFactory.getBrowser(this);
        if (browser != null) break;
        try { Thread.sleep(200); } catch (InterruptedException e) {}
      }
 
      // Get the set_bind eventIns for the three DEF'd Viewpoint nodes
 
      try {
        Node view1 = browser.getNode("View1");
        Node view2 = browser.getNode("View2");
        Node view3 = browser.getNode("View3");
        bind1 = (EventInSFBool) view1.getEventIn("set_bind");
        bind2 = (EventInSFBool) view2.getEventIn("set_bind");
        bind3 = (EventInSFBool) view3.getEventIn("set_bind");
      } catch (vrml.eai.InvalidNodeException ignored) {}
 
      // cycle through each Viewpoint node at 1 sec intervals
 
      while (true) {
        try { Thread.sleep(1000); } catch (InterruptedException e) {}
        bind1.setValue(true);
        try { Thread.sleep(1000); } catch (InterruptedException e) {}
        bind2.setValue(true);
        try { Thread.sleep(1000); } catch (InterruptedException e) {}
        bind3.setValue(true);
      }
    }
  }

This next example shows how to perform scene graph traverals using the EAI. The script will search for all Switch nodes in a scene and set their whichChoice fields to a certain value. Two buttons are created in the applet's canvas to let the user set all Switch nodes to their first or second nodes. For the particular VRML file show here, this causes a switch between a purple cube and a cyan sphere. Note that we use the beginUpdate() and endUpdate() browser methods so that the scene graph is only updated once the traversal process has completed.

index.html

<APPLET CODE="switcher.class" HEIGHT="32" WIDTH="400" MAYSCRIPT>
</APPLET>
<EMBED SRC="switcher.wrl" WIDTH="400" HEIGHT="400">
 
switcher.wrl
  #VRML V2.0 utf8
 
  DEF RootNode Group {
     children [
        NavigationInfo { type [ "EXAMINE", "ANY" ] }
 
        Switch {
           whichChoice 0
           choice [
              Shape { # Switch 1
                 appearance Appearance { material
                    Material { diffuseColor 1 0 1 }
                 }
                 geometry Box { size 4 4 4 }
              }
              Shape { # Switch 2
                 appearance Appearance { material
                    Material { diffuseColor 0 1 1 }
                 }
                 geometry Sphere { radius 2 }
              }
           ]
        }
     ]
  }
switcher.java
  import java.awt.*;
  import java.applet.*;
  import vrml.eai.Node;
  import vrml.eai.BrowserFactory;
  import vrml.eai.Browser;
  import vrml.eai.field.*;
 
  public class switcher extends Applet {
    Browser browser = null;
    String  button1 = "Flick Switch 1";
    String  button2 = "Flick Switch 2";
 
    // create the two applet buttons and get the browser reference
 
    public void start() {
      setBackground(Color.white);
      add(new Button(button1));
      add(new Button(button2));
      browser = BrowserFactory.getBrowser(this);
    }
 
    // search scene graph for all Switch nodes and update their whichChoice
 
    public void set_switch(int value) {
      browser.beginUpdate();
      Node root = browser.getNode("RootNode");
      set_switch_recur((EventOutMFNode) root.getEventOut("children"), value);
      browser.endUpdate();
    }
 
    // recursive method to do the scene graph traversal
 
    public void set_switch_recur(EventOutMFNode children, int value) {
      if (children == null) return;
      Node nodes[]  = children.getValue();
      int num_nodes = nodes.length;
 
      for (int i = 0; i < num_nodes; ++i) {
        String node_type = nodes[i].getType();
 
        if (node_type.compareTo("Switch") == 0) {
 
          // Grab the whichChoice field of the Switch and change it
 
          EventInSFInt32 whichChoice = (EventInSFInt32)
            nodes[i].getEventIn("whichChoice");
 
          whichChoice.setValue(value);
 
        } else if (node_type.compareTo("Group") == 0 ||
                   node_type.compareTo("Transform") == 0 ||
                   node_type.compareTo("Collision") == 0) {
 
          // recurse into grouping nodes - other grouping nodes possible
 
          set_switch_recur((EventOutMFNode) nodes[i].getEventOut("children"),
                           value);
        }
      }
    }
 
    // The button event handling routine
 
    public boolean action(Event event, Object what) {
      if (event.target instanceof Button && browser != null) {
        Button b = (Button) event.target;
        if (b.getLabel() == button1) {
          set_switch(0);
        } else if (b.getLabel() == button2) {
          set_switch(1);
        }
      }
      return true;
    }
  }

This final example shows the creation of widgets in a Java applet that can be used to control items in the scene graph. Here the EAI is used to build a helix model using an Extrusion node and to animate this model. The applet then allows the user to change the number of coils in the helix. The HTML segment for embedding this example in a web browser is as follows.

Figure B.2 — Helix example

index.html

  <embed src="helix.wrl" border=0 height="200" width="200">
  <applet code="helix.class" mayscript height="100" width="200">
  </applet>
 
helix.wrl
  #VRML V2.0 utf8
 
  Viewpoint {
      position 0 4 5
      orientation 1 0 0 -0.5
  }
 
  Shape {
     appearance Appearance {
        material Material {
         diffuseColor 0.8 0.8 0.9
         shininess 1
        }
     }
     geometry DEF Coil Extrusion {
        crossSection []
        spine []
        creaseAngle 3.14
     }
  }
helix.java
  import java.awt.*;
  import java.applet.*;
  import vrml.eai.field.*;
  import vrml.eai.Node;
  import vrml.eai.BrowserFactory;
  import vrml.eai.Browser;
 
  public class helix extends Applet implements Runnable {
    EventInMFVec3f spine = null;
    EventInMFVec2f crossSection = null;
    Thread thread = null;
    Choice choice;
    int spineLimit = 250;
    float[][] spineValue = new float[spineLimit+1][3];
    int crossSectionLimit = 10;
    float[][] crossSectionValue = new float[crossSectionLimit+1][2];
    float numCoils = 5f;
 
    // set up the applet controls
 
    public void init() {
      super.init();
      setBackground(Color.white);
      Panel p1 = new Panel();
      Label lblNCoils = new Label("Number of Coils");
      p1.add(lblNCoils);
      choice= new Choice();
      choice.addItem("5"); choice.addItem("4"); choice.addItem("3");
      choice.addItem("2"); choice.addItem("1");
      p1.add(choice);
      add(p1);
    }
 
    public void start() {
      // get the VRML Browser reference
      Browser browser = null;
      for (int count = 0; count < 10; count++) {
        browser = BrowserFactory.getBrowser(this);
        if (browser != null) break;
        try { Thread.sleep (200); } catch (InterruptedException e) {}
      }
 
      if (browser == null) {
        throw new Error("Failed to get the browser after 10 tries!");     
      }
 
      // get the spine and crossSection fields of the Extrusion node
 
      try {
        Node coil = browser.getNode("Coil");
        spine = (EventInMFVec3f) coil.getEventIn("set_spine");
        crossSection = (EventInMFVec2f) coil.getEventIn("set_crossSection");
      } catch (vrml.eai.InvalidNodeException ne){
        System.out.println("Node Exception Error:" + ne.getMessage());
      }
 
      if (thread == null) {
        thread = new Thread(this);
        thread.start();
      } else
        thread.resume();
    }
 
    public void stop() {
      if (thread != null) thread.suspend();
    }
 
    public void destroy() {
      thread.stop();
      thread = null;
    }
 
    public void run() {
 
      // calculate and set the crossSection values of the Extrusion node
 
      float thickness = 0.1f;
      float diameter = 1.5f;
      float two_pi = (float) Math.PI * 2.0f;
      for (int j = 0; j <= crossSectionLimit; j++) {
        float angle = j * two_pi / crossSectionLimit;
        crossSectionValue[j][0] = thickness / 2 * (float) Math.sin(angle);
        crossSectionValue[j][1] = thickness / 2 * (float) Math.cos(angle);
      }
      crossSection.setValue(crossSectionValue);
 
      // oscilate the spring between 0.3 and 1, with 0.05 increments
 
      float inc = 0.05f;
      float value = 0.3f;
      float springLength = 2f;
      while (true) {
        value += inc;
 
        //calculate and set the coordinates for the whole spine
 
        for (int i = 0; i <= spineLimit; i++) {
          float stepsPerCoil = (float) Math.round(spineLimit / numCoils);
          float angle = i * two_pi / stepsPerCoil;
          spineValue[i][0] = diameter / 2 * (float) Math.cos(angle);
          spineValue[i][1] = springLength / numCoils * value * i / stepsPerCoil;
          spineValue[i][2] = diameter / 2 * (float) Math.sin(angle);
        }
        spine.setValue(spineValue);
 
        // sleep for 0.1 seconds
 
        try { thread.sleep(100); } catch (InterruptedException e) {}
 
        // reverse movement direction
 
        if (value >= 1f && inc == 0.05f)
          inc = -0.05f;
        else if (value <= 0.3 && inc == -0.05f)
          inc = 0.05f;        
      }
    }
  
    // handle input (deprecated Java API)
 
    public boolean handleEvent(Event event) {
      if (event.id == Event.ACTION_EVENT && event.target == choice) 
        changeNumCoils();
      return super.handleEvent(event);
    }
 
    // changes number of coils in the helix
 
    private void changeNumCoils() {
      String number = choice.getSelectedItem();
      numCoils = (new Float(number)).floatValue();
    }
  }

--- VRML separator bar ---