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.