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.