java left logo
java middle logo
java right logo
 

Home arrow Other API Tips
 
 
Main Menu
Home
Java Tutorials
Book Reviews
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Sitemap
Java Network
Java Forums
Java Tips Blog




Most Visited Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews
Top Rated Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews


Statistics
Registered Users: 769
Java SE Tips: 614
Java ME Tips: 201
Java EE Tips: 184
Other API Tips: 779
Java Applications: 298
Java Libraries: 209
Java Games: 16
Book Reviews:
 
 
 
Creating five sample behaviors and applies them to an object in a scene E-mail
User Rating: / 2
PoorBest 

This Java tip creates five sample behaviors and applies them to an object in a scene:

The behaviors are as follows:

  • Object Size - displays the size of the geometry in the object
  • Explode - explodes the geometry after 10 seconds
  • Stretch - allows the geometry to be stretched using the spacebar (simple physics)
  • Bounds - displays the bounds of the object
  • FPS - displays frames-per-seconds rendered


Image

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.GraphicsConfigTemplate;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.net.URL;

import javax.media.j3d.Alpha;
import javax.media.j3d.Appearance;
import javax.media.j3d.AudioDevice;
import javax.media.j3d.Background;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingBox;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.GraphicsConfigTemplate3D;
import javax.media.j3d.Group;
import javax.media.j3d.Locale;
import javax.media.j3d.Node;
import javax.media.j3d.PhysicalBody;
import javax.media.j3d.PhysicalEnvironment;
import javax.media.j3d.PointAttributes;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Switch;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TransparencyAttributes;
import javax.media.j3d.View;
import javax.media.j3d.ViewPlatform;
import javax.media.j3d.VirtualUniverse;
import javax.media.j3d.WakeupCondition;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnAWTEvent;
import javax.media.j3d.WakeupOnElapsedFrames;
import javax.media.j3d.WakeupOnElapsedTime;
import javax.media.j3d.WakeupOr;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import com.sun.j3d.audioengines.javasound.JavaSoundMixer;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.image.TextureLoader;

/**
 * Creates five sample behaviors and applies them to an object in a scene:
 <p>
 * 1. Object Size - displays the size of the geometry in the object 2. Explode -
 * explodes the geometry after 10 seconds 3. Stretch - allows the geometry to be
 * stretched using the spacebar (simple physics) 4. Bounds - displays the bounds
 * of the object 5. FPS - displays frames-per-seconds rendered
 */
