Extensible 3D (X3D) language bindings
Part 2: Java
Annex D
(informative)
Examples
This annex provides a variety of X3D examples showing ECMAScript operations.
Table D.1 contains a table of contents that lists the topics in this clause:
This example demonstrates a scripted response to a TouchSensor isOver event by changing the color of a Box from blue to red:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd">
<X3D profile="Immersive">
<head>
<meta content="TouchSensorIsOverEvent.x3d" name="filename"/>
<meta content="Xeena VRML importer" name="translator"/>
<meta content="23 February 2005" name="imported"/>
<meta content="23 February 2005" name="revised"/>
<meta
content="X3D-Edit, http://www.web3D.org/TaskGroups/x3d/translation/README.X3D-Edit.html" name="generator"/>
<meta content="Vrml97ToX3dNist, http://ovrt.nist.gov/v2_x3d.html" name="generator"/>
</head>
<Scene>
<Group>
<Shape>
<Appearance>
<Material DEF="MAT" diffuseColor="0 0 1"/>
</Appearance>
<Box/>
</Shape>
<TouchSensor DEF="TS"/>
</Group>
<Script DEF="SC" url=""SAIExample1.class" ">
<field accessType="inputOnly" name="isOver" type="SFBool"/>
<field accessType="outputOnly" name="diffuseColor_changed" type="SFColor"/>
</Script>
<ROUTE fromField="isOver" fromNode="TS" toField="isOver" toNode="SC"/>
<ROUTE fromField="diffuseColor_changed" fromNode="SC"
toField="set_diffuseColor" toNode="MAT"/>
</Scene>
</X3D>
// Standard imports
import java.util.Map;
// Application specific imports
import org.web3d.x3d.sai.*;
public class SAIExample1
implements X3DScriptImplementation, X3DFieldEventListener {
/** Color Constant, RED */
private static final float[] RED = new float[] {1.0f, 0, 0};
/** Color Constant, BLUE */
private static final float[] BLUE = new float[] {0, 0, 1.0f};
/** A mapping for fieldName(String) to an X3DField object */
private Map fields;
/** The isOver field */
private SFBool isOver;
/** The diffuseColor_changed field */
private SFColor diffuseColor;
//----------------------------------------------------------
// Methods from the X3DScriptImplementation interface.
//----------------------------------------------------------
/**
* Set the browser instance to be used by this script implementation.
*
* @param browser The browser reference to keep
*/
public void setBrowser(Browser browser) {
}
/**
* Set the listing of fields that have been declared in the file for
* this node. .
*
* @param The external view of ourselves, so you can add routes to yourself
* using the standard API calls
* @param fields The mapping of field names to instances
*/
public void setFields(X3DScriptNode externalView, Map fields) {
this.fields = fields;
}
/**
* Notification that the script has completed the setup and should go
* about its own internal initialization.
*/
public void initialize() {
isOver = (SFBool) fields.get("isOver");
diffuseColor = (SFColor) fields.get("diffuseColor_changed");
// Listen to events on isOver
isOver.addX3DEventListener(this);
}
/**
* Notification that this script instance is no longer in use by the
* scene graph and should now release all resources.
*/
public void shutdown() {
}
/**
* Notification that all the events in the current cascade have finished
* processing.
*/
public void eventsProcessed() {
}
//----------------------------------------------------------
// Methods from the X3DFieldEventListener interface.
//----------------------------------------------------------
/**
* Handle field changes.
*
* @param evt The field event
*/
public void readableFieldChanged(X3DFieldEvent evt) {
if (evt.getSource() == isOver) {
if (isOver.getValue() == true)
diffuseColor.setValue(RED);
else
diffuseColor.setValue(BLUE);
} else {
System.out.println("Unhandled event: " + evt);
}
}
}
Click here to view this example in a 3D scene window.
This example shows using createX3DFromString to create nodes:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd">
<X3D profile="Immersive">
<head>
<meta content="CreateNodes.x3d" name="filename"/>
<meta content="Xeena VRML importer" name="translator"/>
<meta content="*enter date of initial version here*" name="created"/>
<meta content="23 February 2005" name="imported"/>
<meta content="23 February 2005" name="revised"/>
<meta
content="X3D-Edit, http://www.web3D.org/TaskGroups/x3d/translation/README.X3D-Edit.html" name="generator"/>
<meta content="Vrml97ToX3dNist, http://ovrt.nist.gov/v2_x3d.html" name="generator"/>
</head>
<Scene>
<Transform DEF="HOLDER" translation="-2.0 0.0 0.0"/>
<Script DEF="SC" url="SAIExample.class">
<field accessType="outputOnly" name="children" type="MFNode"/>
</Script>
<ROUTE fromField="children" fromNode="SC" toField="children" toNode="HOLDER"/>
</Scene>
</X3D>
// Standard imports
import java.util.Map;
// Application specific imports
import org.web3d.x3d.sai.*;
public class SAIExample2
implements X3DScriptImplementation {
/** Color Constant, RED */
private static final float[] RED = new float[] {1.0f, 0, 0};
/** A mapping for fieldName(String) to an X3DField object */
private Map fields;
/** A reference to the browser */
private Browser browser;
/** The field to place the generated nodes via createX3DFromString */
private MFNode children;
//----------------------------------------------------------
// Methods from the X3DScriptImplementation interface.
//----------------------------------------------------------
/**
* Set the browser instance to be used by this script implementation.
*
* @param browser The browser reference to keep
*/
public void setBrowser(Browser browser) {
this.browser = browser;
}
/**
* Set the listing of fields that have been declared in the file for
* this node. .
*
* @param The external view of ourselves, so you can add routes to yourself
* using the standard API calls
* @param fields The mapping of field names to instances
*/
public void setFields(X3DScriptNode externalView, Map fields) {
this.fields = fields;
}
/**
* Notification that the script has completed the setup and should go
* about its own internal initialization.
*/
public void initialize() {
children = (MFNode) fields.get("children");
// Create nodes directly in the parent scene
X3DScene scene = (X3DScene) browser.getExecutionContext();
X3DShapeNode shape = (X3DShapeNode) scene.createNode("Shape");
X3DGeometryNode box = (X3DGeometryNode) scene.createNode("Box");
shape.setGeometry(box);
scene.addRootNode(shape);
// Create children using the createX3DFromString service
String vrmlCmd =
"PROFILE Interchange Shape { geometry Sphere{} }";
X3DScene tmpScene = browser.createX3DFromString(vrmlCmd);
X3DNode[] nodes = tmpScene.getRootNodes();
// Nodes must be removed before adding to another scene
for(int i=0; i < nodes.length; i++) {
tmpScene.removeRootNode(nodes[i]);
}
children.setValue(nodes.length,nodes);
}
/**
* Notification that this script instance is no longer in use by the
* scene graph and should now release all resources.
*/
public void shutdown() {
}
/**
* Notification that all the events in the current cascade have finished
* processing.
*/
public void eventsProcessed() {
}
}
Click here to view this example in a 3D scene window.
This example shows how to use per frame notification to produce a frame rate annotation:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "http://www.web3d.org/specifications/x3d-3.0.dtd"
"file:///www.web3d.org/TaskGroups/x3d/translation/x3d-3.0.dtd">
<X3D profile="Immersive">
<head>
<meta content="PerFrameNotification.x3d" name="filename"/>
<meta content="Xeena VRML importer" name="translator"/>
<meta content="23 February 2005" name="imported"/>
<meta content="23 February 2005" name="revised"/>
<meta
content="X3D-Edit, http://www.web3D.org/TaskGroups/x3d/translation/README.X3D-Edit.html" name="generator"/>
<meta content="Vrml97ToX3dNist, http://ovrt.nist.gov/v2_x3d.html" name="generator"/>
</head>
<Scene>
<Script DEF="SC" url=""SAIExample3.class" "/>
</Scene>
</X3D>
// Standard imports
import java.util.Map;
// Application specific imports
import org.web3d.x3d.sai.*;
public class SAIExample3
implements X3DPerFrameObserverScript {
/** When did the last frame start */
private long lastStartTime;
//----------------------------------------------------------
// Methods from the X3DScriptImplementation interface.
//----------------------------------------------------------
/**
* Set the browser instance to be used by this script implementation.
*
* @param browser The browser reference to keep
*/
public void setBrowser(Browser browser) {
}
/**
* Set the listing of fields that have been declared in the file for
* this node. .
*
* @param The external view of ourselves, so you can add routes to yourself
* using the standard API calls
* @param fields The mapping of field names to instances
*/
public void setFields(X3DScriptNode externalView, Map fields) {
}
/**
* Notification that the script has completed the setup and should go
* about its own internal initialization.
*/
public void initialize() {
lastStartTime = System.currentTimeMillis();
}
/**
* Notification that this script instance is no longer in use by the
* scene graph and should now release all resources.
*/
public void shutdown() {
}
/**
* Notification that all the events in the current cascade have finished
* processing.
*/
public void eventsProcessed() {
}
//----------------------------------------------------------
// Methods from the X3DPerFrameObserver interface.
//----------------------------------------------------------
/**
* Start of frame notification.
*/
public void prepareEvents() {
float frameTime = (System.currentTimeMillis() - lastStartTime) / 1000f;
lastStartTime = System.currentTimeMillis();
float fps = 1.0f / frameTime;
System.out.println("FPS: " + fps);
}
}
Click here to view this example in a 3D scene window.
This example shows adding dynamic routes:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd">
<X3D profile="Immersive">
<Scene>
<Script DEF="SC" url="SAIExample4.class">
<field accessType="inputOnly" name="touchTime" type="SFTime"/>
</Script>
</Scene>
</X3D>
// Standard imports
import java.util.Map;
// Application specific imports
import org.web3d.x3d.sai.*;
public class SAIExample4
implements X3DScriptImplementation, X3DFieldEventListener {
/** A mapping for fieldName(String) to an X3DField object */
private Map fields;
/** A reference to the browser */
private Browser browser;
/** inputOnly touchTime */
private SFTime touchTime;
/** initializeOnly selfRef */
private X3DScriptNode selfRef;
//----------------------------------------------------------
// Methods from the X3DScriptImplementation interface.
//----------------------------------------------------------
/**
* Set the browser instance to be used by this script implementation.
*
* @param browser The browser reference to keep
*/
public void setBrowser(Browser browser) {
this.browser = browser;
}
/**
* Set the listing of fields that have been declared in the file for
* this node. .
*
* @param The external view of ourselves, so you can add routes to yourself
* using the standard API calls
* @param fields The mapping of field names to instances
*/
public void setFields(X3DScriptNode externalView, Map fields) {
this.fields = fields;
selfRef = externalView;
}
/**
* Notification that the script has completed the setup and should go
* about its own internal initialization.
*/
public void initialize() {
touchTime = (SFTime) fields.get("touchTime");
// Listen to events on touchTime
touchTime.addX3DEventListener(this);
// Create nodes directly in the parent scene
X3DScene scene = (X3DScene) browser.getExecutionContext();
X3DShapeNode shape = (X3DShapeNode) scene.createNode("Shape");
X3DGeometryNode box = (X3DGeometryNode) scene.createNode("Box");
X3DNode touchSensor = scene.createNode("TouchSensor");
shape.setGeometry(box);
// Create a Group to hold the nodes
X3DGroupingNode group = (X3DGroupingNode) scene.createNode("Group");
// Add the shape and sensor to the group
group.addChild(shape);
group.addChild(touchSensor);
// Add the nodes to the scene
scene.addRootNode(group);
// Get a handle to the toplevel execution context
scene.addRoute(touchSensor,"touchTime", selfRef, "touchTime");
}
/**
* Notification that this script instance is no longer in use by the
* scene graph and should now release all resources.
*/
public void shutdown() {
}
/**
* Notification that all the events in the current cascade have finished
* processing.
*/
public void eventsProcessed() {
}
//----------------------------------------------------------
// Methods from the X3DFieldEventListener interface.
//----------------------------------------------------------
/**
* Handle field changes.
*
* @param evt The field event
*/
public void readableFieldChanged(X3DFieldEvent evt) {
if (evt.getSource() == touchTime) {
System.out.println("Poke!");
} else {
System.out.println("Unhandled event: " + evt);
}
}
}
Click here to view this example in a 3D scene window.
This example shows creation of nodes from a prototype:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd">
<X3D profile="Immersive">
<Scene>
<ProtoDeclare name="ColoredSphere">
<ProtoInterface>
<field accessType="initializeOnly" name="color" type="SFColor" value="0.0 0.0 0.0"/>
</ProtoInterface>
<ProtoBody>
<Shape>
<Appearance>
<Material>
<IS>
<connect nodeField="diffuseColor" protoField="color"/>
</IS>
</Material>
</Appearance>
<Sphere/>
</Shape>
</ProtoBody>
</ProtoDeclare>
<Script DEF="SC" url="SAIExample5.class"/>
</Scene>
</X3D>
// Standard imports
import java.util.Map;
// Application specific imports
import org.web3d.x3d.sai.*;
public class SAIExample5
implements X3DScriptImplementation {
/** Color Constant, RED */
private static final float[] RED = new float[] {1.0f, 0, 0};
/** A mapping for fieldName(String) to an X3DField object */
private Map fields;
/** A reference to the browser */
private Browser browser;
/** The field to place the generated nodes via createX3DFromString */
private MFNode children;
//----------------------------------------------------------
// Methods from the X3DScriptImplementation interface.
//----------------------------------------------------------
/**
* Set the browser instance to be used by this script implementation.
*
* @param browser The browser reference to keep
*/
public void setBrowser(Browser browser) {
this.browser = browser;
}
/**
* Set the listing of fields that have been declared in the file for
* this node. .
*
* @param The external view of ourselves, so you can add routes to yourself
* using the standard API calls
* @param fields The mapping of field names to instances
*/
public void setFields(X3DScriptNode externalView, Map fields) {
this.fields = fields;
}
/**
* Notification that the script has completed the setup and should go
* about its own internal initialization.
*/
public void initialize() {
// Create nodes directly in the parent scene
X3DScene scene = (X3DScene) browser.getExecutionContext();
// Create protoInstance nodes
// Get the proto declaration declared in the main scene
X3DProtoDeclaration protoDecl = scene.getProto("ColoredSphere");
// Create a new instance of this proto
X3DProtoInstance instance = protoDecl.createInstance();
// Get the color field and set it to red
SFColor color = (SFColor) instance.getField("color");
color.setValue(RED);
// Add the created proto instance to the scene
scene.addRootNode(instance);
}
/**
* Notification that this script instance is no longer in use by the
* scene graph and should now release all resources.
*/
public void shutdown() {
}
/**
* Notification that all the events in the current cascade have finished
* processing.
*/
public void eventsProcessed() {
}
}
Click here to view this example in a 3D scene window.