Extensible 3D (X3D) language bindings
Part 1: 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:
Table D.1 — Topics in this annex
D.1 Introduction and table of contents |
This example demonstrates a scripted response to a TouchSensor isOver event by changing the color of a Box from blue to red:
#X3D V3.0 utf8 Group { children [ Shape { appearance Appearance { material MAT Material { diffuseColor 0 0 1 } } geometry Box {} } DEF TS TouchSensor {} ] } DEF SC Script { inputOnly SFBool isOver outputOnly SFColor diffuseColor_changed url ["SAIExample1.class"] } ROUTE TS.isOver TO SC.isOver ROUTE SC.diffuseColor_changed TO MAT.set_diffuseColor
// 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:
#X3D V3.0 utf8 DEF HOLDER Transform { translation -2 0 0 } DEF SC Script { outputOnly MFNode children url ["SAIExample2.class"] } ROUTE SC.children1 TO HOLDER.children
// 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:
#X3D V3.0 utf8 DEF SC Script { url ["SAIExample3.class"] }
// 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:
#X3D V3.0 utf8 DEF SC Script { inputOnly SFTime touchTime url ["SAIExample4.class"] }
// 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:
#X3D V3.0 utf8 PROTO ColoredSphere [ initializeOnly SFColor color ] { Shape { appearance Appearance { material Material { diffuseColor IS color } } geometry Sphere {} } } DEF SC Script { url ["SAIExample5.class"] }
// 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.