Extensible 3D (X3D) language bindings
Part 2:  Java

Annex D

(informative)

Examples

--- X3D separator bar ---

cube D.1 Introduction and topics

D.1.1 Introduction

This annex provides a variety of X3D examples showing ECMAScript operations.

D.1.2 Topics

Table D.1 contains a table of contents that lists the topics in this clause:

Table D.1 — Topics in this annex

--- X3D separator bar ---

cube D.2 TouchSensor isOver event

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="&quot;SAIExample1.class&quot; ">
      <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.

--- X3D separator bar ---

cube D.3 Create nodes

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.

--- X3D separator bar ---

cube D.4 Per frame notification

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="&quot;SAIExample3.class&quot; "/>
  </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.

--- X3D separator bar ---

cube D.5 Add dynamic routes

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.

--- X3D separator bar ---

cube D.6 Create nodes from a prototype

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.

--- X3D separator bar ---