public class BehaviorTest extends Java3dApplet implements ExplosionListener,
    ActionListener {
  private static int m_kWidth = 350;

  private static int m_kHeight = 400;

  private RotationInterpolator m_RotationInterpolator = null;

  private StretchBehavior m_StretchBehavior = null;

  private ObjectSizeBehavior m_SizeBehavior = null;

  private ExplodeBehavior m_ExplodeBehavior = null;

  private FpsBehavior m_FpsBehavior = null;

  private BoundsBehavior m_BoundsBehavior = null;

  public BehaviorTest() {
    initJava3d();

    Panel controlPanel = new Panel();

    Button rotateButton = new Button("Rotate");
    rotateButton.addActionListener(this);
    controlPanel.add(rotateButton);

    Button objSizeButton = new Button("Object Size");
    objSizeButton.addActionListener(this);
    controlPanel.add(objSizeButton);

    Button explodeButton = new Button("Explode");
    explodeButton.addActionListener(this);
    controlPanel.add(explodeButton);

    Button stretchButton = new Button("Stretch");
    stretchButton.addActionListener(this);
    controlPanel.add(stretchButton);

    Button boundsButton = new Button("Bounds");
    boundsButton.addActionListener(this);
    controlPanel.add(boundsButton);

    Button fpsButton = new Button("FPS");
    fpsButton.addActionListener(this);
    controlPanel.add(fpsButton);

    add(controlPanel, BorderLayout.SOUTH);
  }

  // handle event from the GUI components we created
  public void actionPerformed(ActionEvent event) {
    if (event.getActionCommand().equals("Object Size"!= false)
      m_SizeBehavior.setEnable(!m_SizeBehavior.getEnable());

    else if (event.getActionCommand().equals("Explode"!= false)
      m_ExplodeBehavior.setEnable(!m_ExplodeBehavior.getEnable());

    else if (event.getActionCommand().equals("Stretch"!= false)
      m_StretchBehavior.setEnable(!m_StretchBehavior.getEnable());

    else if (event.getActionCommand().equals("Rotate"!= false)
      m_RotationInterpolator.setEnable(!m_RotationInterpolator
          .getEnable());

    else if (event.getActionCommand().equals("Bounds"!= false)
      m_BoundsBehavior.setEnable(!m_BoundsBehavior.getEnable());

    else if (event.getActionCommand().equals("FPS"!= false)
      m_FpsBehavior.setEnable(!m_FpsBehavior.getEnable());
  }

  protected Background createBackground() {
    return null;
  }

  protected BranchGroup createSceneBranchGroup() {
    BranchGroup objRoot = super.createSceneBranchGroup();

    // create a TransformGroup to rotate the hand
    TransformGroup objTrans = new TransformGroup();
    objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);

    // create a RotationInterpolator behavior to rotate the hand
    Transform3D yAxis = new Transform3D();
    Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 00,
        400000000);

    m_RotationInterpolator = new RotationInterpolator(rotationAlpha,
        objTrans, yAxis, 0.0f(floatMath.PI * 2.0f);
    m_RotationInterpolator.setSchedulingBounds(createApplicationBounds());
    objTrans.addChild(m_RotationInterpolator);

    // create an Appearance and Material
    Appearance app = new Appearance();

    TextureLoader tex = new TextureLoader("earth.jpg"this);
    app.setTexture(tex.getTexture());

    Sphere sphere = new Sphere(3, Primitive.GENERATE_NORMALS
        | Primitive.GENERATE_TEXTURE_COORDS, 32, app);

    // connect the scenegraph
    objTrans.addChild(sphere);
    objRoot.addChild(objTrans);

    m_FpsBehavior = new FpsBehavior();
    m_FpsBehavior.setSchedulingBounds(getApplicationBounds());
    objRoot.addChild(m_FpsBehavior);

    m_BoundsBehavior = new BoundsBehavior(sphere);
    m_BoundsBehavior.setSchedulingBounds(getApplicationBounds());
    m_BoundsBehavior.addBehaviorToParentGroup(objTrans);

    m_StretchBehavior = new StretchBehavior((GeometryArraysphere
        .getShape().getGeometry());
    m_StretchBehavior.setSchedulingBounds(getApplicationBounds());
    objRoot.addChild(m_StretchBehavior);
    m_StretchBehavior.setEnable(false);

    m_SizeBehavior = new ObjectSizeBehavior((GeometryArraysphere
        .getShape().getGeometry());
    m_SizeBehavior.setSchedulingBounds(getApplicationBounds());
    objRoot.addChild(m_SizeBehavior);
    m_SizeBehavior.setEnable(false);

    m_ExplodeBehavior = new ExplodeBehavior(sphere.getShape()1000020,
        this);
    m_ExplodeBehavior.setSchedulingBounds(getApplicationBounds());
    objRoot.addChild(m_ExplodeBehavior);

    return objRoot;
  }

  public WakeupCondition onExplosionFinished(ExplodeBehavior explodeBehavior,
      Shape3D shape3D) {
    System.out.println("Explosion Finished.");
    return explodeBehavior.restart(shape3D, 1000020this);
  }

  public static void main(String[] args) {
    BehaviorTest behaviorTest = new BehaviorTest();
    behaviorTest.saveCommandLineArguments(args);

    new MainFrame(behaviorTest, m_kWidth, m_kHeight);
  }
}

//this class implements a simple behavior that
//output the rendered Frames Per Second.

class FpsBehavior extends Behavior {
  // the wake up condition for the behavior
  protected WakeupCondition m_WakeupCondition = null;

  protected long m_StartTime = 0;

  private final int m_knReportInterval = 100;

  public FpsBehavior() {
    // save the WakeupCriterion for the behavior
    m_WakeupCondition = new WakeupOnElapsedFrames(m_knReportInterval);
  }

  public void initialize() {
    // apply the initial WakeupCriterion
    wakeupOn(m_WakeupCondition);
  }

  public void processStimulus(java.util.Enumeration criteria) {
    while (criteria.hasMoreElements()) {
      WakeupCriterion wakeUp = (WakeupCriterioncriteria.nextElement();

      // every N frames, update position of the graphic
      if (wakeUp instanceof WakeupOnElapsedFrames) {
        if (m_StartTime > 0) {
          final long interval = System.currentTimeMillis()
              - m_StartTime;
          System.out.println("FPS: " (m_knReportInterval * 1000)
              / interval);
        }

        m_StartTime = System.currentTimeMillis();
      }
    }

    // assign the next WakeUpCondition, so we are notified again
    wakeupOn(m_WakeupCondition);
  }
}

//this class implements a simple behavior that
//displays a graphical representation of the Bounds
//of a Node.

class BoundsBehavior extends Behavior {
  // the wake up condition for the behavior
  protected WakeupCondition m_WakeupCondition = null;

  // the Node that we are tracking
  protected Node m_Node = null;

  protected TransformGroup m_TransformGroup = null;

  protected Switch m_BoundsSwitch = null;

  protected Transform3D m_Transform3D = null;

  protected Vector3d m_Scale = null;

  protected Vector3d m_Vector3d = null;

  protected Point3d m_Point3d1 = null;

  protected Point3d m_Point3d2 = null;

  private final int m_kSphereBounds = 0;

  private final int m_kBoxBounds = 1;

  public BoundsBehavior(Node node) {
    // save the GeometryArray that we are modifying
    m_Node = node;

    m_Transform3D = new Transform3D();
    m_Scale = new Vector3d();
    m_Vector3d = new Vector3d();
    m_Point3d1 = new Point3d();
    m_Point3d2 = new Point3d();

    // set the capability bits that the behavior requires
    m_Node.setCapability(Node.ALLOW_BOUNDS_READ);

    // save the WakeupCriterion for the behavior
    m_WakeupCondition = new WakeupOnElapsedFrames(10);
  }

  public void addBehaviorToParentGroup(Group nodeParentGroup) {
    nodeParentGroup.addChild(this);

    m_TransformGroup = new TransformGroup();
    m_TransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

    m_BoundsSwitch = new Switch();
    m_BoundsSwitch.setCapability(Switch.ALLOW_SWITCH_WRITE);

    Appearance app = new Appearance();

    PolygonAttributes polyAttrbutes = new PolygonAttributes();
    polyAttrbutes.setPolygonMode(PolygonAttributes.POLYGON_LINE);
    polyAttrbutes.setCullFace(PolygonAttributes.CULL_NONE);
    app.setPolygonAttributes(polyAttrbutes);

    m_BoundsSwitch.addChild(new Sphere(1, app));

    ColorCube cube = new ColorCube();
    cube.setAppearance(app);

    Group g = new Group();
    g.addChild(cube);
    m_BoundsSwitch.addChild(g);

    m_BoundsSwitch.setWhichChild(Switch.CHILD_NONE);

    m_TransformGroup.addChild(m_BoundsSwitch);
    nodeParentGroup.addChild(m_TransformGroup);
  }

  public void setEnable(boolean bEnable) {
    super.setEnable(bEnable);

    if (m_BoundsSwitch != null) {
      if (bEnable == false)
        m_BoundsSwitch.setWhichChild(Switch.CHILD_NONE);
    }
  }

  public void initialize() {
    // apply the initial WakeupCriterion
    wakeupOn(m_WakeupCondition);
  }

  public void processStimulus(java.util.Enumeration criteria) {
    while (criteria.hasMoreElements()) {
      WakeupCriterion wakeUp = (WakeupCriterioncriteria.nextElement();

      // every N frames, update position of the graphic
      if (wakeUp instanceof WakeupOnElapsedFrames) {
        if (m_TransformGroup != null) {
          Bounds bounds = m_Node.getBounds();

          int nBoundsType = m_kBoxBounds;
          m_Transform3D.setIdentity();

          if (bounds instanceof BoundingSphere) {
            nBoundsType = m_kSphereBounds;

            ((BoundingSpherebounds).getCenter(m_Point3d1);

            m_Vector3d.x = m_Point3d1.x;
            m_Vector3d.y = m_Point3d1.y;
            m_Vector3d.z = m_Point3d1.z;

            m_Scale.x = ((BoundingSpherebounds).getRadius() 2;
            m_Scale.y = m_Scale.x;
            m_Scale.z = m_Scale.y;

          else if (bounds instanceof BoundingBox) {
            nBoundsType = m_kBoxBounds;

            ((BoundingBoxbounds).getLower(m_Point3d1);
            ((BoundingBoxbounds).getUpper(m_Point3d2);

            m_Vector3d.x = (m_Point3d1.x + m_Point3d2.x2;
            m_Vector3d.y = (m_Point3d1.y + m_Point3d2.y2;
            m_Vector3d.z = (m_Point3d1.z + m_Point3d2.z2;

            m_Scale.x = Math.abs(m_Point3d1.x - m_Point3d2.x2;
            m_Scale.y = Math.abs(m_Point3d1.y - m_Point3d2.y2;
            m_Scale.z = Math.abs(m_Point3d1.z - m_Point3d2.z2;
          else
            System.err
                .println("BoundsBehavior found a Bounds it cannot represent: "
                    + bounds);

          m_Transform3D.setScale(m_Scale);
          m_Transform3D.setTranslation(m_Vector3d);

          m_TransformGroup.setTransform(m_Transform3D);

          m_BoundsSwitch.setWhichChild(nBoundsType);
        else {
          System.err
              .println("Call addBehaviorToParentGroup for BoundsBehavior.");
        }
      }
    }

    // assign the next WakeUpCondition, so we are notified again
    wakeupOn(m_WakeupCondition);
  }
}

class ExplodeBehavior extends Behavior {
  // the wake up condition for the behavior
  protected WakeupCondition m_InitialWakeupCondition = null;

  protected WakeupCondition m_FrameWakeupCondition = null;

  // the GeometryArray for the Shape3D that we are modifying
  protected Shape3D m_Shape3D = null;

  protected GeometryArray m_GeometryArray = null;

  protected float[] m_CoordinateArray = null;

  protected float[] m_OriginalCoordinateArray = null;

  protected Appearance m_Appearance = null;

  protected TransparencyAttributes m_TransparencyAttributes = null;

  protected int m_nElapsedTime = 0;

  protected int m_nNumFrames = 0;

  protected int m_nFrameNumber = 0;

  protected Vector3f m_Vector = null;

  ExplosionListener m_Listener = null;

  public ExplodeBehavior(Shape3D shape3D, int nElapsedTime, int nNumFrames,
      ExplosionListener listener) {
    // allocate a temporary vector
    m_Vector = new Vector3f();

    m_FrameWakeupCondition = new WakeupOnElapsedFrames(1);

    restart(shape3D, nElapsedTime, nNumFrames, listener);
  }

  public WakeupCondition restart(Shape3D shape3D, int nElapsedTime,
      int nNumFrames, ExplosionListener listener) {
    System.out.println("Will explode after: " + nElapsedTime / 1000
        " secs.");

    m_Shape3D = shape3D;
    m_nElapsedTime = nElapsedTime;
    m_nNumFrames = nNumFrames;
    m_nFrameNumber = 0;

    // create the WakeupCriterion for the behavior
    m_InitialWakeupCondition = new WakeupOnElapsedTime(m_nElapsedTime);

    m_Listener = listener;

    // save the GeometryArray that we are modifying
    m_GeometryArray = (GeometryArraym_Shape3D.getGeometry();

    if (m_Shape3D.isLive() == false && m_Shape3D.isCompiled() == false) {
      // set the capability bits that the behavior requires
      m_Shape3D.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
      m_Shape3D.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);

      m_Shape3D.getAppearance().setCapability(
          Appearance.ALLOW_POINT_ATTRIBUTES_WRITE);
      m_Shape3D.getAppearance().setCapability(
          Appearance.ALLOW_POLYGON_ATTRIBUTES_WRITE);
      m_Shape3D.getAppearance().setCapability(
          Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_WRITE);
      m_Shape3D.getAppearance().setCapability(
          Appearance.ALLOW_TEXTURE_WRITE);

      m_GeometryArray.setCapability(GeometryArray.ALLOW_COORDINATE_READ);
      m_GeometryArray.setCapability(GeometryArray.ALLOW_COORDINATE_WRITE);
      m_GeometryArray.setCapability(GeometryArray.ALLOW_COUNT_READ);
    }

    // make a copy of the object's original appearance
    m_Appearance = new Appearance();
    m_Appearance = (Appearancem_Shape3D.getAppearance()
        .cloneNodeComponent(true);

    // allocate an array for the model coordinates
    m_CoordinateArray = new float[* m_GeometryArray.getVertexCount()];

    // make a copy of the models original coordinates
    m_OriginalCoordinateArray = new float[* m_GeometryArray
        .getVertexCount()];
    m_GeometryArray.getCoordinates(0, m_OriginalCoordinateArray);

    // start (or restart) the behavior
    setEnable(true);

    return m_InitialWakeupCondition;
  }

  public void initialize() {
    // apply the initial WakeupCriterion
    wakeupOn(m_InitialWakeupCondition);
  }

  public void processStimulus(java.util.Enumeration criteria) {
    while (criteria.hasMoreElements()) {
      WakeupCriterion wakeUp = (WakeupCriterioncriteria.nextElement();

      if (wakeUp instanceof WakeupOnElapsedTime) {
        // we are starting the explosion, apply the
        // appearance changes we require
        PolygonAttributes polyAttribs = new PolygonAttributes(
            PolygonAttributes.POLYGON_POINT,
            PolygonAttributes.CULL_NONE, 0);
        m_Shape3D.getAppearance().setPolygonAttributes(polyAttribs);

        PointAttributes pointAttribs = new PointAttributes(3false);
        m_Shape3D.getAppearance().setPointAttributes(pointAttribs);

        m_Shape3D.getAppearance().setTexture(null);

        m_TransparencyAttributes = new TransparencyAttributes(
            TransparencyAttributes.NICEST, 0);
        m_TransparencyAttributes
            .setCapability(TransparencyAttributes.ALLOW_VALUE_WRITE);
        m_Shape3D.getAppearance().setTransparencyAttributes(
            m_TransparencyAttributes);
      else {
        // we are mid explosion, modify the GeometryArray
        m_nFrameNumber++;

        m_GeometryArray.getCoordinates(0, m_CoordinateArray);

        m_TransparencyAttributes
            .setTransparency(((floatm_nFrameNumber)
                ((floatm_nNumFrames));
        m_Shape3D.getAppearance().setTransparencyAttributes(
            m_TransparencyAttributes);

        for (int n = 0; n < m_CoordinateArray.length; n += 3) {
          m_Vector.x = m_CoordinateArray[n];
          m_Vector.y = m_CoordinateArray[n + 1];
          m_Vector.z = m_CoordinateArray[n + 2];

          m_Vector.normalize();

          m_CoordinateArray[n+= m_Vector.x * Math.random()
              + Math.random();
          m_CoordinateArray[n + 1+= m_Vector.y * Math.random()
              + Math.random();
          m_CoordinateArray[n + 2+= m_Vector.z * Math.random()
              + Math.random();
        }

        // assign the new coordinates
        m_GeometryArray.setCoordinates(0, m_CoordinateArray);
      }
    }

    if (m_nFrameNumber < m_nNumFrames) {
      // assign the next WakeUpCondition, so we are notified again
      wakeupOn(m_FrameWakeupCondition);
    else {
      // we are at the end of the explosion
      // reapply the original appearance and GeometryArray
      // coordinates
      setEnable(false);
      m_Shape3D.setAppearance(m_Appearance);

      m_GeometryArray.setCoordinates(0, m_OriginalCoordinateArray);

      m_OriginalCoordinateArray = null;
      m_GeometryArray = null;
      m_CoordinateArray = null;
      m_TransparencyAttributes = null;

      // if we have a listener notify them that we are done
      if (m_Listener != null)
        wakeupOn(m_Listener.onExplosionFinished(this, m_Shape3D));
    }
  }
}

interface ExplosionListener {
  abstract public WakeupCondition onExplosionFinished(
      ExplodeBehavior explodeBehavior, Shape3D shape3D);
}

//this class implements a simple behavior that
//calculates and prints the size of an object
//based on the vertices in its GeometryArray

class ObjectSizeBehavior extends Behavior {
  // the wake up condition for the behavior
  protected WakeupCondition m_WakeupCondition = null;

  // the GeometryArray for the Shape3D that we are querying
  protected GeometryArray m_GeometryArray = null;

  // cache some information on the model to save reallocation
  protected float[] m_CoordinateArray = null;

  protected BoundingBox m_BoundingBox = null;

  protected Point3d m_Point = null;;

  public ObjectSizeBehavior(GeometryArray geomArray) {
    // save the GeometryArray that we are modifying
    m_GeometryArray = geomArray;

    // set the capability bits that the behavior requires
    m_GeometryArray.setCapability(GeometryArray.ALLOW_COORDINATE_READ);
    m_GeometryArray.setCapability(GeometryArray.ALLOW_COUNT_READ);

    // allocate an array for the coordinates
    m_CoordinateArray = new float[* m_GeometryArray.getVertexCount()];

    // create the BoundingBox used to
    // calculate the size of the object
    m_BoundingBox = new BoundingBox();

    // create a temporary point
    m_Point = new Point3d();

    // create the WakeupCriterion for the behavior
    WakeupCriterion criterionArray[] new WakeupCriterion[1];
    criterionArray[0new WakeupOnElapsedFrames(20);

    // save the WakeupCriterion for the behavior
    m_WakeupCondition = new WakeupOr(criterionArray)