Java/3D/Mouse Keyboard Action

Материал из Java эксперт
Перейти к: навигация, поиск

Class Drag

   <source lang="java">

/*

*  @(#)Drag.java 1.14 98/04/13 13:07:16
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/

import com.sun.j3d.utils.behaviors.mouse.MouseRotate; import com.sun.j3d.utils.behaviors.mouse.MouseZoom; import com.sun.j3d.utils.behaviors.mouse.MouseTranslate; import java.applet.*; import java.awt.*; import java.io.*; import java.net.*; import java.awt.BorderLayout; import java.awt.event.*; import javax.media.j3d.*; import javax.vecmath.*; import com.sun.j3d.utils.universe.*; /**

* Class Drag
*
* Author Jim Argabright
* Date   11/24/97
*/

public class Drag extends Applet {

  boolean appletFlag = true;
  /**
   * Sets the "applet" flag which is used to determine 
   * whether or not this program is running as an applet.
   */
  public void setAppletFlag(boolean flag) {
     appletFlag = flag;
  }
  /**
   *  Create the scenegraph for this program.
   */
  public BranchGroup createSceneGraph() {
       // Define colors
       Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
       Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
       Color3f red   = new Color3f(0.80f, 0.20f, 0.2f);
       Color3f ambientRed = new Color3f(0.2f, 0.05f, 0.0f);
       Color3f ambient = new Color3f(0.2f, 0.2f, 0.2f);
       Color3f diffuse = new Color3f(0.7f, 0.7f, 0.7f);
       Color3f specular = new Color3f(0.7f, 0.7f, 0.7f);
 Color3f bgColor = new Color3f(0.05f, 0.05f, 0.2f);
       // Create the branch group
 BranchGroup branchGroup = new BranchGroup();
       // Create a Transformgroup to scale all objects so they
       // appear in the scene.
       TransformGroup objScale = new TransformGroup();
       Transform3D t3d = new Transform3D();
       t3d.setScale(0.4);
       objScale.setTransform(t3d);
       branchGroup.addChild(objScale);
       // Create the bounding leaf node
 BoundingSphere bounds = 
          new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
       BoundingLeaf boundingLeaf = new BoundingLeaf(bounds);
       objScale.addChild(boundingLeaf);
 // Set up the background
 Background bg = new Background(bgColor);
 bg.setApplicationBounds(bounds);
 objScale.addChild(bg);
       // Create the ambient light
       AmbientLight ambLight = new AmbientLight(white);
       ambLight.setInfluencingBounds(bounds);
       objScale.addChild(ambLight);
       // Create the directional light
       Vector3f dir = new Vector3f(-1.0f, -1.0f, -1.0f);
       DirectionalLight dirLight = new DirectionalLight(white, dir);
       dirLight.setInfluencingBounds(bounds);
       objScale.addChild(dirLight);
    
       // Create the red appearance node
       Material redMaterial = 
          new Material(ambientRed, black, red, specular, 75.0f);
       redMaterial.setLightingEnable(true);
       Appearance redAppearance = new Appearance();
       redAppearance.setMaterial(redMaterial);
       // Create the white appearance node
       Material whiteMaterial = 
          new Material(ambient, black, diffuse, specular, 75.0f);
       whiteMaterial.setLightingEnable(true);
       Appearance whiteAppearance = new Appearance();
       whiteAppearance.setMaterial(whiteMaterial);
       // Create the transform node
 TransformGroup transformGroup = new TransformGroup();
 transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
 transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
 transformGroup.addChild(new Cube(redAppearance).getChild());

// transformGroup.addChild(new Corners(whiteAppearance).getChild());

 objScale.addChild(transformGroup);
 
 // Create the drag behavior node
 MouseRotate behavior = new MouseRotate();
 behavior.setTransformGroup(transformGroup);
 transformGroup.addChild(behavior);
 behavior.setSchedulingBounds(bounds);
 
 // Create the zoom behavior node
 MouseZoom behavior2 = new MouseZoom();
 behavior2.setTransformGroup(transformGroup);
 transformGroup.addChild(behavior2);
 behavior2.setSchedulingBounds(bounds);
 
 // Create the zoom behavior node
 MouseTranslate behavior3 = new MouseTranslate();
 behavior3.setTransformGroup(transformGroup);
 transformGroup.addChild(behavior3);
 behavior3.setSchedulingBounds(bounds);
       // Let Java 3D perform optimizations on this scene graph.
       branchGroup.rupile();
 return branchGroup;
   }
   /**
    * Calls the various methods necessary to initialize the 
    * program.
    */
   public void init() {
       // Set the layout manager
 setLayout(new BorderLayout());
       // Create the 3D canvas
 Canvas3D canvas = new Canvas3D(null);
 add("Center", canvas);
 // Create the scene branch graph
 BranchGroup scene = createSceneGraph();
 // Create the Universe, the Locale, and the view branch graph
 SimpleUniverse u = new SimpleUniverse(canvas);
       // This will move the ViewPlatform back a bit so the
       // objects in the scene can be viewed.
       u.getViewingPlatform().setNominalViewingTransform();
 u.addBranchGraph(scene);
  }
   /**
    *  Inner class used to "kill" the window when running as
    *  an application.
    */
   static class killAdapter extends WindowAdapter {
      public void windowClosing(WindowEvent event) {
         System.exit(0);
      }
   }
   /**
    *  Used when running as an application.
    */
   public static void main(String[] args) {
      Drag drag = new Drag();
      drag.setAppletFlag(false);
      drag.init();
      Frame frame = new Frame("Drag the mouse in the window");
      frame.setSize(640, 480);
      frame.add("Center", drag);
      frame.addWindowListener(new killAdapter());
      frame.setVisible(true);
   }

} /*

*  @(#)Cube.java 1.3 98/02/20 14:30:08
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/

class Cube extends Object {

  private Shape3D shape3D;
  private static final float[] verts = {
  // Front Face
     1.0f, -1.0f,  1.0f,     1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,    -1.0f, -1.0f,  1.0f,
  // Back Face
    -1.0f, -1.0f, -1.0f,    -1.0f,  1.0f, -1.0f,
     1.0f,  1.0f, -1.0f,     1.0f, -1.0f, -1.0f,
  // Right Face
     1.0f, -1.0f, -1.0f,     1.0f,  1.0f, -1.0f,
     1.0f,  1.0f,  1.0f,     1.0f, -1.0f,  1.0f,
  // Left Face
    -1.0f, -1.0f,  1.0f,    -1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f, -1.0f,    -1.0f, -1.0f, -1.0f,
  // Top Face
     1.0f,  1.0f,  1.0f,     1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,    -1.0f,  1.0f,  1.0f,
  // Bottom Face
    -1.0f, -1.0f,  1.0f,    -1.0f, -1.0f, -1.0f,
     1.0f, -1.0f, -1.0f,     1.0f, -1.0f,  1.0f,
  };
  private static final float[] normals = {
  // Front Face
     0.0f,  0.0f,  1.0f,     0.0f,  0.0f,  1.0f,
     0.0f,  0.0f,  1.0f,     0.0f,  0.0f,  1.0f,
  // Back Face
     0.0f,  0.0f, -1.0f,     0.0f,  0.0f, -1.0f,
     0.0f,  0.0f, -1.0f,     0.0f,  0.0f, -1.0f,
  // Right Face
     1.0f,  0.0f,  0.0f,     1.0f,  0.0f,  0.0f,
     1.0f,  0.0f,  0.0f,     1.0f,  0.0f,  0.0f,
  // Left Face
    -1.0f,  0.0f,  0.0f,    -1.0f,  0.0f,  0.0f,
    -1.0f,  0.0f,  0.0f,    -1.0f,  0.0f,  0.0f,
  // Top Face
     0.0f,  1.0f,  0.0f,     0.0f,  1.0f,  0.0f,
     0.0f,  1.0f,  0.0f,     0.0f,  1.0f,  0.0f,
  // Bottom Face
     0.0f, -1.0f,  0.0f,     0.0f, -1.0f,  0.0f,
     0.0f, -1.0f,  0.0f,     0.0f, -1.0f,  0.0f,
  };
  private static final float[] textCoords = {
  // Front Face
     1.0f,  0.0f,            1.0f,  1.0f,
     0.0f,  1.0f,            0.0f,  0.0f,
  // Back Face
     1.0f,  0.0f,            1.0f,  1.0f,
     0.0f,  1.0f,            0.0f,  0.0f,
  // Right Face
     1.0f,  0.0f,            1.0f,  1.0f,
     0.0f,  1.0f,            0.0f,  0.0f,
  // Left Face
     1.0f,  0.0f,            1.0f,  1.0f,
     0.0f,  1.0f,            0.0f,  0.0f,
  // Top Face
     1.0f,  0.0f,            1.0f,  1.0f,
     0.0f,  1.0f,            0.0f,  0.0f,
  // Bottom Face
     1.0f,  0.0f,            1.0f,  1.0f,
     0.0f,  1.0f,            0.0f,  0.0f
  };
  public Cube(Appearance appearance) {
     QuadArray quadArray = new QuadArray(24, QuadArray.COORDINATES | 
                                             QuadArray.NORMALS |
                                             QuadArray.TEXTURE_COORDINATE_2);
     quadArray.setCoordinates(0, verts);
     quadArray.setNormals(0, normals);
     quadArray.setTextureCoordinates(0, textCoords);
     shape3D = new Shape3D(quadArray, appearance);
  }
  public Shape3D getChild() {
     return shape3D;
  }

}


      </source>
   
  
 
  



Demonstrate the use of the mouse utility classes

   <source lang="java">

/* Essential Java 3D Fast Ian Palmer Publisher: Springer-Verlag ISBN: 1-85233-394-4

  • /

import java.awt.BorderLayout; import java.awt.Button; import java.awt.Frame; import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.media.j3d.ViewPlatform; import javax.media.j3d.VirtualUniverse; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.behaviors.mouse.MouseRotate; import com.sun.j3d.utils.behaviors.mouse.MouseTranslate; import com.sun.j3d.utils.behaviors.mouse.MouseZoom; import com.sun.j3d.utils.geometry.Box; /**

* This application demonstrates the use of the mouse utility classes. It allows
* rotation, translation and resizing of the screen image of a cube by clicking
* and dragging the mouse on the shape.
* 
* @author I.J.Palmer
* @version 1.0
*/

public class SimpleMouse extends Frame implements ActionListener {

 protected Canvas3D myCanvas3D = new Canvas3D(null);
 protected Button exitButton = new Button("Exit");
 protected BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0,
     0.0), 100.0);
 /**
  * Build the view branch of the scene graph
  * 
  * @return BranchGroup that is the root of the view branch
  */
 protected BranchGroup buildViewBranch(Canvas3D c) {
   BranchGroup viewBranch = new BranchGroup();
   Transform3D viewXfm = new Transform3D();
   viewXfm.set(new Vector3f(0.0f, 0.0f, 10.0f));
   TransformGroup viewXfmGroup = new TransformGroup(viewXfm);
   ViewPlatform myViewPlatform = new ViewPlatform();
   PhysicalBody myBody = new PhysicalBody();
   PhysicalEnvironment myEnvironment = new PhysicalEnvironment();
   viewXfmGroup.addChild(myViewPlatform);
   viewBranch.addChild(viewXfmGroup);
   View myView = new View();
   myView.addCanvas3D(c);
   myView.attachViewPlatform(myViewPlatform);
   myView.setPhysicalBody(myBody);
   myView.setPhysicalEnvironment(myEnvironment);
   return viewBranch;
 }
 /**
  * Add some lights to the scene graph
  * 
  * @param b
  *            BranchGroup that the lights are added to
  */
 protected void addLights(BranchGroup b) {
   Color3f ambLightColour = new Color3f(0.5f, 0.5f, 0.5f);
   AmbientLight ambLight = new AmbientLight(ambLightColour);
   ambLight.setInfluencingBounds(bounds);
   Color3f dirLightColour = new Color3f(1.0f, 1.0f, 1.0f);
   Vector3f dirLightDir = new Vector3f(-1.0f, -1.0f, -1.0f);
   DirectionalLight dirLight = new DirectionalLight(dirLightColour,
       dirLightDir);
   dirLight.setInfluencingBounds(bounds);
   b.addChild(ambLight);
   b.addChild(dirLight);
 }
 /**
  * Build the content branch for the scene graph
  * 
  * @return BranchGroup that is the root of the content
  */
 protected BranchGroup buildContentBranch() {
   Appearance app = new Appearance();
   Color3f ambientColour = new Color3f(1.0f, 0.0f, 0.0f);
   Color3f emissiveColour = new Color3f(0.0f, 0.0f, 0.0f);
   Color3f specularColour = new Color3f(1.0f, 1.0f, 1.0f);
   Color3f diffuseColour = new Color3f(1.0f, 0.0f, 0.0f);
   float shininess = 20.0f;
   app.setMaterial(new Material(ambientColour, emissiveColour,
       diffuseColour, specularColour, shininess));
   Box cube = new Box(2.0f, 2.0f, 2.0f, app);
   BranchGroup contentBranch = new BranchGroup();
   addLights(contentBranch);
   //Create the transform groups that will be
   //affected by the mouse utiltities
   TransformGroup spinGroup = new TransformGroup();
   TransformGroup zoomGroup = new TransformGroup();
   TransformGroup moveGroup = new TransformGroup();
   //Set the capabilities of the groups so that we can
   //manipulate them
   spinGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   spinGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   zoomGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   zoomGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   moveGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   moveGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   //Create and use the rotation utility
   MouseRotate mouseSpin = new MouseRotate();
   mouseSpin.setTransformGroup(spinGroup);
   contentBranch.addChild(mouseSpin);
   mouseSpin.setSchedulingBounds(bounds);
   //Create and use the zoom utility
   MouseZoom mouseSize = new MouseZoom();
   mouseSize.setTransformGroup(zoomGroup);
   contentBranch.addChild(mouseSize);
   mouseSize.setSchedulingBounds(bounds);
   //Create and use the translation utility
   MouseTranslate mouseMove = new MouseTranslate();
   mouseMove.setTransformGroup(moveGroup);
   contentBranch.addChild(mouseMove);
   mouseMove.setSchedulingBounds(bounds);
   //Put it all together
   spinGroup.addChild(cube);
   moveGroup.addChild(spinGroup);
   zoomGroup.addChild(moveGroup);
   contentBranch.addChild(zoomGroup);
   return contentBranch;
 }
 /**
  * Use the action event of the exit button to end the application.
  */
 public void actionPerformed(ActionEvent e) {
   if (e.getSource() == exitButton) {
     dispose();
     System.exit(0);
   }
 }
 public SimpleMouse() {
   VirtualUniverse myUniverse = new VirtualUniverse();
   Locale myLocale = new Locale(myUniverse);
   myLocale.addBranchGraph(buildViewBranch(myCanvas3D));
   myLocale.addBranchGraph(buildContentBranch());
   setTitle("SimpleMouse");
   setSize(400, 400);
   setLayout(new BorderLayout());
   Panel bottom = new Panel();
   bottom.add(exitButton);
   add(BorderLayout.CENTER, myCanvas3D);
   add(BorderLayout.SOUTH, bottom);
   exitButton.addActionListener(this);
   setVisible(true);
 }
 public static void main(String[] args) {
   SimpleMouse sm = new SimpleMouse();
 }

}


      </source>
   
  
 
  



Improved mouse behaviors

   <source lang="java">

/**********************************************************

Copyright (C) 2001   Daniel Selman
First distributed with the book "Java 3D Programming"
by Daniel Selman and published by Manning Publications.
http://manning.ru/selman
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
The license can be found on the WWW at:
http://www.fsf.org/copyleft/gpl.html
Or by writing to:
Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
Authors can be contacted at:
Daniel Selman: daniel@selman.org
If you make changes you think others would like, please 
contact one of the authors or someone at the 
www.j3d.org web site.
**************************************************************/

import java.applet.Applet; import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.GraphicsConfigTemplate; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Label; import java.awt.Panel; import java.awt.TextField; import java.awt.event.MouseEvent; import java.io.File; import java.net.URL; import java.util.Enumeration; import javax.media.j3d.Appearance; import javax.media.j3d.AudioDevice; import javax.media.j3d.Background; import javax.media.j3d.Behavior; import javax.media.j3d.BoundingSphere; import javax.media.j3d.Bounds; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.GraphicsConfigTemplate3D; import javax.media.j3d.Group; import javax.media.j3d.Locale; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.media.j3d.ViewPlatform; import javax.media.j3d.VirtualUniverse; import javax.media.j3d.WakeupCriterion; import javax.media.j3d.WakeupOnAWTEvent; import javax.media.j3d.WakeupOr; import javax.vecmath.Color3f; import javax.vecmath.Matrix3d; import javax.vecmath.Matrix4d; import javax.vecmath.Point3d; import javax.vecmath.Point3f; 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; /**

* This example illustrates the mouse behaviors defined in the
* org.selman.java3d.book package. These improved mouse behaviors: - handle
* TransformGroups above the target TG properly 
- can be applied to any * object, not just TGs
- support interface reporting to give easy feedback * on all manipulations
- better motion speed control
- range * validation to clamp scales and translation between limits
*/

public class MouseNavigateTest extends Java3dApplet implements

   ScaleChangeListener, RotationChangeListener, TranslationChangeListener {
 private static int m_kWidth = 300;
 private static int m_kHeight = 400;
 // create some UI to provide feedback on all mouse
 // manipulations
 Label m_RotationLabel = null;
 TextField m_RotationFieldX = null;
 TextField m_RotationFieldY = null;
 TextField m_RotationFieldZ = null;
 Label m_TranslationLabel = null;
 TextField m_TranslationFieldX = null;
 TextField m_TranslationFieldY = null;
 TextField m_TranslationFieldZ = null;
 Label m_ScaleLabel = null;
 TextField m_ScaleFieldZ = null;
 TextField m_ScaleFieldY = null;
 TextField m_ScaleFieldX = null;
 public MouseNavigateTest() {
   initJava3d();
 }
 protected void addCanvas3D(Canvas3D c3d) {
   setLayout(new BorderLayout());
   add(c3d, BorderLayout.CENTER);
   Panel controlPanel = new Panel();
   // add the UI to the frame
   m_RotationLabel = new Label("Rotation: ");
   m_RotationFieldX = new TextField("0.00");
   m_RotationFieldY = new TextField("0.00");
   m_RotationFieldZ = new TextField("0.00");
   controlPanel.add(m_RotationLabel);
   controlPanel.add(m_RotationFieldX);
   controlPanel.add(m_RotationFieldY);
   controlPanel.add(m_RotationFieldZ);
   m_TranslationLabel = new Label("Translation: ");
   m_TranslationFieldX = new TextField("0.00");
   m_TranslationFieldY = new TextField("0.00");
   m_TranslationFieldZ = new TextField("0.00");
   controlPanel.add(m_TranslationLabel);
   controlPanel.add(m_TranslationFieldX);
   controlPanel.add(m_TranslationFieldY);
   controlPanel.add(m_TranslationFieldZ);
   m_ScaleLabel = new Label("Scale: ");
   m_ScaleFieldX = new TextField("0.00");
   m_ScaleFieldY = new TextField("0.00");
   m_ScaleFieldZ = new TextField("0.00");
   controlPanel.add(m_ScaleLabel);
   controlPanel.add(m_ScaleFieldX);
   controlPanel.add(m_ScaleFieldY);
   controlPanel.add(m_ScaleFieldZ);
   add(controlPanel, BorderLayout.SOUTH);
   doLayout();
 }
 protected double getScale() {
   return 1.0;
 }
 // do nothing for these notifications from the mouse behaviors
 public void onStartDrag(Object target) {
 }
 public void onEndDrag(Object target) {
 }
 public void onApplyTransform(Object target) {
 }
 public void onAdjustTransform(Object target, int xpos, int ypos) {
 }
 // called by TornadoMouseRotate
 // yes, those really are Euler angles for the objects rotation
 public void onRotate(Object target, Point3d point3d) {
   m_RotationFieldX.setText(String.valueOf((int) java.lang.Math
       .toDegrees(point3d.x)));
   m_RotationFieldY.setText(String.valueOf((int) java.lang.Math
       .toDegrees(point3d.y)));
   m_RotationFieldZ.setText(String.valueOf((int) java.lang.Math
       .toDegrees(point3d.z)));
 }
 // called by TornadoMouseScale
 public void onScale(Object target, Vector3d scale) {
   m_ScaleFieldX.setText(String.valueOf(scale.x));
   m_ScaleFieldY.setText(String.valueOf(scale.y));
   m_ScaleFieldZ.setText(String.valueOf(scale.z));
 }
 // called by TornadoMouseTranslate
 public void onTranslate(Object target, Vector3d vTranslation) {
   m_TranslationFieldX.setText(String.valueOf(vTranslation.x));
   m_TranslationFieldY.setText(String.valueOf(vTranslation.y));
   m_TranslationFieldZ.setText(String.valueOf(vTranslation.z));
 }
 // we want a black background
 protected Background createBackground() {
   return null;
 }
 protected BranchGroup createSceneBranchGroup() {
   BranchGroup objRoot = super.createSceneBranchGroup();
   // note that we are creating a TG *above* the TG
   // the is being controlled by the mouse behaviors.
   // The SUN mouse translate behavior would fail in this
   // instance as all movement would be in the X-Y plane
   // irrespective of any TG above the object.
   // The TornadoMouseTranslate behavior always moves an object
   // parrallel to the image plane
   TransformGroup objTrans1 = new TransformGroup();
   Transform3D t3d = new Transform3D();
   objTrans1.getTransform(t3d);
   t3d.setEuler(new Vector3d(0.9, 0.8, 0.3));
   objTrans1.setTransform(t3d);
   TransformGroup objTrans = new TransformGroup();
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   // create the mouse scale behavior and set limits
   TornadoMouseScale mouseScale = new TornadoMouseScale(5, 0.1f);
   mouseScale.setMinScale(new Point3d(0.5, 0.5, 0.5));
   mouseScale.setMaxScale(new Point3d(2, 2, 2));
   mouseScale.setObject(objTrans);
   mouseScale.setChangeListener(this);
   mouseScale.setSchedulingBounds(getApplicationBounds());
   objTrans.addChild(mouseScale);
   // create the mouse rotate behavior
   TornadoMouseRotate mouseRotate = new TornadoMouseRotate(0.001, 0.001);
   mouseRotate.setInvert(true);
   mouseRotate.setObject(objTrans);
   mouseRotate.setChangeListener(this);
   mouseRotate.setSchedulingBounds(getApplicationBounds());
   objTrans.addChild(mouseRotate);
   // create the mouse translate behavior and set limits
   TornadoMouseTranslate mouseTrans = new TornadoMouseTranslate(0.005f);
   mouseTrans.setObject(objTrans);
   mouseTrans.setChangeListener(this);
   mouseTrans.setMinTranslate(new Point3d(-4, -4, -4));
   mouseTrans.setMaxTranslate(new Point3d(4, 4, 4));
   mouseTrans.setSchedulingBounds(getApplicationBounds());
   objTrans.addChild(mouseTrans);
   objTrans.addChild(new ColorCube(0.5));
   // create some axis for the world to show it has been rotated
   ColorCube axis = new ColorCube(5.0);
   Appearance app = new Appearance();
   app
       .setPolygonAttributes(new PolygonAttributes(
           PolygonAttributes.POLYGON_LINE,
           PolygonAttributes.CULL_NONE, 0));
   axis.setAppearance(app);
   objTrans1.addChild(axis);
   objTrans1.addChild(objTrans);
   objRoot.addChild(objTrans1);
   return objRoot;
 }
 public static void main(String[] args) {
   MouseNavigateTest mouseTest = new MouseNavigateTest();
   mouseTest.saveCommandLineArguments(args);
   new MainFrame(mouseTest, m_kWidth, m_kHeight);
 }

} //***************************************************************************** /**

* TornadoMouseRotate
* 
* Custom mouse rotation behaviour
* 
* @author Daniel Selman
* @version 1.0
*/

//***************************************************************************** class TornadoMouseRotate extends TornadoMouseBehavior {

 protected double m_FactorX = 0.001;
 protected double m_FactorY = 0.001;
 protected Transform3D m_TransformX = null;
 protected Transform3D m_TransformY = null;
 protected boolean m_bInvert = false;
 //*****************************************************************************
 /**
  * @param xf
  *            the x rotation scale factor
  * @param yf
  *            the y rotation scale factor
  */
 //*****************************************************************************
 public TornadoMouseRotate(double xf, double yf) {
   m_FactorX = xf;
   m_FactorY = yf;
   m_TransformX = new Transform3D();
   m_TransformY = new Transform3D();
   m_bInvert = false;
 }
 protected boolean isStartBehaviorEvent(java.awt.event.MouseEvent evt) {
   int nId = evt.getID();
   return ((nId == MouseEvent.MOUSE_DRAGGED) && (evt.isAltDown() == false) && (evt
       .isMetaDown() == false));
 }
 //*****************************************************************************
 /**
  * @param bInvert
  *            true to invert the Y axis
  */
 //*****************************************************************************
 public void setInvert(boolean bInvert) {
   m_bInvert = bInvert;
 }
 // this behavior is relative to the *screen*
 // the current rotation of the object etc. is ignored
 protected boolean isRelativeToObjectCoordinates() {
   return false;
 }
 protected void applyVectorToObject(Vector3f vector) {
   TransformGroup tg = getTransformGroup();
   if (tg != null) {
     tg.getTransform(m_Transform3D);
     double x_angle = vector.y * m_FactorX;
     double y_angle = vector.x * m_FactorY;
     m_TransformX.rotX(x_angle);
     m_TransformY.rotY(y_angle);
     Matrix4d mat = new Matrix4d();
     // Remember old matrix
     m_Transform3D.get(mat);
     // Translate to origin
     m_Transform3D.setTranslation(new Vector3d(0.0, 0.0, 0.0));
     if (m_bInvert != false) {
       m_Transform3D.mul(m_Transform3D, m_TransformX);
       m_Transform3D.mul(m_Transform3D, m_TransformY);
     } else {
       m_Transform3D.mul(m_TransformX, m_Transform3D);
       m_Transform3D.mul(m_TransformY, m_Transform3D);
     }
     // Set old translation back
     Vector3d translation = new Vector3d(mat.m03, mat.m13, mat.m23);
     m_Transform3D.setTranslation(translation);
     // save the new Transform3D
     applyTransform();
     if (m_Listener != null) {
       Point3d rotate = Euler.getEulerRotation(m_Transform3D);
       ((RotationChangeListener) m_Listener)
           .onRotate(m_Object, rotate);
     }
   }
 }

} // TornadoMouseRotate class Euler {

 public static int EulOrdXYZs() {
   return EulOrd(X, EulParEven, EulRepNo, EulFrmS);
 }
 public static int EulOrdXYXs() {
   return EulOrd(X, EulParEven, EulRepYes, EulFrmS);
 }
 public static int EulOrdXZYs() {
   return EulOrd(X, EulParOdd, EulRepNo, EulFrmS);
 }
 public static int EulOrdXZXs() {
   return EulOrd(X, EulParOdd, EulRepYes, EulFrmS);
 }
 public static int EulOrdYZXs() {
   return EulOrd(Y, EulParEven, EulRepNo, EulFrmS);
 }
 public static int EulOrdYZYs() {
   return EulOrd(Y, EulParEven, EulRepYes, EulFrmS);
 }
 public static int EulOrdYXZs() {
   return EulOrd(Y, EulParOdd, EulRepNo, EulFrmS);
 }
 public static int EulOrdYXYs() {
   return EulOrd(Y, EulParOdd, EulRepYes, EulFrmS);
 }
 public static int EulOrdZXYs() {
   return EulOrd(Z, EulParEven, EulRepNo, EulFrmS);
 }
 public static int EulOrdZXZs() {
   return EulOrd(Z, EulParEven, EulRepYes, EulFrmS);
 }
 public static int EulOrdZYXs() {
   return EulOrd(Z, EulParOdd, EulRepNo, EulFrmS);
 }
 public static int EulOrdZYZs() {
   return EulOrd(Z, EulParOdd, EulRepYes, EulFrmS);
 }
 /* Rotating axes */
 public static int EulOrdZYXr() {
   return EulOrd(X, EulParEven, EulRepNo, EulFrmR);
 }
 public static int EulOrdXYXr() {
   return EulOrd(X, EulParEven, EulRepYes, EulFrmR);
 }
 public static int EulOrdYZXr() {
   return EulOrd(X, EulParOdd, EulRepNo, EulFrmR);
 }
 public static int EulOrdXZXr() {
   return EulOrd(X, EulParOdd, EulRepYes, EulFrmR);
 }
 public static int EulOrdXZYr() {
   return EulOrd(Y, EulParEven, EulRepNo, EulFrmR);
 }
 public static int EulOrdYZYr() {
   return EulOrd(Y, EulParEven, EulRepYes, EulFrmR);
 }
 public static int EulOrdZXYr() {
   return EulOrd(Y, EulParOdd, EulRepNo, EulFrmR);
 }
 public static int EulOrdYXYr() {
   return EulOrd(Y, EulParOdd, EulRepYes, EulFrmR);
 }
 public static int EulOrdYXZr() {
   return EulOrd(Z, EulParEven, EulRepNo, EulFrmR);
 }
 public static int EulOrdZXZr() {
   return EulOrd(Z, EulParEven, EulRepYes, EulFrmR);
 }
 public static int EulOrdXYZr() {
   return EulOrd(Z, EulParOdd, EulRepNo, EulFrmR);
 }
 public static int EulOrdZYZr() {
   return EulOrd(Z, EulParOdd, EulRepYes, EulFrmR);
 }
 public static int EulFrm(int ord) {
   // DCS, was unsigned
   return ((ord) & 1);
 }
 public static int EulRep(int ord) {
   // DCS, was unsigned
   return (((ord) >> 1) & 1);
 }
 public static int EulPar(int ord) {
   return (((ord) >> 2) & 1);
 }
 public static int EulAxI(int ord) {
   // DCS, was unsigned
   return ((int) (EulSafe((((ord) >> 3) & 3))));
 }
 public static int EulAxJ(int ord) {
   int i = 0;
   if (EulPar(ord) == EulParOdd)
     i = 1;
   return ((int) (EulNext(EulAxI(ord) + i)));
 }
 public static int EulAxK(int ord) {
   int i = 0;
   if (EulPar(ord) != EulParOdd)
     i = 1;
   return ((int) (EulNext(EulAxI(ord) + i)));
 }
 public static int EulAxH(int ord) {
   if (EulRep(ord) == EulRepNo)
     return EulAxK(ord);
   return EulAxI(ord);
 }
 public static int EulOrd(int i, int p, int r, int f) {
   return (((((((i) << 1) + (p)) << 1) + (r)) << 1) + (f));
 }
 // enum
 static final int X = 0;
 static final int Y = 1;
 static final int Z = 2;
 static final int W = 3;
 static final int EulRepNo = 0;
 static final int EulRepYes = 1;
 static final int EulParEven = 0;
 static final int EulParOdd = 1;
 static final int EulFrmS = 0;
 static final int EulFrmR = 1;
 static final float FLT_EPSILON = 1.192092896e-07F;
 static EulGetOrdInfo EulGetOrd(int ord) {
   EulGetOrdInfo info = new EulGetOrdInfo();
   // note, used to be unsigned!
   int o = ord;
   info.f = o & 1;
   o >>= 1;
   info.s = o & 1;
   o >>= 1;
   info.n = o & 1;
   o >>= 1;
   info.i = EulSafe(o & 3);
   info.j = EulNext(info.i + info.n);
   info.k = EulNext(info.i + 1 - info.n);
   if (info.s != 0)
     info.h = info.k;
   else
     info.h = info.i;
   return info;
 }
 static int EulSafe(int val) {
   int[] valArray = { 0, 1, 2, 0 };
   return valArray[val];
 }
 static int EulNext(int val) {
   int[] valArray = { 1, 2, 0, 1 };
   return valArray[val];
 }
 // float HMatrix[4][4];
 /* Convert matrix to Euler angles (in radians). */
 public static EulerAngles Eul_FromMatrix(float[][] M, int order) {
   EulerAngles ea = new EulerAngles();
   EulGetOrdInfo info = EulGetOrd(order);
   int i = info.i;
   int j = info.j;
   int k = info.k;
   int h = info.h;
   int n = info.n;
   int s = info.s;
   int f = info.f;
   if (s == EulRepYes) {
     double sy = Math.sqrt(M[i][j] * M[i][j] + M[i][k] * M[i][k]);
     if (sy > 16 * FLT_EPSILON) {
       ea.x = (float) Math.atan2(M[i][j], M[i][k]);
       ea.y = (float) Math.atan2(sy, M[i][i]);
       ea.z = (float) Math.atan2(M[j][i], -M[k][i]);
     } else {
       ea.x = (float) Math.atan2(-M[j][k], M[j][j]);
       ea.y = (float) Math.atan2(sy, M[i][i]);
       ea.z = 0;
     }
   } else {
     double cy = Math.sqrt(M[i][i] * M[i][i] + M[j][i] * M[j][i]);
     if (cy > 16 * FLT_EPSILON) {
       ea.x = (float) Math.atan2(M[k][j], M[k][k]);
       ea.y = (float) Math.atan2(-M[k][i], cy);
       ea.z = (float) Math.atan2(M[j][i], M[i][i]);
     } else {
       ea.x = (float) Math.atan2(-M[j][k], M[j][j]);
       ea.y = (float) Math.atan2(-M[k][i], cy);
       ea.z = 0;
     }
   }
   if (n == EulParOdd) {
     ea.x = -ea.x;
     ea.y = -ea.y;
     ea.z = -ea.z;
   }
   if (f == EulFrmR) {
     float t = ea.x;
     ea.x = ea.z;
     ea.z = t;
   }
   ea.w = order;
   return (ea);
 }
 /* Convert quaternion to Euler angles (in radians). */
 public static EulerAngles Eul_FromQuat(Quat q, int order) {
   float[][] M = new float[4][4];
   double Nq = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
   double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
   double xs = q.x * s, ys = q.y * s, zs = q.z * s;
   double wx = q.w * xs, wy = q.w * ys, wz = q.w * zs;
   double xx = q.x * xs, xy = q.x * ys, xz = q.x * zs;
   double yy = q.y * ys, yz = q.y * zs, zz = q.z * zs;
   M[X][X] = (float) (1.0 - (yy + zz));
   M[X][Y] = (float) (xy - wz);
   M[X][Z] = (float) (xz + wy);
   M[Y][X] = (float) (xy + wz);
   M[Y][Y] = (float) (1.0 - (xx + zz));
   M[Y][Z] = (float) (yz - wx);
   M[Z][X] = (float) (xz - wy);
   M[Z][Y] = (float) (yz + wx);
   M[Z][Z] = (float) (1.0 - (xx + yy));
   M[W][X] = M[W][Y] = M[W][Z] = M[X][W] = M[Y][W] = M[Z][W] = 0.0f;
   M[W][W] = 1.0f;
   return (Eul_FromMatrix(M, order));
 }
 public static Point3d getEulerRotation(Transform3D t3d) {
   Point3d Rotation = new Point3d();
   Matrix3d m1 = new Matrix3d();
   t3d.get(m1);
   // extract the rotation angles from the upper 3x3 rotation
   // component of the 4x4 transformation matrix
   Rotation.y = -java.lang.Math.asin(m1.getElement(2, 0));
   double c = java.lang.Math.cos(Rotation.y);
   double tRx, tRy, tRz;
   if (java.lang.Math.abs(Rotation.y) > 0.00001) {
     tRx = m1.getElement(2, 2) / c;
     tRy = -m1.getElement(2, 1) / c;
     Rotation.x = java.lang.Math.atan2(tRy, tRx);
     tRx = m1.getElement(0, 0) / c;
     tRy = -m1.getElement(1, 0) / c;
     Rotation.z = java.lang.Math.atan2(tRy, tRx);
   } else {
     Rotation.x = 0.0;
     tRx = m1.getElement(1, 1);
     tRy = m1.getElement(0, 1);
     Rotation.z = java.lang.Math.atan2(tRy, tRx);
   }
   Rotation.x = -Rotation.x;
   Rotation.z = -Rotation.z;
   // now try to ensure that the values are positive by adding 2PI if
   // necessary...
   if (Rotation.x < 0.0)
     Rotation.x += 2 * java.lang.Math.PI;
   if (Rotation.y < 0.0)
     Rotation.y += 2 * java.lang.Math.PI;
   if (Rotation.z < 0.0)
     Rotation.z += 2 * java.lang.Math.PI;
   return Rotation;
 }

} class EulerAngles extends Quat {

 public EulerAngles() {
 }

} class Quat {

 public float x;
 public float y;
 public float z;
 public float w;
 public Quat( )
 {
 }

} class EulGetOrdInfo {

 public int i;
 public int j;
 public int k;
 public int h;
 public int n;
 public int s;
 public int f;
 EulGetOrdInfo() {
 }

} //***************************************************************************** /**

* Base class for the Tornado Mouse Behaviors (Rotate, Translate, Scale).
* 
* @author Daniel Selman
* @version 1.0
*/

//***************************************************************************** abstract class TornadoMouseBehavior extends Behavior {

 // private data
 protected Object m_Object = null;
 protected Point3f m_NewPos = null;
 protected Point3f m_OldPos = null;
 protected Vector3f m_TranslationVector = null;
 protected Transform3D m_Translation = null;
 protected boolean m_bDragging = false;
 protected WakeupOr m_MouseCriterion = null;
 protected int m_nLastY = 0;
 protected Transform3D m_Transform3D = null;
 protected TornadoChangeListener m_Listener = null;
 public TornadoMouseBehavior() {
   m_Object = null;
   m_NewPos = new Point3f();
   m_OldPos = new Point3f();
   m_Translation = new Transform3D();
   m_TranslationVector = new Vector3f();
   m_bDragging = false;
   m_Transform3D = new Transform3D();
 }
 //*****************************************************************************
 /**
  * Register a listener for the behavior.
  * 
  * @param listener
  *            the listener to add or null to remove the listener
  */
 //*****************************************************************************
 public void setChangeListener(TornadoChangeListener listener) {
   m_Listener = listener;
 }
 //*****************************************************************************
 /**
  * Apply a delta vector (in the object"s local coordinates) to the object.
  */
 //*****************************************************************************
 protected abstract void applyVectorToObject(Vector3f v);
 //*****************************************************************************
 /**
  * @return true is this the mouse event that starts the tracking behaviour
  */
 //*****************************************************************************
 protected abstract boolean isStartBehaviorEvent(
     java.awt.event.MouseEvent evt);
 //*****************************************************************************
 /**
  * Dispatches mouse events as appropriate. Should not need to overide this
  * method.
  */
 //*****************************************************************************
 protected void processMouseEvent(java.awt.event.MouseEvent evt) {
   if (m_Object != null) {
     if (isStartBehaviorEvent(evt) != false)
       adjustTransform(evt.getX(), evt.getY());
     else if (isStopBehaviorEvent(evt) != false)
       onEndDrag();
   }
 }
 //*****************************************************************************
 /**
  * @return true if this is the event that stops drag tracking behviour the
  *         default uses MOUSE_RELEASED.
  */
 //*****************************************************************************
 protected boolean isStopBehaviorEvent(java.awt.event.MouseEvent evt) {
   int nId = evt.getID();
   return (m_bDragging != false && nId == MouseEvent.MOUSE_RELEASED || nId == MouseEvent.MOUSE_EXITED);
 }
 //*****************************************************************************
 /**
  * @return true if this behaviours change vector is relative to the starting
  *         mouse click. The default is a behaviour that generates delta
  *         change vectors as the user moves the mouse.
  */
 //*****************************************************************************
 protected boolean isRelativeToStartDrag() {
   return false;
 }
 //*****************************************************************************
 /**
  * @return true if the mouse coordinates should be converted to local object
  *         coordinates before being processed by applyVectorToObject
  */
 //*****************************************************************************
 protected boolean isRelativeToObjectCoordinates() {
   return true;
 }
 //*****************************************************************************
 /**
  * Allows custom start drag processing. Default does nothing.
  */
 //*****************************************************************************
 protected void onStartDrag() {
   if (m_Listener != null)
     m_Listener.onStartDrag(m_Object);
 }
 //*****************************************************************************
 /**
  * Allows custom end drag processing. ** Call this base class! **
  */
 //*****************************************************************************
 protected void onEndDrag() {
   m_bDragging = false;
   if (m_Listener != null)
     m_Listener.onEndDrag(m_Object);
 }
 //*****************************************************************************
 /**
  * Gets the Transform3D to convert from the Objects coordinate system to the
  * world coordinate system.
  * 
  * @param t3d
  *            the Transform3D to populate
  */
 //*****************************************************************************
 protected void getObjectLocalToVworld(Transform3D t3d) {
   if (getTransformGroup() != null)
     getTransformGroup().getLocalToVworld(t3d);
 }
 //*****************************************************************************
 /**
  * Gets the Transform3D to convert from the Image plate coordinate system to
  * the world coordinate system.
  * 
  * @param t3d
  *            the Transform3D to populate
  */
 //*****************************************************************************
 protected void getImagePlateToVworld(Transform3D t3d) {
   getView().getCanvas3D(0).getImagePlateToVworld(t3d);
 }
 //*****************************************************************************
 /**
  * @return the TransformGroup if a TG Object is associated with the behavior
  *         or null otherwise.
  */
 //*****************************************************************************
 protected TransformGroup getTransformGroup() {
   if (m_Object instanceof TransformGroup)
     return (TransformGroup) m_Object;
   return null;
 }
 //*****************************************************************************
 /**
  * Saves the behaviors Transform3D into its TransformGroup (if present).
  * Catches any exceptions (bad transform) that might be thrown.
  */
 //*****************************************************************************
 protected void applyTransform() {
   TransformGroup tg = getTransformGroup();
   if (tg != null) {
     try {
       // save the new Transform3D
       tg.setTransform(m_Transform3D);
       if (m_Listener != null)
         m_Listener.onApplyTransform(m_Object);
     } catch (Exception e) {
       System.err.println(e.toString());
     }
   }
 }
 //*****************************************************************************
 /**
  * Transforms the x,y mouse coordinates to coordinates relative to the
  * object. Calculates a "delta vector" in object coordinates and calls
  * ApplyVectorToObject().
  * 
  * Thanks to: A.R. van Ballegooy. Simon McMullen [simonmc@mincom.ru]
  */
 //*****************************************************************************
 protected void adjustTransform(int xpos, int ypos) {
   if (m_Listener != null)
     m_Listener.onAdjustTransform(m_Object, xpos, ypos);
   if (m_bDragging == false) {
     // initialise the starting position
     m_OldPos.x = xpos;
     m_OldPos.y = ypos;
     m_OldPos.z = 0.0f;
     m_nLastY = ypos;
     onStartDrag();
   }
   m_bDragging = true;
   // save the current position and invert the tracking in the Y direction
   // (positive upwards)
   m_NewPos.x = xpos;
   m_NewPos.y = m_nLastY + (m_nLastY - ypos);
   m_NewPos.z = 0.0f;
   m_nLastY = ypos;
   // transform points to Virtual World Coordinates
   getImagePlateToVworld(m_Translation);
   if (isRelativeToStartDrag() == false)
     m_Translation.transform(m_OldPos);
   m_Translation.transform(m_NewPos);
   // transform coordinates to Object Space Coordinates
   // Make sure capability ALLOW_LOCAL_TO_VWORLD_READ is set....
   if (isRelativeToObjectCoordinates() != false) {
     getObjectLocalToVworld(m_Translation);
     m_Translation.transpose();
     // transform points to local coordinate system
     if (isRelativeToStartDrag() == false)
       m_Translation.transform(m_OldPos);
     m_Translation.transform(m_NewPos);
   }
   // Calculate change and scale
   m_TranslationVector.sub(m_NewPos, m_OldPos);
   applyVectorToObject(m_TranslationVector);
   if (isRelativeToStartDrag() == false) {
     // store the new positions
     m_OldPos.x = xpos;
     m_OldPos.y = ypos;
     m_OldPos.z = 0.0f;
   }
 }
 //*****************************************************************************
 /**
  * Dispatches events based on the behaviours criteria
  */
 //*****************************************************************************
 public void processStimulus(Enumeration criteria) {
   WakeupCriterion wakeup;
   AWTEvent[] event;
   int id;
   int dx, dy;
   if (m_Object != null) {
     while (criteria.hasMoreElements()) {
       wakeup = (WakeupCriterion) criteria.nextElement();
       if (wakeup instanceof WakeupOnAWTEvent) {
         event = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
         for (int i = 0; i < event.length; i++) {
           processMouseEvent((MouseEvent) event[i]);
         }
       }
     }
   }
   // tell the behaviour when to wake up again...
   wakeupOn(m_MouseCriterion);
 }
 //*****************************************************************************
 /**
  * Registers which AWT events are of interest to the behaviour
  */
 //*****************************************************************************
 public void initialize() {
   WakeupCriterion[] mouseEvents = new WakeupCriterion[3];
   mouseEvents[0] = new WakeupOnAWTEvent(MouseEvent.MOUSE_DRAGGED);
   mouseEvents[1] = new WakeupOnAWTEvent(MouseEvent.MOUSE_PRESSED);
   mouseEvents[2] = new WakeupOnAWTEvent(MouseEvent.MOUSE_RELEASED);
   m_MouseCriterion = new WakeupOr(mouseEvents);
   wakeupOn(m_MouseCriterion);
 }
 //*****************************************************************************
 /**
  * void setObject( Object obj )
  * 
  * @param obj
  *            the Objectto manipulate. A null object disables the behaviour.
  */
 //*****************************************************************************
 public void setObject(Object obj) {
   m_Object = obj;
 }

} // TornadoMouseBehavior //***************************************************************************** /**

* TornadoMouseScale
* 
* Custon scaling behaviour
* 
* @author Daniel Selman
* @version 1.0
*/

//***************************************************************************** class TornadoMouseScale extends TornadoMouseBehavior {

 // private data
 protected float m_Delta = 0;
 protected float m_Threshold = 0;
 protected Point3d m_MinScale;
 protected Point3d m_MaxScale;
 //*****************************************************************************
 /**
  * @param threshold
  *            the amount the mouse must be moved before an object is moved
  * @param delta
  *            the step size to use for object scaling bigger = faster
  *            scaling.
  * 
  * Default minimum scale: 0.1,0.1,0.1 Default maximum scale: 5,5,5
  */
 //*****************************************************************************
 public TornadoMouseScale(float threshold, float delta) {
   m_Delta = delta;
   m_Threshold = threshold;
   m_MinScale = new Point3d(0.1, 0.1, 0.1);
   m_MaxScale = new Point3d(5, 5, 5);
 }
 //*****************************************************************************
 /**
  * @param minScale
  *            the minimum x,y,z scale
  */
 //*****************************************************************************
 public void setMinScale(Point3d minScale) {
   m_MinScale = minScale;
 }
 //*****************************************************************************
 /**
  * @param maxScale
  *            the maximum x,y,z scale
  */
 //*****************************************************************************
 public void setMaxScale(Point3d maxScale) {
   m_MaxScale = maxScale;
 }
 // this behavior is relative to the *screen*
 // the current rotation of the object etc. is ignored
 protected boolean isRelativeToObjectCoordinates() {
   return true;
 }
 protected boolean isStartBehaviorEvent(java.awt.event.MouseEvent evt) {
   int nId = evt.getID();
   return ((nId == MouseEvent.MOUSE_DRAGGED) && (evt.isAltDown() != false) && (evt
       .isMetaDown() == false));
 }
 protected void applyVectorToObject(Vector3f vector) {
   TransformGroup tg = getTransformGroup();
   if (tg != null) {
     tg.getTransform(m_Transform3D);
     Vector3d vScale = new Vector3d();
     m_Transform3D.getScale(vScale);
     Vector3f delta = new Vector3f();
     if (vector.x > m_Threshold)
       delta.x = m_Delta;
     else if (vector.x < -m_Threshold)
       delta.x = -m_Delta;
     if (vector.y > m_Threshold)
       delta.y = m_Delta;
     else if (vector.y < -m_Threshold)
       delta.y = -m_Delta;
     if (vector.z > m_Threshold)
       delta.z = m_Delta;
     else if (vector.z < -m_Threshold)
       delta.z = -m_Delta;
     Vector3d objectScale = new Vector3d(vScale.x + delta.x, vScale.y
         + delta.y, vScale.z + delta.z);
     if (objectScale.x >= m_MinScale.x && objectScale.y >= m_MinScale.y
         && objectScale.z >= m_MinScale.z) {
       if (objectScale.x <= m_MaxScale.x
           && objectScale.y <= m_MaxScale.y
           && objectScale.z <= m_MaxScale.z) {
         m_Transform3D.setScale(objectScale);
         // save the new Transform3D
         applyTransform();
         if (m_Listener != null)
           ((ScaleChangeListener) m_Listener).onScale(m_Object,
               objectScale);
       }
     }
   }
 }

} // TornadoMouseScale //***************************************************************************** /**

* TornadoMouseTranslate
* 
* Custom translation behavior.
* 
* @author Daniel Selman
* @version 1.0
*/

//***************************************************************************** class TornadoMouseTranslate extends TornadoMouseBehavior {

 // private data
 private float m_Scale = 1;
 protected Point3d m_MinTranslate = null;
 protected Point3d m_MaxTranslate = null;
 // protected data
 // public data
 //*****************************************************************************
 /**
  * @param scale
  *            the translation scale factor (bigger = faster)
  * 
  * Default minimum translation: -10,-10,-10 Default maximum translation:
  * 10,10,10
  */
 //*****************************************************************************
 public TornadoMouseTranslate(float scale) {
   m_Scale = scale;
   m_MinTranslate = new Point3d(-10, -10, -10);
   m_MaxTranslate = new Point3d(10, 10, 10);
 }
 //*****************************************************************************
 /**
  * @param minTrans
  *            the minimum x,y,z translation
  */
 //*****************************************************************************
 public void setMinTranslate(Point3d minTrans) {
   m_MinTranslate = minTrans;
 }
 //*****************************************************************************
 /**
  * @param maxTrans
  *            the maximum x,y,z translation
  */
 //*****************************************************************************
 public void setMaxTranslate(Point3d maxTrans) {
   m_MaxTranslate = maxTrans;
 }
 protected boolean isStartBehaviorEvent(java.awt.event.MouseEvent evt) {
   int nId = evt.getID();
   return ((nId == MouseEvent.MOUSE_DRAGGED) && (evt.isAltDown() == false) && (evt
       .isMetaDown() != false));
 }
 protected void applyVectorToObject(Vector3f vector) {
   TransformGroup tg = getTransformGroup();
   if (tg != null) {
     // scale the mouse movements so the objects roughly tracks with the
     // mouse
     vector.scale(m_Scale);
     Vector3d vTranslation = new Vector3d();
     tg.getTransform(m_Transform3D);
     m_Transform3D.get(vTranslation);
     vTranslation.x += vector.x;
     vTranslation.y += vector.y;
     vTranslation.z += vector.z;
     if (vTranslation.x >= m_MinTranslate.x
         && vTranslation.y >= m_MinTranslate.y
         && vTranslation.z >= m_MinTranslate.z) {
       if (vTranslation.x <= m_MaxTranslate.x
           && vTranslation.y <= m_MaxTranslate.y
           && vTranslation.z <= m_MaxTranslate.z) {
         m_Transform3D.setTranslation(vTranslation);
         applyTransform();
         if (m_Listener != null)
           ((TranslationChangeListener) m_Listener).onTranslate(
               m_Object, vTranslation);
       }
     }
   }
 }

} // TornadoMouseTranslate //***************************************************************************** /**

* Interface to listen for changes in translation from the TornadoMouseScale
* class.
* 
* @author Daniel Selman
* @version 1.0
*/

//***************************************************************************** abstract interface ScaleChangeListener extends TornadoChangeListener {

 //*****************************************************************************
 /**
  * Callback to notify of new scale being applied.
  * 
  * @param target
  *            the Object being manipulated
  * @param scale
  *            the new scale being applied
  */
 //*****************************************************************************
 public void onScale(Object target, Vector3d scale);

} //***************************************************************************** /**

* Interface to listen for changes in translation from the TornadoMouseTranslate
* class.
* 
* @author Daniel Selman
* @version 1.0
*/

//***************************************************************************** abstract interface TranslationChangeListener extends TornadoChangeListener {

 //*****************************************************************************
 /**
  * Callback to notify of new translationg being applied.
  * 
  * @param target
  *            the Object being manipulated
  * @param vTranslation
  *            the new translation being applied
  */
 //*****************************************************************************
 public void onTranslate(Object target, Vector3d vTranslation);

} //***************************************************************************** /**

* Interface to listen for changes in rotation from the TornadoMouseRotate
* class.
* 
* @author Daniel Selman
* @version 1.0
*/

//***************************************************************************** abstract interface RotationChangeListener extends TornadoChangeListener {

 //*****************************************************************************
 /**
  * Callback to notify of new translationg being applied.
  * 
  * @param target
  *            the Object being manipulated
  * @param point3d
  *            the new rotation (Euler, radians) applied
  */
 //*****************************************************************************
 public void onRotate(Object target, Point3d point3d);

} //***************************************************************************** /**

* Interface to listen for changes affected by in the TornadoMouseBehaviors.
* 
* @author Daniel Selman
* @version 1.0
*/

//***************************************************************************** abstract interface TornadoChangeListener {

 //*****************************************************************************
 /**
  * Callback to notify of a start drag event.
  * 
  * @param target
  *            the Object being manipulated
  */
 //*****************************************************************************
 public void onStartDrag(Object target);
 //*****************************************************************************
 /**
  * Callback to notify of an end drag event.
  * 
  * @param target
  *            the Object being manipulated
  */
 //*****************************************************************************
 public void onEndDrag(Object target);
 //*****************************************************************************
 /**
  * Notification that the Transform is being updated
  * 
  * @param target
  *            the Object being manipulated
  */
 //*****************************************************************************
 public void onApplyTransform(Object target);
 //*****************************************************************************
 /**
  * Notification that a new Transform is being calculated
  * 
  * @param target
  *            the Object being manipulated
  * @param xpos
  *            the mouse x position
  * @param ypos
  *            the mouse y position
  */
 //*****************************************************************************
 public void onAdjustTransform(Object target, int xpos, int ypos);

} /*******************************************************************************

* Copyright (C) 2001 Daniel Selman
* 
* First distributed with the book "Java 3D Programming" by Daniel Selman and
* published by Manning Publications. http://manning.ru/selman
* 
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 2.
* 
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
* 
* The license can be found on the WWW at: http://www.fsf.org/copyleft/gpl.html
* 
* Or by writing to: Free Software Foundation, Inc., 59 Temple Place - Suite
* 330, Boston, MA 02111-1307, USA.
* 
* Authors can be contacted at: Daniel Selman: daniel@selman.org
* 
* If you make changes you think others would like, please contact one of the
* authors or someone at the www.j3d.org web site.
******************************************************************************/

//***************************************************************************** /**

* Java3dApplet
* 
* Base class for defining a Java 3D applet. Contains some useful methods for
* defining views and scenegraphs etc.
* 
* @author Daniel Selman
* @version 1.0
*/

//***************************************************************************** abstract class Java3dApplet extends Applet {

 public static int m_kWidth = 300;
 public static int m_kHeight = 300;
 protected String[] m_szCommandLineArray = null;
 protected VirtualUniverse m_Universe = null;
 protected BranchGroup m_SceneBranchGroup = null;
 protected Bounds m_ApplicationBounds = null;
 //  protected com.tornadolabs.j3dtree.Java3dTree m_Java3dTree = null;
 public Java3dApplet() {
 }
 public boolean isApplet() {
   try {
     System.getProperty("user.dir");
     System.out.println("Running as Application.");
     return false;
   } catch (Exception e) {
   }
   System.out.println("Running as Applet.");
   return true;
 }
 public URL getWorkingDirectory() throws java.net.MalformedURLException {
   URL url = null;
   try {
     File file = new File(System.getProperty("user.dir"));
     System.out.println("Running as Application:");
     System.out.println("   " + file.toURL());
     return file.toURL();
   } catch (Exception e) {
   }
   System.out.println("Running as Applet:");
   System.out.println("   " + getCodeBase());
   return getCodeBase();
 }
 public VirtualUniverse getVirtualUniverse() {
   return m_Universe;
 }
 //public com.tornadolabs.j3dtree.Java3dTree getJ3dTree() {
 //return m_Java3dTree;
 //  }
 public Locale getFirstLocale() {
   java.util.Enumeration e = m_Universe.getAllLocales();
   if (e.hasMoreElements() != false)
     return (Locale) e.nextElement();
   return null;
 }
 protected Bounds getApplicationBounds() {
   if (m_ApplicationBounds == null)
     m_ApplicationBounds = createApplicationBounds();
   return m_ApplicationBounds;
 }
 protected Bounds createApplicationBounds() {
   m_ApplicationBounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   return m_ApplicationBounds;
 }
 protected Background createBackground() {
   Background back = new Background(new Color3f(0.9f, 0.9f, 0.9f));
   back.setApplicationBounds(createApplicationBounds());
   return back;
 }
 public void initJava3d() {
   //  m_Java3dTree = new com.tornadolabs.j3dtree.Java3dTree();
   m_Universe = createVirtualUniverse();
   Locale locale = createLocale(m_Universe);
   BranchGroup sceneBranchGroup = createSceneBranchGroup();
   ViewPlatform vp = createViewPlatform();
   BranchGroup viewBranchGroup = createViewBranchGroup(
       getViewTransformGroupArray(), vp);
   createView(vp);
   Background background = createBackground();
   if (background != null)
     sceneBranchGroup.addChild(background);
   //    m_Java3dTree.recursiveApplyCapability(sceneBranchGroup);
   //  m_Java3dTree.recursiveApplyCapability(viewBranchGroup);
   locale.addBranchGraph(sceneBranchGroup);
   addViewBranchGroup(locale, viewBranchGroup);
   onDoneInit();
 }
 protected void onDoneInit() {
   //  m_Java3dTree.updateNodes(m_Universe);
 }
 protected double getScale() {
   return 1.0;
 }
 public TransformGroup[] getViewTransformGroupArray() {
   TransformGroup[] tgArray = new TransformGroup[1];
   tgArray[0] = new TransformGroup();
   // move the camera BACK a little...
   // note that we have to invert the matrix as
   // we are moving the viewer
   Transform3D t3d = new Transform3D();
   t3d.setScale(getScale());
   t3d.setTranslation(new Vector3d(0.0, 0.0, -20.0));
   t3d.invert();
   tgArray[0].setTransform(t3d);
   return tgArray;
 }
 protected void addViewBranchGroup(Locale locale, BranchGroup bg) {
   locale.addBranchGraph(bg);
 }
 protected Locale createLocale(VirtualUniverse u) {
   return new Locale(u);
 }
 protected BranchGroup createSceneBranchGroup() {
   m_SceneBranchGroup = new BranchGroup();
   return m_SceneBranchGroup;
 }
 protected View createView(ViewPlatform vp) {
   View view = new View();
   PhysicalBody pb = createPhysicalBody();
   PhysicalEnvironment pe = createPhysicalEnvironment();
   AudioDevice audioDevice = createAudioDevice(pe);
   if (audioDevice != null) {
     pe.setAudioDevice(audioDevice);
     audioDevice.initialize();
   }
   view.setPhysicalEnvironment(pe);
   view.setPhysicalBody(pb);
   if (vp != null)
     view.attachViewPlatform(vp);
   view.setBackClipDistance(getBackClipDistance());
   view.setFrontClipDistance(getFrontClipDistance());
   Canvas3D c3d = createCanvas3D();
   view.addCanvas3D(c3d);
   addCanvas3D(c3d);
   return view;
 }
 protected PhysicalBody createPhysicalBody() {
   return new PhysicalBody();
 }
 protected AudioDevice createAudioDevice(PhysicalEnvironment pe) {
   JavaSoundMixer javaSoundMixer = new JavaSoundMixer(pe);
   if (javaSoundMixer == null)
     System.out.println("create of audiodevice failed");
   return javaSoundMixer;
 }
 protected PhysicalEnvironment createPhysicalEnvironment() {
   return new PhysicalEnvironment();
 }
 protected float getViewPlatformActivationRadius() {
   return 100;
 }
 protected ViewPlatform createViewPlatform() {
   ViewPlatform vp = new ViewPlatform();
   vp.setViewAttachPolicy(View.RELATIVE_TO_FIELD_OF_VIEW);
   vp.setActivationRadius(getViewPlatformActivationRadius());
   return vp;
 }
 protected Canvas3D createCanvas3D() {
   GraphicsConfigTemplate3D gc3D = new GraphicsConfigTemplate3D();
   gc3D.setSceneAntialiasing(GraphicsConfigTemplate.PREFERRED);
   GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment()
       .getScreenDevices();
   Canvas3D c3d = new Canvas3D(gd[0].getBestConfiguration(gc3D));
   c3d.setSize(getCanvas3dWidth(c3d), getCanvas3dHeight(c3d));
   return c3d;
 }
 protected int getCanvas3dWidth(Canvas3D c3d) {
   return m_kWidth;
 }
 protected int getCanvas3dHeight(Canvas3D c3d) {
   return m_kHeight;
 }
 protected double getBackClipDistance() {
   return 100.0;
 }
 protected double getFrontClipDistance() {
   return 1.0;
 }
 protected BranchGroup createViewBranchGroup(TransformGroup[] tgArray,
     ViewPlatform vp) {
   BranchGroup vpBranchGroup = new BranchGroup();
   if (tgArray != null && tgArray.length > 0) {
     Group parentGroup = vpBranchGroup;
     TransformGroup curTg = null;
     for (int n = 0; n < tgArray.length; n++) {
       curTg = tgArray[n];
       parentGroup.addChild(curTg);
       parentGroup = curTg;
     }
     tgArray[tgArray.length - 1].addChild(vp);
   } else
     vpBranchGroup.addChild(vp);
   return vpBranchGroup;
 }
 protected void addCanvas3D(Canvas3D c3d) {
   setLayout(new BorderLayout());
   add(c3d, BorderLayout.CENTER);
   doLayout();
 }
 protected VirtualUniverse createVirtualUniverse() {
   return new VirtualUniverse();
 }
 protected void saveCommandLineArguments(String[] szArgs) {
   m_szCommandLineArray = szArgs;
 }
 protected String[] getCommandLineArguments() {
   return m_szCommandLineArray;
 }

}


      </source>
   
  
 
  



KeyNavigatorApp renders a simple landscape

   <source lang="java">

/*

* @(#)KeyNavigatorApp.java 1.0 99/04/15 11:42:40
* 
* Copyright (c) 1996-1999 Sun Microsystems, Inc. All Rights Reserved.
* 
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
* 
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
* 
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear facility.
* Licensee represents and warrants that it will not use or redistribute the
* Software for such purposes.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.GeometryArray; import javax.media.j3d.IndexedTriangleArray; import javax.media.j3d.LineArray; import javax.media.j3d.Link; import javax.media.j3d.Shape3D; import javax.media.j3d.SharedGroup; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior; import com.sun.j3d.utils.universe.SimpleUniverse; // KeyNavigatorApp renders a simple landscape public class KeyNavigatorApp extends Applet {

 Shape3D createPyramid() {
   IndexedTriangleArray pyGeom = new IndexedTriangleArray(5,
       GeometryArray.COORDINATES | GeometryArray.COLOR_3, 12);
   pyGeom.setCoordinate(0, new Point3f(0.0f, 0.7f, 0.0f));
   pyGeom.setCoordinate(1, new Point3f(-0.4f, 0.0f, -0.4f));
   pyGeom.setCoordinate(2, new Point3f(-0.4f, 0.0f, 0.4f));
   pyGeom.setCoordinate(3, new Point3f(0.4f, 0.0f, 0.4f));
   pyGeom.setCoordinate(4, new Point3f(0.4f, 0.0f, -0.4f));
   pyGeom.setCoordinateIndex(0, 0);
   pyGeom.setCoordinateIndex(1, 1);
   pyGeom.setCoordinateIndex(2, 2);
   pyGeom.setCoordinateIndex(3, 0);
   pyGeom.setCoordinateIndex(4, 2);
   pyGeom.setCoordinateIndex(5, 3);
   pyGeom.setCoordinateIndex(6, 0);
   pyGeom.setCoordinateIndex(7, 3);
   pyGeom.setCoordinateIndex(8, 4);
   pyGeom.setCoordinateIndex(9, 0);
   pyGeom.setCoordinateIndex(10, 4);
   pyGeom.setCoordinateIndex(11, 1);
   Color3f c = new Color3f(0.6f, 0.5f, 0.55f);
   pyGeom.setColor(0, c);
   pyGeom.setColor(1, c);
   pyGeom.setColor(2, c);
   pyGeom.setColor(3, c);
   pyGeom.setColor(4, c);
   Shape3D pyramid = new Shape3D(pyGeom);
   return pyramid;
 }
 Shape3D createLand() {
   LineArray landGeom = new LineArray(44, GeometryArray.COORDINATES
       | GeometryArray.COLOR_3);
   float l = -50.0f;
   for (int c = 0; c < 44; c += 4) {
     landGeom.setCoordinate(c + 0, new Point3f(-50.0f, 0.0f, l));
     landGeom.setCoordinate(c + 1, new Point3f(50.0f, 0.0f, l));
     landGeom.setCoordinate(c + 2, new Point3f(l, 0.0f, -50.0f));
     landGeom.setCoordinate(c + 3, new Point3f(l, 0.0f, 50.0f));
     l += 10.0f;
   }
   Color3f c = new Color3f(0.1f, 0.8f, 0.1f);
   for (int i = 0; i < 44; i++)
     landGeom.setColor(i, c);
   return new Shape3D(landGeom);
 }
 public BranchGroup createSceneGraph(SimpleUniverse su) {
   // Create the root of the branch graph
   TransformGroup vpTrans = null;
   BranchGroup objRoot = new BranchGroup();
   Vector3f translate = new Vector3f();
   Transform3D T3D = new Transform3D();
   TransformGroup TG = null;
   objRoot.addChild(createLand());
   SharedGroup share = new SharedGroup();
   share.addChild(createPyramid());
   float[][] position = { { 0.0f, 0.0f, -3.0f }, { 6.0f, 0.0f, 0.0f },
       { 6.0f, 0.0f, 6.0f }, { 3.0f, 0.0f, -10.0f },
       { 13.0f, 0.0f, -30.0f }, { -13.0f, 0.0f, 30.0f },
       { -13.0f, 0.0f, 23.0f }, { 13.0f, 0.0f, 3.0f } };
   for (int i = 0; i < position.length; i++) {
     translate.set(position[i]);
     T3D.setTranslation(translate);
     TG = new TransformGroup(T3D);
     TG.addChild(new Link(share));
     objRoot.addChild(TG);
   }
   vpTrans = su.getViewingPlatform().getViewPlatformTransform();
   translate.set(0.0f, 0.3f, 0.0f);
   T3D.setTranslation(translate);
   vpTrans.setTransform(T3D);
   KeyNavigatorBehavior keyNavBeh = new KeyNavigatorBehavior(vpTrans);
   keyNavBeh
       .setSchedulingBounds(new BoundingSphere(new Point3d(), 1000.0));
   objRoot.addChild(keyNavBeh);
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 } // end of CreateSceneGraph method of KeyNavigatorApp
 public KeyNavigatorApp() {
   setLayout(new BorderLayout());
   Canvas3D canvas3D = new Canvas3D(null);
   add("Center", canvas3D);
   // SimpleUniverse is a Convenience Utility class
   SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
   BranchGroup scene = createSceneGraph(simpleU);
   simpleU.addBranchGraph(scene);
 } // end of KeyNavigatorApp (constructor)
 //  The following allows this to be run as an application
 //  as well as an applet
 public static void main(String[] args) {
   System.out
       .print("KeyNavigatorApp.java \n- a demonstration of the KeyNavigatorBehavior ");
   System.out
       .println("class to provide keyboard navigation in a Java 3D scene.");
   System.out
       .println("When the app loads, you can use the arrow keys to move.");
   System.out
       .println("This is an example progam from The Java 3D API Tutorial.");
   System.out.println("The Java 3D Tutorial is available on the web at:");
   System.out.println("http://www.sun.ru/desktop/java3d/collateral");
   Frame frame = new MainFrame(new KeyNavigatorApp(), 256, 256);
 } // end of main (method of KeyNavigatorApp)

} // end of class KeyNavigatorApp


      </source>
   
  
 
  



MouseBehaviorApp renders a single, interactively rotatable,translatable, and zoomable ColorCube object

   <source lang="java">

/*

*      @(#)MouseBehaviorApp.java 1.0 99/03/25 11:42:40
*
* Copyright (c) 1996-1999 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.*; import com.sun.j3d.utils.behaviors.mouse.*; import javax.media.j3d.*; import javax.vecmath.*; import java.awt.event.*; import java.util.Enumeration; // MouseBehaviorApp renders a single, interactively rotatable, // traslatable, and zoomable ColorCube object. public class MouseBehaviorApp extends Applet {

   public BranchGroup createSceneGraph() {
 // Create the root of the branch graph
 BranchGroup objRoot = new BranchGroup();
       TransformGroup objTransform = new TransformGroup();
       objTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
       objTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
       objRoot.addChild(objTransform);
       objTransform.addChild(new ColorCube(0.4));
       objRoot.addChild(new Axis());
       MouseRotate myMouseRotate = new MouseRotate();
       myMouseRotate.setTransformGroup(objTransform);
       myMouseRotate.setSchedulingBounds(new BoundingSphere());
       objRoot.addChild(myMouseRotate);
       MouseTranslate myMouseTranslate = new MouseTranslate();
       myMouseTranslate.setTransformGroup(objTransform);
       myMouseTranslate.setSchedulingBounds(new BoundingSphere());
       objRoot.addChild(myMouseTranslate);
       MouseZoom myMouseZoom = new MouseZoom();
       myMouseZoom.setTransformGroup(objTransform);
       myMouseZoom.setSchedulingBounds(new BoundingSphere());
       objRoot.addChild(myMouseZoom);
 // Let Java 3D perform optimizations on this scene graph.
       objRoot.rupile();
 return objRoot;
   } // end of CreateSceneGraph method of MouseBehaviorApp
   // Create a simple scene and attach it to the virtual universe
   public MouseBehaviorApp() {
       setLayout(new BorderLayout());
       Canvas3D canvas3D = new Canvas3D(null);
       add("Center", canvas3D);
       BranchGroup scene = createSceneGraph();
       // SimpleUniverse is a Convenience Utility class
       SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
 // This will move the ViewPlatform back a bit so the
 // objects in the scene can be viewed.
       simpleU.getViewingPlatform().setNominalViewingTransform();
       simpleU.addBranchGraph(scene);
   } // end of MouseBehaviorApp (constructor)
   //  The following allows this to be run as an application
   //  as well as an applet
   public static void main(String[] args) {
       System.out.print("MouseBehaviorApp.java \n- a demonstration of using the mouse ");
       System.out.println("behavior utility classes to provide interaction in a Java 3D scene.");
       System.out.println("Hold the mouse button while moving the mouse to make the cube move.");
       System.out.println("     left mouse button      - rotate cube");
       System.out.println("     right mouse button     - translate cube");
       System.out.println("     Alt+left mouse button  - zoom cube");
       System.out.println("This is a simple example progam from The Java 3D API Tutorial.");
       System.out.println("The Java 3D Tutorial is available on the web at:");
       System.out.println("http://www.sun.ru/desktop/java3d/collateral");
       Frame frame = new MainFrame(new MouseBehaviorApp(), 256, 256);
   } // end of main (method of MouseBehaviorApp)

} // end of class MouseBehaviorApp

/*

* Getting Started with the Java 3D API written in Java 3D
* 
* This program demonstrates: 1. writing a visual object class In this program,
* Axis class defines a visual object This particular class extends Shape3D See
* the text for a discussion. 2. Using LineArray to draw 3D lines.
*/

class Axis extends Shape3D {

 ////////////////////////////////////////////
 //
 // create axis visual object
 //
 public Axis() {
   this.setGeometry(createGeometry());
 }
 private Geometry createGeometry() {
   // create line for X axis
   IndexedLineArray axisLines = new IndexedLineArray(18,
       GeometryArray.COORDINATES, 30);
   axisLines.setCoordinate(0, new Point3f(-1.0f, 0.0f, 0.0f));
   axisLines.setCoordinate(1, new Point3f(1.0f, 0.0f, 0.0f));
   axisLines.setCoordinate(2, new Point3f(0.9f, 0.1f, 0.1f));
   axisLines.setCoordinate(3, new Point3f(0.9f, -0.1f, 0.1f));
   axisLines.setCoordinate(4, new Point3f(0.9f, 0.1f, -0.1f));
   axisLines.setCoordinate(5, new Point3f(0.9f, -0.1f, -0.1f));
   axisLines.setCoordinate(6, new Point3f(0.0f, -1.0f, 0.0f));
   axisLines.setCoordinate(7, new Point3f(0.0f, 1.0f, 0.0f));
   axisLines.setCoordinate(8, new Point3f(0.1f, 0.9f, 0.1f));
   axisLines.setCoordinate(9, new Point3f(-0.1f, 0.9f, 0.1f));
   axisLines.setCoordinate(10, new Point3f(0.1f, 0.9f, -0.1f));
   axisLines.setCoordinate(11, new Point3f(-0.1f, 0.9f, -0.1f));
   axisLines.setCoordinate(12, new Point3f(0.0f, 0.0f, -1.0f));
   axisLines.setCoordinate(13, new Point3f(0.0f, 0.0f, 1.0f));
   axisLines.setCoordinate(14, new Point3f(0.1f, 0.1f, 0.9f));
   axisLines.setCoordinate(15, new Point3f(-0.1f, 0.1f, 0.9f));
   axisLines.setCoordinate(16, new Point3f(0.1f, -0.1f, 0.9f));
   axisLines.setCoordinate(17, new Point3f(-0.1f, -0.1f, 0.9f));
   axisLines.setCoordinateIndex(0, 0);
   axisLines.setCoordinateIndex(1, 1);
   axisLines.setCoordinateIndex(2, 2);
   axisLines.setCoordinateIndex(3, 1);
   axisLines.setCoordinateIndex(4, 3);
   axisLines.setCoordinateIndex(5, 1);
   axisLines.setCoordinateIndex(6, 4);
   axisLines.setCoordinateIndex(7, 1);
   axisLines.setCoordinateIndex(8, 5);
   axisLines.setCoordinateIndex(9, 1);
   axisLines.setCoordinateIndex(10, 6);
   axisLines.setCoordinateIndex(11, 7);
   axisLines.setCoordinateIndex(12, 8);
   axisLines.setCoordinateIndex(13, 7);
   axisLines.setCoordinateIndex(14, 9);
   axisLines.setCoordinateIndex(15, 7);
   axisLines.setCoordinateIndex(16, 10);
   axisLines.setCoordinateIndex(17, 7);
   axisLines.setCoordinateIndex(18, 11);
   axisLines.setCoordinateIndex(19, 7);
   axisLines.setCoordinateIndex(20, 12);
   axisLines.setCoordinateIndex(21, 13);
   axisLines.setCoordinateIndex(22, 14);
   axisLines.setCoordinateIndex(23, 13);
   axisLines.setCoordinateIndex(24, 15);
   axisLines.setCoordinateIndex(25, 13);
   axisLines.setCoordinateIndex(26, 16);
   axisLines.setCoordinateIndex(27, 13);
   axisLines.setCoordinateIndex(28, 17);
   axisLines.setCoordinateIndex(29, 13);
   return axisLines;
 } // end of Axis createGeometry()

} // end of class Axis


      </source>
   
  
 
  



MouseNavigatorApp renders a single, interactively rotatable, traslatable, and zoomable ColorCube object

   <source lang="java">

/*

* @(#)MouseNavigatorApp.java 1.0 99/03/25 11:42:40
* 
* Copyright (c) 1996-1999 Sun Microsystems, Inc. All Rights Reserved.
* 
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
* 
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
* 
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear facility.
* Licensee represents and warrants that it will not use or redistribute the
* Software for such purposes.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Geometry; import javax.media.j3d.GeometryArray; import javax.media.j3d.IndexedLineArray; import javax.media.j3d.Shape3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.mouse.MouseBehavior; import com.sun.j3d.utils.behaviors.mouse.MouseRotate; import com.sun.j3d.utils.behaviors.mouse.MouseTranslate; import com.sun.j3d.utils.behaviors.mouse.MouseZoom; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.SimpleUniverse; // MouseNavigatorApp renders a single, interactively rotatable, // traslatable, and zoomable ColorCube object. public class MouseNavigatorApp extends Applet {

 public BranchGroup createSceneGraph(SimpleUniverse su) {
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   TransformGroup vpTrans = null;
   BoundingSphere mouseBounds = null;
   vpTrans = su.getViewingPlatform().getViewPlatformTransform();
   objRoot.addChild(new ColorCube(0.4));
   objRoot.addChild(new Axis());
   mouseBounds = new BoundingSphere(new Point3d(), 1000.0);
   MouseRotate myMouseRotate = new MouseRotate(MouseBehavior.INVERT_INPUT);
   myMouseRotate.setTransformGroup(vpTrans);
   myMouseRotate.setSchedulingBounds(mouseBounds);
   objRoot.addChild(myMouseRotate);
   MouseTranslate myMouseTranslate = new MouseTranslate(
       MouseBehavior.INVERT_INPUT);
   myMouseTranslate.setTransformGroup(vpTrans);
   myMouseTranslate.setSchedulingBounds(mouseBounds);
   objRoot.addChild(myMouseTranslate);
   MouseZoom myMouseZoom = new MouseZoom(MouseBehavior.INVERT_INPUT);
   myMouseZoom.setTransformGroup(vpTrans);
   myMouseZoom.setSchedulingBounds(mouseBounds);
   objRoot.addChild(myMouseZoom);
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 } // end of CreateSceneGraph method of MouseNavigatorApp
 // Create a simple scene and attach it to the virtual universe
 public MouseNavigatorApp() {
   setLayout(new BorderLayout());
   Canvas3D canvas3D = new Canvas3D(null);
   add("Center", canvas3D);
   // SimpleUniverse is a Convenience Utility class
   SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
   BranchGroup scene = createSceneGraph(simpleU);
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   simpleU.getViewingPlatform().setNominalViewingTransform();
   simpleU.addBranchGraph(scene);
 } // end of MouseNavigatorApp (constructor)
 //  The following allows this to be run as an application
 //  as well as an applet
 public static void main(String[] args) {
   System.out
       .print("MouseNavigatorApp.java \n- a demonstration of using the mouse ");
   System.out
       .println("behavior utility classes to provide navigational interaction in a Java 3D scene.");
   System.out
       .println("Hold the mouse button while moving the mouse to move.");
   System.out.println("     left mouse button      - rotate");
   System.out.println("     right mouse button     - translate");
   System.out.println("     Alt+left mouse button  - zoom");
   System.out
       .println("This is a simple example progam from The Java 3D API Tutorial.");
   System.out.println("The Java 3D Tutorial is available on the web at:");
   System.out.println("http://www.sun.ru/desktop/java3d/collateral");
   Frame frame = new MainFrame(new MouseNavigatorApp(), 256, 256);
 } // end of main (method of MouseNavigatorApp)

} // end of class MouseNavigatorApp /*

* Getting Started with the Java 3D API written in Java 3D
* 
* This program demonstrates: 1. writing a visual object class In this program,
* Axis class defines a visual object This particular class extends Shape3D See
* the text for a discussion. 2. Using LineArray to draw 3D lines.
*/

class Axis extends Shape3D {

 ////////////////////////////////////////////
 //
 // create axis visual object
 //
 public Axis() {
   this.setGeometry(createGeometry());
 }
 private Geometry createGeometry() {
   // create line for X axis
   IndexedLineArray axisLines = new IndexedLineArray(18,
       GeometryArray.COORDINATES, 30);
   axisLines.setCoordinate(0, new Point3f(-1.0f, 0.0f, 0.0f));
   axisLines.setCoordinate(1, new Point3f(1.0f, 0.0f, 0.0f));
   axisLines.setCoordinate(2, new Point3f(0.9f, 0.1f, 0.1f));
   axisLines.setCoordinate(3, new Point3f(0.9f, -0.1f, 0.1f));
   axisLines.setCoordinate(4, new Point3f(0.9f, 0.1f, -0.1f));
   axisLines.setCoordinate(5, new Point3f(0.9f, -0.1f, -0.1f));
   axisLines.setCoordinate(6, new Point3f(0.0f, -1.0f, 0.0f));
   axisLines.setCoordinate(7, new Point3f(0.0f, 1.0f, 0.0f));
   axisLines.setCoordinate(8, new Point3f(0.1f, 0.9f, 0.1f));
   axisLines.setCoordinate(9, new Point3f(-0.1f, 0.9f, 0.1f));
   axisLines.setCoordinate(10, new Point3f(0.1f, 0.9f, -0.1f));
   axisLines.setCoordinate(11, new Point3f(-0.1f, 0.9f, -0.1f));
   axisLines.setCoordinate(12, new Point3f(0.0f, 0.0f, -1.0f));
   axisLines.setCoordinate(13, new Point3f(0.0f, 0.0f, 1.0f));
   axisLines.setCoordinate(14, new Point3f(0.1f, 0.1f, 0.9f));
   axisLines.setCoordinate(15, new Point3f(-0.1f, 0.1f, 0.9f));
   axisLines.setCoordinate(16, new Point3f(0.1f, -0.1f, 0.9f));
   axisLines.setCoordinate(17, new Point3f(-0.1f, -0.1f, 0.9f));
   axisLines.setCoordinateIndex(0, 0);
   axisLines.setCoordinateIndex(1, 1);
   axisLines.setCoordinateIndex(2, 2);
   axisLines.setCoordinateIndex(3, 1);
   axisLines.setCoordinateIndex(4, 3);
   axisLines.setCoordinateIndex(5, 1);
   axisLines.setCoordinateIndex(6, 4);
   axisLines.setCoordinateIndex(7, 1);
   axisLines.setCoordinateIndex(8, 5);
   axisLines.setCoordinateIndex(9, 1);
   axisLines.setCoordinateIndex(10, 6);
   axisLines.setCoordinateIndex(11, 7);
   axisLines.setCoordinateIndex(12, 8);
   axisLines.setCoordinateIndex(13, 7);
   axisLines.setCoordinateIndex(14, 9);
   axisLines.setCoordinateIndex(15, 7);
   axisLines.setCoordinateIndex(16, 10);
   axisLines.setCoordinateIndex(17, 7);
   axisLines.setCoordinateIndex(18, 11);
   axisLines.setCoordinateIndex(19, 7);
   axisLines.setCoordinateIndex(20, 12);
   axisLines.setCoordinateIndex(21, 13);
   axisLines.setCoordinateIndex(22, 14);
   axisLines.setCoordinateIndex(23, 13);
   axisLines.setCoordinateIndex(24, 15);
   axisLines.setCoordinateIndex(25, 13);
   axisLines.setCoordinateIndex(26, 16);
   axisLines.setCoordinateIndex(27, 13);
   axisLines.setCoordinateIndex(28, 17);
   axisLines.setCoordinateIndex(29, 13);
   return axisLines;
 } // end of Axis createGeometry()

} // end of class Axis


      </source>
   
  
 
  



MousePickApp renders two interactively rotatable cubes

   <source lang="java">

/*

* @(#)MousePickApp.java 1.0 99/03/25 11:42:40
* 
* Copyright (c) 1996-1999 Sun Microsystems, Inc. All Rights Reserved.
* 
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
* 
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
* 
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear facility.
* Licensee represents and warrants that it will not use or redistribute the
* Software for such purposes.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.picking.PickRotateBehavior; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.SimpleUniverse; // MousePickApp renders two interactively rotatable cubes. public class MousePickApp extends Applet {

 public BranchGroup createSceneGraph(Canvas3D canvas) {
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   TransformGroup objRotate = null;
   PickRotateBehavior pickRotate = null;
   Transform3D transform = new Transform3D();
   BoundingSphere behaveBounds = new BoundingSphere();
   // create ColorCube and PickRotateBehavior objects
   transform.setTranslation(new Vector3f(-0.6f, 0.0f, -0.6f));
   objRotate = new TransformGroup(transform);
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   objRotate.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
   objRoot.addChild(objRotate);
   objRotate.addChild(new ColorCube(0.4));
   pickRotate = new PickRotateBehavior(objRoot, canvas, behaveBounds);
   objRoot.addChild(pickRotate);
   // add a second ColorCube object to the scene graph
   transform.setTranslation(new Vector3f(0.6f, 0.0f, -0.6f));
   objRotate = new TransformGroup(transform);
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   objRotate.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
   objRoot.addChild(objRotate);
   objRotate.addChild(new ColorCube(0.4));
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 } // end of CreateSceneGraph method of MousePickApp
 // Create a simple scene and attach it to the virtual universe
 public MousePickApp() {
   setLayout(new BorderLayout());
   Canvas3D canvas3D = new Canvas3D(null);
   add("Center", canvas3D);
   // SimpleUniverse is a Convenience Utility class
   SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
   BranchGroup scene = createSceneGraph(canvas3D);
   // This will move the ViewPlatform back a bit
   simpleU.getViewingPlatform().setNominalViewingTransform();
   simpleU.addBranchGraph(scene);
 } // end of MousePickApp (constructor)
 //  The following allows this to be run as an application or as an applet
 public static void main(String[] args) {
   System.out
       .print("MousePickApp.java \n- a demonstration of using the PickRotateBehavior ");
   System.out
       .println("utility class to provide interaction in a Java 3D scene.");
   System.out
       .println("Hold the mouse button over a cube then move the mouse to make that cube rotate.");
   System.out
       .println("This is a simple example progam from The Java 3D API Tutorial.");
   System.out.println("The Java 3D Tutorial is available on the web at:");
   System.out.println("http://www.sun.ru/desktop/java3d/collateral");
   Frame frame = new MainFrame(new MousePickApp(), 256, 256);
 } // end of main (method of MousePickApp)

} // end of class MousePickApp


      </source>
   
  
 
  



MouseRotate2App renders a single, interactively rotatable cube

   <source lang="java">

/*

* @(#)MouseRotate2App.java 1.0 99/03/25 11:42:40
* 
* Copyright (c) 1996-1999 Sun Microsystems, Inc. All Rights Reserved.
* 
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
* 
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
* 
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear facility.
* Licensee represents and warrants that it will not use or redistribute the
* Software for such purposes.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.mouse.MouseRotate; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.SimpleUniverse; // MouseRotate2App renders a single, interactively rotatable cube. public class MouseRotate2App extends Applet {

 public BranchGroup createSceneGraph() {
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   TransformGroup objRotate = null;
   MouseRotate myMouseRotate = null;
   Transform3D transform = new Transform3D();
   // create ColorCube and MouseRotate behvaior objects
   transform.setTranslation(new Vector3f(-0.6f, 0.0f, -0.6f));
   objRotate = new TransformGroup(transform);
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   objRoot.addChild(objRotate);
   objRotate.addChild(new ColorCube(0.4));
   myMouseRotate = new MouseRotate();
   myMouseRotate.setTransformGroup(objRotate);
   myMouseRotate.setSchedulingBounds(new BoundingSphere());
   objRoot.addChild(myMouseRotate);
   // create ColorCube and MouseRotate behvaior objects
   transform.setTranslation(new Vector3f(0.6f, 0.0f, -0.6f));
   objRotate = new TransformGroup(transform);
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   objRoot.addChild(objRotate);
   objRotate.addChild(new ColorCube(0.4));
   myMouseRotate = new MouseRotate();
   myMouseRotate.setTransformGroup(objRotate);
   myMouseRotate.setSchedulingBounds(new BoundingSphere());
   objRoot.addChild(myMouseRotate);
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 } // end of CreateSceneGraph method of MouseRotate2App
 // Create a simple scene and attach it to the virtual universe
 public MouseRotate2App() {
   setLayout(new BorderLayout());
   Canvas3D canvas3D = new Canvas3D(null);
   add("Center", canvas3D);
   BranchGroup scene = createSceneGraph();
   // SimpleUniverse is a Convenience Utility class
   SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   simpleU.getViewingPlatform().setNominalViewingTransform();
   simpleU.addBranchGraph(scene);
 } // end of MouseRotate2App (constructor)
 //  The following allows this to be run as an application
 //  as well as an applet
 public static void main(String[] args) {
   System.out
       .print("MouseRotate2App.java \n- a demonstration of using the MouseRotate ");
   System.out
       .println("utility behavior class to provide interaction in a Java 3D scene.");
   System.out
       .println("Hold the mouse button while moving the mouse to make the cube rotate.");
   System.out
       .println("This is a simple example progam from The Java 3D API Tutorial.");
   System.out.println("The Java 3D Tutorial is available on the web at:");
   System.out.println("http://www.sun.ru/desktop/java3d/collateral");
   Frame frame = new MainFrame(new MouseRotate2App(), 256, 256);
 } // end of main (method of MouseRotate2App)

} // end of class MouseRotate2App


      </source>
   
  
 
  



MouseRotateApp renders a single, interactively rotatable cube

   <source lang="java">

/*

* @(#)MouseRotateApp.java 1.0 99/03/25 11:42:40
* 
* Copyright (c) 1996-1999 Sun Microsystems, Inc. All Rights Reserved.
* 
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
* 
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
* 
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear facility.
* Licensee represents and warrants that it will not use or redistribute the
* Software for such purposes.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Geometry; import javax.media.j3d.GeometryArray; import javax.media.j3d.IndexedLineArray; import javax.media.j3d.Shape3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Point3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.mouse.MouseRotate; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.SimpleUniverse; // MouseRotateApp renders a single, interactively rotatable cube. public class MouseRotateApp extends Applet {

 public BranchGroup createSceneGraph() {
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   TransformGroup objRotate = new TransformGroup();
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   objRoot.addChild(objRotate);
   objRotate.addChild(new ColorCube(0.4));
   objRoot.addChild(new Axis());
   MouseRotate myMouseRotate = new MouseRotate();
   myMouseRotate.setTransformGroup(objRotate);
   myMouseRotate.setSchedulingBounds(new BoundingSphere());
   objRoot.addChild(myMouseRotate);
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 } // end of CreateSceneGraph method of MouseRotateApp
 // Create a simple scene and attach it to the virtual universe
 public MouseRotateApp() {
   setLayout(new BorderLayout());
   Canvas3D canvas3D = new Canvas3D(null);
   add("Center", canvas3D);
   BranchGroup scene = createSceneGraph();
   // SimpleUniverse is a Convenience Utility class
   SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   simpleU.getViewingPlatform().setNominalViewingTransform();
   simpleU.addBranchGraph(scene);
 } // end of MouseRotateApp (constructor)
 //  The following allows this to be run as an application
 //  as well as an applet
 public static void main(String[] args) {
   System.out
       .print("MouseRotateApp.java \n- a demonstration of using the MouseRotate ");
   System.out
       .println("utility behavior class to provide interaction in a Java 3D scene.");
   System.out
       .println("Hold the mouse button while moving the mouse to make the cube rotate.");
   System.out
       .println("This is a simple example progam from The Java 3D API Tutorial.");
   System.out.println("The Java 3D Tutorial is available on the web at:");
   System.out.println("http://www.sun.ru/desktop/java3d/collateral");
   Frame frame = new MainFrame(new MouseRotateApp(), 256, 256);
 } // end of main (method of MouseRotateApp)

} // end of class MouseRotateApp /*

* Getting Started with the Java 3D API written in Java 3D
* 
* This program demonstrates: 1. writing a visual object class In this program,
* Axis class defines a visual object This particular class extends Shape3D See
* the text for a discussion. 2. Using LineArray to draw 3D lines.
*/

class Axis extends Shape3D {

 ////////////////////////////////////////////
 //
 // create axis visual object
 //
 public Axis() {
   this.setGeometry(createGeometry());
 }
 private Geometry createGeometry() {
   // create line for X axis
   IndexedLineArray axisLines = new IndexedLineArray(18,
       GeometryArray.COORDINATES, 30);
   axisLines.setCoordinate(0, new Point3f(-1.0f, 0.0f, 0.0f));
   axisLines.setCoordinate(1, new Point3f(1.0f, 0.0f, 0.0f));
   axisLines.setCoordinate(2, new Point3f(0.9f, 0.1f, 0.1f));
   axisLines.setCoordinate(3, new Point3f(0.9f, -0.1f, 0.1f));
   axisLines.setCoordinate(4, new Point3f(0.9f, 0.1f, -0.1f));
   axisLines.setCoordinate(5, new Point3f(0.9f, -0.1f, -0.1f));
   axisLines.setCoordinate(6, new Point3f(0.0f, -1.0f, 0.0f));
   axisLines.setCoordinate(7, new Point3f(0.0f, 1.0f, 0.0f));
   axisLines.setCoordinate(8, new Point3f(0.1f, 0.9f, 0.1f));
   axisLines.setCoordinate(9, new Point3f(-0.1f, 0.9f, 0.1f));
   axisLines.setCoordinate(10, new Point3f(0.1f, 0.9f, -0.1f));
   axisLines.setCoordinate(11, new Point3f(-0.1f, 0.9f, -0.1f));
   axisLines.setCoordinate(12, new Point3f(0.0f, 0.0f, -1.0f));
   axisLines.setCoordinate(13, new Point3f(0.0f, 0.0f, 1.0f));
   axisLines.setCoordinate(14, new Point3f(0.1f, 0.1f, 0.9f));
   axisLines.setCoordinate(15, new Point3f(-0.1f, 0.1f, 0.9f));
   axisLines.setCoordinate(16, new Point3f(0.1f, -0.1f, 0.9f));
   axisLines.setCoordinate(17, new Point3f(-0.1f, -0.1f, 0.9f));
   axisLines.setCoordinateIndex(0, 0);
   axisLines.setCoordinateIndex(1, 1);
   axisLines.setCoordinateIndex(2, 2);
   axisLines.setCoordinateIndex(3, 1);
   axisLines.setCoordinateIndex(4, 3);
   axisLines.setCoordinateIndex(5, 1);
   axisLines.setCoordinateIndex(6, 4);
   axisLines.setCoordinateIndex(7, 1);
   axisLines.setCoordinateIndex(8, 5);
   axisLines.setCoordinateIndex(9, 1);
   axisLines.setCoordinateIndex(10, 6);
   axisLines.setCoordinateIndex(11, 7);
   axisLines.setCoordinateIndex(12, 8);
   axisLines.setCoordinateIndex(13, 7);
   axisLines.setCoordinateIndex(14, 9);
   axisLines.setCoordinateIndex(15, 7);
   axisLines.setCoordinateIndex(16, 10);
   axisLines.setCoordinateIndex(17, 7);
   axisLines.setCoordinateIndex(18, 11);
   axisLines.setCoordinateIndex(19, 7);
   axisLines.setCoordinateIndex(20, 12);
   axisLines.setCoordinateIndex(21, 13);
   axisLines.setCoordinateIndex(22, 14);
   axisLines.setCoordinateIndex(23, 13);
   axisLines.setCoordinateIndex(24, 15);
   axisLines.setCoordinateIndex(25, 13);
   axisLines.setCoordinateIndex(26, 16);
   axisLines.setCoordinateIndex(27, 13);
   axisLines.setCoordinateIndex(28, 17);
   axisLines.setCoordinateIndex(29, 13);
   return axisLines;
 } // end of Axis createGeometry()

} // end of class Axis


      </source>
   
  
 
  



Navigation around the scene

   <source lang="java">

/* Essential Java 3D Fast Ian Palmer Publisher: Springer-Verlag ISBN: 1-85233-394-4

  • /

import java.awt.BorderLayout; import java.awt.Button; import java.awt.Frame; import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.BoundingLeaf; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.media.j3d.ViewPlatform; import javax.media.j3d.VirtualUniverse; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior; import com.sun.j3d.utils.geometry.Box; /**

* This application uses the mouse keyboard utility class to allow navigation
* around the scene. The scene consists of a yellow and red cube.
* 
* @author I.J.Palmer
* @version 1.0
*/

public class SimpleKeyNav extends Frame implements ActionListener {

 protected Canvas3D myCanvas3D = new Canvas3D(null);
 protected Button exitButton = new Button("Exit");
 protected BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0,
     0.0), 100.0);
 /**
  * Build the view branch of the scene graph. In this case a key navigation
  * utility object is created and associated with the view transform so that
  * the view can be changed via the keyboard.
  * 
  * @return BranchGroup that is the root of the view branch
  */
 protected BranchGroup buildViewBranch(Canvas3D c) {
   BranchGroup viewBranch = new BranchGroup();
   Transform3D viewXfm = new Transform3D();
   viewXfm.set(new Vector3f(0.0f, 0.0f, 10.0f));
   TransformGroup viewXfmGroup = new TransformGroup(viewXfm);
   viewXfmGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   viewXfmGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   BoundingSphere movingBounds = new BoundingSphere(new Point3d(0.0, 0.0,
       0.0), 100.0);
   BoundingLeaf boundLeaf = new BoundingLeaf(movingBounds);
   ViewPlatform myViewPlatform = new ViewPlatform();
   viewXfmGroup.addChild(boundLeaf);
   PhysicalBody myBody = new PhysicalBody();
   PhysicalEnvironment myEnvironment = new PhysicalEnvironment();
   viewXfmGroup.addChild(myViewPlatform);
   viewBranch.addChild(viewXfmGroup);
   View myView = new View();
   myView.addCanvas3D(c);
   myView.attachViewPlatform(myViewPlatform);
   myView.setPhysicalBody(myBody);
   myView.setPhysicalEnvironment(myEnvironment);
   KeyNavigatorBehavior keyNav = new KeyNavigatorBehavior(viewXfmGroup);
   keyNav.setSchedulingBounds(movingBounds);
   viewBranch.addChild(keyNav);
   return viewBranch;
 }
 /**
  * Add some lights to the scene graph
  * 
  * @param b
  *            BranchGroup that the lights are added to
  */
 protected void addLights(BranchGroup b) {
   // Create a bounds for the background and lights
   // Set up the global lights
   Color3f ambLightColour = new Color3f(0.5f, 0.5f, 0.5f);
   AmbientLight ambLight = new AmbientLight(ambLightColour);
   ambLight.setInfluencingBounds(bounds);
   Color3f dirLightColour = new Color3f(1.0f, 1.0f, 1.0f);
   Vector3f dirLightDir = new Vector3f(-1.0f, -1.0f, -1.0f);
   DirectionalLight dirLight = new DirectionalLight(dirLightColour,
       dirLightDir);
   dirLight.setInfluencingBounds(bounds);
   b.addChild(ambLight);
   b.addChild(dirLight);
 }
 /**
  * Build the content branch for the scene graph
  * 
  * @return BranchGroup that is the root of the content
  */
 protected BranchGroup buildContentBranch() {
   //Create the appearance an appearance for the two cubes
   Appearance app1 = new Appearance();
   Appearance app2 = new Appearance();
   Color3f ambientColour1 = new Color3f(1.0f, 0.0f, 0.0f);
   Color3f ambientColour2 = new Color3f(1.0f, 1.0f, 0.0f);
   Color3f emissiveColour = new Color3f(0.0f, 0.0f, 0.0f);
   Color3f specularColour = new Color3f(1.0f, 1.0f, 1.0f);
   Color3f diffuseColour1 = new Color3f(1.0f, 0.0f, 0.0f);
   Color3f diffuseColour2 = new Color3f(1.0f, 1.0f, 0.0f);
   float shininess = 20.0f;
   app1.setMaterial(new Material(ambientColour1, emissiveColour,
       diffuseColour1, specularColour, shininess));
   app2.setMaterial(new Material(ambientColour2, emissiveColour,
       diffuseColour2, specularColour, shininess));
   //Make two cubes
   Box leftCube = new Box(1.0f, 1.0f, 1.0f, app1);
   Box rightCube = new Box(1.0f, 1.0f, 1.0f, app2);
   BranchGroup contentBranch = new BranchGroup();
   addLights(contentBranch);
   //Put it all together
   Transform3D leftGroupXfm = new Transform3D();
   leftGroupXfm.set(new Vector3d(-1.5, 0.0, 0.0));
   TransformGroup leftGroup = new TransformGroup(leftGroupXfm);
   Transform3D rightGroupXfm = new Transform3D();
   rightGroupXfm.set(new Vector3d(1.5, 0.0, 0.0));
   TransformGroup rightGroup = new TransformGroup(rightGroupXfm);
   leftGroup.addChild(leftCube);
   rightGroup.addChild(rightCube);
   contentBranch.addChild(leftGroup);
   contentBranch.addChild(rightGroup);
   return contentBranch;
 }
 /**
  * Use the action event of the exit button to end the application.
  */
 public void actionPerformed(ActionEvent e) {
   dispose();
   System.exit(0);
 }
 public SimpleKeyNav() {
   VirtualUniverse myUniverse = new VirtualUniverse();
   Locale myLocale = new Locale(myUniverse);
   myLocale.addBranchGraph(buildViewBranch(myCanvas3D));
   myLocale.addBranchGraph(buildContentBranch());
   setTitle("SimpleKeyNav");
   setSize(400, 400);
   setLayout(new BorderLayout());
   Panel bottom = new Panel();
   bottom.add(exitButton);
   add(BorderLayout.CENTER, myCanvas3D);
   add(BorderLayout.SOUTH, bottom);
   exitButton.addActionListener(this);
   setVisible(true);
 }
 public static void main(String[] args) {
   SimpleKeyNav skn = new SimpleKeyNav();
 }

}


      </source>
   
  
 
  



Oriented Pt Test

   <source lang="java">

/*

* @(#)OrientedPtTest.java 1.10 02/10/21 13:47:48
* 
* Copyright (c) 1996-2002 Sun Microsystems, Inc. All Rights Reserved.
* 
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*  - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*  - Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 
* Neither the name of Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* 
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
* 
* You acknowledge that Software is not designed,licensed or intended for use in
* the design, construction, operation or maintenance of any nuclear facility.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Font; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.Background; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Font3D; import javax.media.j3d.FontExtrusion; import javax.media.j3d.Material; import javax.media.j3d.OrientedShape3D; import javax.media.j3d.Text3D; import javax.media.j3d.TextureAttributes; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.vp.OrbitBehavior; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.geometry.Cone; import com.sun.j3d.utils.geometry.Cylinder; import com.sun.j3d.utils.geometry.Sphere; import com.sun.j3d.utils.image.TextureLoader; import com.sun.j3d.utils.universe.SimpleUniverse; import com.sun.j3d.utils.universe.ViewingPlatform; public class OrientedPtTest extends Applet {

 // setup font stuff
 private String fontName = "TestFont";
 private String textString = "OrientedShape3D";
 float sl = textString.length();
 // paths to texture image files
 private java.net.URL earthImage = null;
 private java.net.URL stoneImage = null;
 private SimpleUniverse u;
 public BranchGroup createSceneGraph() {
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   TransformGroup objScale = new TransformGroup();
   Transform3D textMat = new Transform3D();
   // Assuming uniform size chars, set scale to fit string in view
   textMat.setScale(1.2 / sl);
   objScale.setTransform(textMat);
   // Create the transform group node and initialize it to the
   // identity. Enable the TRANSFORM_WRITE capability so that
   // our behavior code can modify it at runtime. Add it to the
   // root of the subgraph.
   TransformGroup objTrans = new TransformGroup();
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   objRoot.addChild(objTrans);
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   Appearance apText = new Appearance();
   Material m = new Material();
   m.setLightingEnable(true);
   apText.setMaterial(m);
   Appearance apEarth = new Appearance();
   Material mm = new Material();
   mm.setLightingEnable(true);
   apEarth.setMaterial(mm);
   Appearance apStone = new Appearance();
   apStone.setMaterial(mm);
   // create 3D text
   Font3D f3d = new Font3D(new Font(fontName, Font.PLAIN, 2),
       new FontExtrusion());
   Point3f textPt = new Point3f(-sl / 2.0f, 3.0f, 0.0f);
   Text3D txt = new Text3D(f3d, textString, textPt);
   OrientedShape3D textShape = new OrientedShape3D();
   textShape.setGeometry(txt);
   textShape.setAppearance(apText);
   textShape.setAlignmentMode(OrientedShape3D.ROTATE_ABOUT_POINT);
   // text is centered around 0, 3, 0. Make it rotate around 0,5,0
   Point3f rotationPt = new Point3f(0.0f, 5.0f, 0.0f);
   textShape.setRotationPoint(rotationPt);
   objScale.addChild(textShape);
   // also add a small Sphere at the rotation point to
   // show that we are rotating around the right point
   Sphere sphere = new Sphere(0.2f);
   TransformGroup sphereGroup = new TransformGroup();
   Transform3D sphereXform = new Transform3D();
   sphereXform.set(new Vector3f(rotationPt));
   sphereGroup.setTransform(sphereXform);
   sphereGroup.addChild(sphere);
   objScale.addChild(sphereGroup);
   // Create a simple shape leaf node, add it to the scene graph.
   Transform3D cubeMat = new Transform3D();
   TransformGroup cubeTrans = new TransformGroup(cubeMat);
   cubeMat.set(new Vector3d(0.9, 0.0, -1.0));
   cubeTrans.setTransform(cubeMat);
   cubeTrans.addChild(new ColorCube(0.3));
   objTrans.addChild(cubeTrans);
   TextureLoader stoneTex = new TextureLoader(stoneImage,
       new String("RGB"), this);
   if (stoneTex != null)
     apStone.setTexture(stoneTex.getTexture());
   TextureAttributes texAttr = new TextureAttributes();
   texAttr.setTextureMode(TextureAttributes.REPLACE);
   apStone.setTextureAttributes(texAttr);
   Transform3D coneMat = new Transform3D();
   TransformGroup coneTrans = new TransformGroup(coneMat);
   coneMat.set(new Vector3d(0.0, 0.0, 0.0));
   coneTrans.setTransform(coneMat);
   coneTrans.addChild(new Cone(.2f, 0.8f, Cone.GENERATE_NORMALS
       | Cone.GENERATE_TEXTURE_COORDS, apStone));
   objTrans.addChild(coneTrans);
   TextureLoader earthTex = new TextureLoader(earthImage,
       new String("RGB"), this);
   if (earthTex != null)
     apEarth.setTexture(earthTex.getTexture());
   apEarth.setTextureAttributes(texAttr);
   Transform3D cylinderMat = new Transform3D();
   TransformGroup cylinderTrans = new TransformGroup(cylinderMat);
   cylinderMat.set(new Vector3d(-0.9, 0.5, -1.0));
   cylinderTrans.setTransform(cylinderMat);
   cylinderTrans.addChild(new Cylinder(.35f, 2.0f,
       Cylinder.GENERATE_NORMALS | Cylinder.GENERATE_TEXTURE_COORDS,
       apEarth));
   objTrans.addChild(cylinderTrans);
   objTrans.addChild(objScale);
   // Set up the background
   Color3f bgColor = new Color3f(0.05f, 0.05f, 0.5f);
   Background bgNode = new Background(bgColor);
   bgNode.setApplicationBounds(bounds);
   objRoot.addChild(bgNode);
   // Set up the ambient light
   Color3f ambientColor = new Color3f(0.1f, 0.1f, 0.1f);
   AmbientLight ambientLightNode = new AmbientLight(ambientColor);
   ambientLightNode.setInfluencingBounds(bounds);
   objRoot.addChild(ambientLightNode);
   // Set up the directional lights
   Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
   Vector3f light1Direction = new Vector3f(1.0f, 1.0f, 1.0f);
   Color3f light2Color = new Color3f(1.0f, 1.0f, 0.9f);
   Vector3f light2Direction = new Vector3f(-1.0f, -1.0f, -1.0f);
   DirectionalLight light1 = new DirectionalLight(light1Color,
       light1Direction);
   light1.setInfluencingBounds(bounds);
   objRoot.addChild(light1);
   DirectionalLight light2 = new DirectionalLight(light2Color,
       light2Direction);
   light2.setInfluencingBounds(bounds);
   objRoot.addChild(light2);
   apText.setMaterial(mm);
   // Have Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 }
 public OrientedPtTest() {
 }
 public OrientedPtTest(java.net.URL earthURL, java.net.URL stoneURL) {
   earthImage = earthURL;
   stoneImage = stoneURL;
 }
 public void init() {
   // the paths to the image files for an applet
   if (earthImage == null) {
     try {
       earthImage = new java.net.URL(getCodeBase().toString()
           + "/earth.jpg");
     } catch (java.net.MalformedURLException ex) {
       System.out.println(ex.getMessage());
       System.exit(1);
     }
   }
   if (stoneImage == null) {
     try {
       stoneImage = new java.net.URL(getCodeBase().toString()
           + "/stone.jpg");
     } catch (java.net.MalformedURLException ex) {
       System.out.println(ex.getMessage());
       System.exit(1);
     }
   }
   setLayout(new BorderLayout());
   Canvas3D c = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
   add("Center", c);
   // Create a simple scene and attach it to the virtual universe
   BranchGroup scene = createSceneGraph();
   u = new SimpleUniverse(c);
   // add mouse behaviors to the ViewingPlatform
   ViewingPlatform viewingPlatform = u.getViewingPlatform();
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   u.getViewingPlatform().setNominalViewingTransform();
   // add orbit behavior to the viewing platform
   OrbitBehavior orbit = new OrbitBehavior(c, OrbitBehavior.REVERSE_ALL);
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   orbit.setSchedulingBounds(bounds);
   viewingPlatform.setViewPlatformBehavior(orbit);
   u.addBranchGraph(scene);
 }
 public void destroy() {
   u.cleanup();
 }
 //
 // The following allows OrientedPtTest to be run as an application
 // as well as an applet
 //
 public static void main(String[] args) {
   java.net.URL earthURL = null;
   java.net.URL stoneURL = null;
   try {
     // the paths to the image files for an application
     earthURL = new java.net.URL("file:earth.jpg");
     stoneURL = new java.net.URL("file:stone.jpg");
   } catch (java.net.MalformedURLException ex) {
     System.out.println(ex.getMessage());
     System.exit(1);
   }
   new MainFrame(new OrientedPtTest(earthURL, stoneURL), 400, 400);
 }

}


      </source>
   
  
 
  



Oriented Test

   <source lang="java">

/*

* @(#)OrientedTest.java 1.10 02/10/21 13:47:43
* 
* Copyright (c) 1996-2002 Sun Microsystems, Inc. All Rights Reserved.
* 
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*  - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*  - Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 
* Neither the name of Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* 
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
* 
* You acknowledge that Software is not designed,licensed or intended for use in
* the design, construction, operation or maintenance of any nuclear facility.
*/

import java.applet.Applet; import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.Font; import java.awt.GraphicsConfiguration; import java.awt.event.MouseEvent; import java.util.Enumeration; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.Background; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Font3D; import javax.media.j3d.FontExtrusion; import javax.media.j3d.Material; import javax.media.j3d.OrientedShape3D; import javax.media.j3d.Text3D; import javax.media.j3d.TextureAttributes; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.WakeupCriterion; import javax.media.j3d.WakeupOnAWTEvent; import javax.vecmath.Color3f; import javax.vecmath.Matrix4d; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.mouse.MouseBehavior; import com.sun.j3d.utils.behaviors.mouse.MouseTranslate; import com.sun.j3d.utils.behaviors.mouse.MouseZoom; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.geometry.Cone; import com.sun.j3d.utils.geometry.Cylinder; import com.sun.j3d.utils.image.TextureLoader; import com.sun.j3d.utils.universe.SimpleUniverse; import com.sun.j3d.utils.universe.ViewingPlatform; public class OrientedTest extends Applet {

 // setup font stuff
 private String fontName = "TestFont";
 private String textString = "OrientedShape3D";
 float sl = textString.length();
 // paths to texture image files
 private java.net.URL earthImage = null;
 private java.net.URL stoneImage = null;
 private SimpleUniverse u = null;
 public BranchGroup createSceneGraph() {
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   TransformGroup objScale = new TransformGroup();
   Transform3D textMat = new Transform3D();
   // Assuming uniform size chars, set scale to fit string in view
   textMat.setScale(1.2 / sl);
   objScale.setTransform(textMat);
   // Create the transform group node and initialize it to the
   // identity. Enable the TRANSFORM_WRITE capability so that
   // our behavior code can modify it at runtime. Add it to the
   // root of the subgraph.
   TransformGroup objTrans = new TransformGroup();
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   objRoot.addChild(objTrans);
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   Appearance apText = new Appearance();
   Material m = new Material();
   m.setLightingEnable(true);
   apText.setMaterial(m);
   Appearance apEarth = new Appearance();
   Material mm = new Material();
   mm.setLightingEnable(true);
   apEarth.setMaterial(mm);
   Appearance apStone = new Appearance();
   apStone.setMaterial(mm);
   // create 3D text
   Font3D f3d = new Font3D(new Font(fontName, Font.PLAIN, 2),
       new FontExtrusion());
   Text3D txt = new Text3D(f3d, textString, new Point3f(-sl / 2.0f, 3.0f,
       0.0f));
   OrientedShape3D textShape = new OrientedShape3D();
   textShape.setGeometry(txt);
   textShape.setAppearance(apText);
   textShape.setAlignmentAxis(0.0f, 1.0f, 0.0f);
   objScale.addChild(textShape);
   // Create a simple shape leaf node, add it to the scene graph.
   Transform3D cubeMat = new Transform3D();
   TransformGroup cubeTrans = new TransformGroup(cubeMat);
   cubeMat.set(new Vector3d(0.9, 0.0, -1.0));
   cubeTrans.setTransform(cubeMat);
   cubeTrans.addChild(new ColorCube(0.3));
   objTrans.addChild(cubeTrans);
   TextureLoader stoneTex = new TextureLoader(stoneImage,
       new String("RGB"), this);
   if (stoneTex != null)
     apStone.setTexture(stoneTex.getTexture());
   TextureAttributes texAttr = new TextureAttributes();
   texAttr.setTextureMode(TextureAttributes.MODULATE);
   apStone.setTextureAttributes(texAttr);
   Transform3D coneMat = new Transform3D();
   TransformGroup coneTrans = new TransformGroup(coneMat);
   coneMat.set(new Vector3d(0.0, 0.0, 0.0));
   coneTrans.setTransform(coneMat);
   coneTrans.addChild(new Cone(.2f, 0.8f, Cone.GENERATE_NORMALS
       | Cone.GENERATE_TEXTURE_COORDS, apStone));
   objTrans.addChild(coneTrans);
   TextureLoader earthTex = new TextureLoader(earthImage,
       new String("RGB"), this);
   if (earthTex != null)
     apEarth.setTexture(earthTex.getTexture());
   apEarth.setTextureAttributes(texAttr);
   Transform3D cylinderMat = new Transform3D();
   TransformGroup cylinderTrans = new TransformGroup(cylinderMat);
   cylinderMat.set(new Vector3d(-0.9, 0.5, -1.0));
   cylinderTrans.setTransform(cylinderMat);
   cylinderTrans.addChild(new Cylinder(.35f, 2.0f,
       Cylinder.GENERATE_NORMALS | Cylinder.GENERATE_TEXTURE_COORDS,
       apEarth));
   objTrans.addChild(cylinderTrans);
   objTrans.addChild(objScale);
   // Set up the background
   Color3f bgColor = new Color3f(0.05f, 0.05f, 0.5f);
   Background bgNode = new Background(bgColor);
   bgNode.setApplicationBounds(bounds);
   objRoot.addChild(bgNode);
   // Set up the ambient light
   Color3f ambientColor = new Color3f(0.1f, 0.1f, 0.1f);
   AmbientLight ambientLightNode = new AmbientLight(ambientColor);
   ambientLightNode.setInfluencingBounds(bounds);
   objRoot.addChild(ambientLightNode);
   // Set up the directional lights
   Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
   Vector3f light1Direction = new Vector3f(1.0f, 1.0f, 1.0f);
   Color3f light2Color = new Color3f(1.0f, 1.0f, 0.9f);
   Vector3f light2Direction = new Vector3f(-1.0f, -1.0f, -1.0f);
   DirectionalLight light1 = new DirectionalLight(light1Color,
       light1Direction);
   light1.setInfluencingBounds(bounds);
   objRoot.addChild(light1);
   DirectionalLight light2 = new DirectionalLight(light2Color,
       light2Direction);
   light2.setInfluencingBounds(bounds);
   objRoot.addChild(light2);
   apText.setMaterial(mm);
   // Have Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 }
 public OrientedTest() {
 }
 public OrientedTest(java.net.URL earthURL, java.net.URL stoneURL) {
   earthImage = earthURL;
   stoneImage = stoneURL;
 }
 public void init() {
   // the paths to the image files for an applet
   if (earthImage == null) {
     try {
       earthImage = new java.net.URL(getCodeBase().toString()
           + "/earth.jpg");
     } catch (java.net.MalformedURLException ex) {
       System.out.println(ex.getMessage());
       System.exit(1);
     }
   }
   if (stoneImage == null) {
     try {
       stoneImage = new java.net.URL(getCodeBase().toString()
           + "/stone.jpg");
     } catch (java.net.MalformedURLException ex) {
       System.out.println(ex.getMessage());
       System.exit(1);
     }
   }
   setLayout(new BorderLayout());
   GraphicsConfiguration config = SimpleUniverse
       .getPreferredConfiguration();
   Canvas3D c = new Canvas3D(config);
   add("Center", c);
   // Create a simple scene and attach it to the virtual universe
   BranchGroup scene = createSceneGraph();
   u = new SimpleUniverse(c, 4);
   // add mouse behaviors to ViewingPlatform
   ViewingPlatform viewingPlatform = u.getViewingPlatform();
   // there is a special rotate behavior, so can"t use the utility
   // method
   MouseRotateY rotate = new MouseRotateY(MouseRotateY.INVERT_INPUT);
   rotate.setTransformGroup(viewingPlatform.getMultiTransformGroup()
       .getTransformGroup(0));
   BranchGroup rotateBG = new BranchGroup();
   rotateBG.addChild(rotate);
   viewingPlatform.addChild(rotateBG);
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   rotate.setSchedulingBounds(bounds);
   MouseZoom zoom = new MouseZoom(c, MouseZoom.INVERT_INPUT);
   zoom.setTransformGroup(viewingPlatform.getMultiTransformGroup()
       .getTransformGroup(1));
   zoom.setSchedulingBounds(bounds);
   BranchGroup zoomBG = new BranchGroup();
   zoomBG.addChild(zoom);
   viewingPlatform.addChild(zoomBG);
   MouseTranslate translate = new MouseTranslate(c,
       MouseTranslate.INVERT_INPUT);
   translate.setTransformGroup(viewingPlatform.getMultiTransformGroup()
       .getTransformGroup(2));
   translate.setSchedulingBounds(bounds);
   BranchGroup translateBG = new BranchGroup();
   translateBG.addChild(translate);
   viewingPlatform.addChild(translateBG);
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   u.getViewingPlatform().setNominalViewingTransform();
   u.addBranchGraph(scene);
 }
 public void destroy() {
   u.cleanup();
 }
 //
 // The following allows OrientedTest to be run as an application
 // as well as an applet
 //
 public static void main(String[] args) {
   java.net.URL earthURL = null;
   java.net.URL stoneURL = null;
   try {
     // the paths to the image files for an application
     earthURL = new java.net.URL("file:earth.jpg");
     stoneURL = new java.net.URL("file:stone.jpg");
   } catch (java.net.MalformedURLException ex) {
     System.out.println(ex.getMessage());
     System.exit(1);
   }
   new MainFrame(new OrientedTest(earthURL, stoneURL), 400, 400);
 }

} /**

* MouseRotateY is a Java3D behavior object that lets users control the rotation
* of an object via a mouse.
*

* To use this utility, first create a transform group that this rotate behavior * will operate on. Then,

*

*
 * 
 * 
 * MouseRotateY behavior = new MouseRotateY();
 * behavior.setTransformGroup(objTrans);
 * objTrans.addChild(behavior);
 * behavior.setSchedulingBounds(bounds);
 * 
 * 
 * 

*

*
The above code will add the rotate behavior to the transform
* group. The user can rotate any object attached to the objTrans.
*/

class MouseRotateY extends MouseBehavior {

 double y_angle;
 double y_factor;
 /**
  * Creates a rotate behavior given the transform group.
  * 
  * @param transformGroup
  *            The transformGroup to operate on.
  */
 public MouseRotateY(TransformGroup transformGroup) {
   super(transformGroup);
 }
 /**
  * Creates a default mouse rotate behavior.
  */
 public MouseRotateY() {
   super(0);
 }
 /**
  * Creates a rotate behavior. Note that this behavior still needs a
  * transform group to work on (use setTransformGroup(tg)) and the transform
  * group must add this behavior.
  * 
  * @param flags
  *            interesting flags (wakeup conditions).
  */
 public MouseRotateY(int flags) {
   super(flags);
 }
 public void initialize() {
   super.initialize();
   y_angle = 0;
   y_factor = .03;
   if ((flags & INVERT_INPUT) == INVERT_INPUT) {
     invert = true;
     y_factor *= -1;
   }
 }
 public double getYFactor() {
   return y_factor;
 }
 public void setFactor(double factor) {
   y_factor = factor;
 }
 public void processStimulus(Enumeration criteria) {
   WakeupCriterion wakeup;
   AWTEvent[] event;
   int id;
   int dx;
   while (criteria.hasMoreElements()) {
     wakeup = (WakeupCriterion) criteria.nextElement();
     if (wakeup instanceof WakeupOnAWTEvent) {
       event = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
       for (int i = 0; i < event.length; i++) {
         processMouseEvent((MouseEvent) event[i]);
         if (((buttonPress) && ((flags & MANUAL_WAKEUP) == 0))
             || ((wakeUp) && ((flags & MANUAL_WAKEUP) != 0))) {
           id = event[i].getID();
           if ((id == MouseEvent.MOUSE_DRAGGED)
               && !((MouseEvent) event[i]).isMetaDown()
               && !((MouseEvent) event[i]).isAltDown()) {
             x = ((MouseEvent) event[i]).getX();
             dx = x - x_last;
             if (!reset) {
               y_angle = dx * y_factor;
               transformY.rotY(y_angle);
               transformGroup.getTransform(currXform);
               //Vector3d translation = new Vector3d();
               //Matrix3f rotation = new Matrix3f();
               Matrix4d mat = new Matrix4d();
               // Remember old matrix
               currXform.get(mat);
               // Translate to origin
               currXform.setTranslation(new Vector3d(0.0, 0.0,
                   0.0));
               if (invert) {
                 currXform.mul(currXform, transformX);
                 currXform.mul(currXform, transformY);
               } else {
                 currXform.mul(transformX, currXform);
                 currXform.mul(transformY, currXform);
               }
               // Set old translation back
               Vector3d translation = new Vector3d(mat.m03,
                   mat.m13, mat.m23);
               currXform.setTranslation(translation);
               // Update xform
               transformGroup.setTransform(currXform);
             } else {
               reset = false;
             }
             x_last = x;
           } else if (id == MouseEvent.MOUSE_PRESSED) {
             x_last = ((MouseEvent) event[i]).getX();
           }
         }
       }
     }
   }
   wakeupOn(mouseCriterion);
 }

}


      </source>
   
  
 
  



PickCallbackApp renders two interactively rotatable cubes

   <source lang="java">

/*

*      @(#)PickCallbackApp.java 1.0 99/03/25 11:42:40
*
* Copyright (c) 1996-1999 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.picking.PickRotateBehavior; import com.sun.j3d.utils.behaviors.picking.PickingCallback; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.SimpleUniverse; // PickCallbackApp renders two interactively rotatable cubes. public class PickCallbackApp extends Applet {

   public class MyCallbackClass extends Object implements PickingCallback{
       public void transformChanged(int type, TransformGroup tg) {
               System.out.println("picking");
       }
   }
   public BranchGroup createSceneGraph(Canvas3D canvas) {
 // Create the root of the branch graph
 BranchGroup objRoot = new BranchGroup();
       TransformGroup objRotate = null;
       PickRotateBehavior pickRotate = null;
       Transform3D transform = new Transform3D();
       BoundingSphere behaveBounds = new BoundingSphere();
       // create ColorCube and PickRotateBehavior objects
       transform.setTranslation(new Vector3f(-0.6f, 0.0f, -0.6f));
       objRotate = new TransformGroup(transform);
       objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
       objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
       objRotate.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
       objRoot.addChild(objRotate);
       objRotate.addChild(new ColorCube(0.4));
       pickRotate = new PickRotateBehavior(objRoot, canvas, behaveBounds);
       objRoot.addChild(pickRotate);
       PickingCallback myCallback = new MyCallbackClass();
       // Register the class callback to be called 
       pickRotate.setupCallback(myCallback);
       // add a second ColorCube object to the scene graph
       transform.setTranslation(new Vector3f( 0.6f, 0.0f, -0.6f));
       objRotate = new TransformGroup(transform);
       objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
       objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
       objRotate.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
       objRoot.addChild(objRotate);
       objRotate.addChild(new ColorCube(0.4));
 // Let Java 3D perform optimizations on this scene graph.
       objRoot.rupile();
 return objRoot;
   } // end of CreateSceneGraph method of PickCallbackApp
   // Create a simple scene and attach it to the virtual universe
   public PickCallbackApp() {
       setLayout(new BorderLayout());
       Canvas3D canvas3D = new Canvas3D(null);
       add("Center", canvas3D);
       // SimpleUniverse is a Convenience Utility class
       SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
       BranchGroup scene = createSceneGraph(canvas3D);
       // This will move the ViewPlatform back a bit
       simpleU.getViewingPlatform().setNominalViewingTransform();
       simpleU.addBranchGraph(scene);
   } // end of PickCallbackApp (constructor)
   //  The following allows this to be run as an application or as an applet
   public static void main(String[] args) {
       System.out.print("PickCallbackApp.java \n- a demonstration of using the PickRotateBehavior ");
       System.out.println("utility class to provide interaction in a Java 3D scene.");
       System.out.println("Hold the mouse button over a cube then move the mouse to make that cube rotate.");
       System.out.println("This is a simple example progam from The Java 3D API Tutorial.");
       System.out.println("The Java 3D Tutorial is available on the web at:");
       System.out.println("http://www.sun.ru/desktop/java3d/collateral");
       Frame frame = new MainFrame(new PickCallbackApp(), 256, 256);
   } // end of main (method of PickCallbackApp)

} // end of class PickCallbackApp


      </source>
   
  
 
  



Picking utilities on various GeometryArray subclasses and Morph object

   <source lang="java">

/*

*  @(#)PickTest.java 1.9 02/10/21 13:48:53
*
* Copyright (c) 1996-2002 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
*   notice, this list of conditions and the following disclaimer.
*
* - Redistribution in binary form must reproduce the above copyright
*   notice, this list of conditions and the following disclaimer in
*   the documentation and/or other materials provided with the
*   distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any
* kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
* EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that Software is not designed,licensed or intended
* for use in the design, construction, operation or maintenance of
* any nuclear facility.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.ruponent; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Enumeration; import javax.media.j3d.Alpha; import javax.media.j3d.Appearance; import javax.media.j3d.Behavior; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.rupressedGeometry; import javax.media.j3d.rupressedGeometryHeader; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Geometry; import javax.media.j3d.GeometryArray; import javax.media.j3d.Group; import javax.media.j3d.IndexedLineArray; import javax.media.j3d.IndexedLineStripArray; import javax.media.j3d.IndexedPointArray; import javax.media.j3d.IndexedQuadArray; import javax.media.j3d.IndexedTriangleArray; import javax.media.j3d.IndexedTriangleFanArray; import javax.media.j3d.IndexedTriangleStripArray; import javax.media.j3d.LineArray; import javax.media.j3d.LineStripArray; import javax.media.j3d.Material; import javax.media.j3d.Morph; import javax.media.j3d.PointArray; import javax.media.j3d.PointAttributes; import javax.media.j3d.QuadArray; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TriangleArray; import javax.media.j3d.TriangleFanArray; import javax.media.j3d.TriangleStripArray; import javax.media.j3d.View; import javax.media.j3d.WakeupOnElapsedFrames; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.border.BevelBorder; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.picking.PickCanvas; import com.sun.j3d.utils.picking.PickTool; import com.sun.j3d.utils.picking.behaviors.PickRotateBehavior; import com.sun.j3d.utils.picking.behaviors.PickTranslateBehavior; import com.sun.j3d.utils.picking.behaviors.PickZoomBehavior; import com.sun.j3d.utils.universe.SimpleUniverse; /**

* PickTest shows how to use the Picking utilities on various GeometryArray
* subclasses and Morph object. Type of Geometry : CompressedGeometry (
* GullCG.java ) IndexedQuadArray ( CubeIQA.java ) TriangleArray (
* TetrahedronTA.java ) IndexedTriangleArray ( TetrahedronITA.java )
* TriangleFanArray ( OctahedronTFA.java ) IndexedTriangleFanArray (
* OctahedronITA.java ) TriangleStripArray ( IcosahedronTFA.java )
* IndexedTriangleStripArray ( IcosahedronITA.java ) PointArray(
* TetrahedronPA.java ) LineArray( TetrahedronLA.java ) IndexLineArray(
* TetrahedronILA.java ) LineStripArray( TetrahedronLSA.java )
* IndexLineStripArray( TetrahedronILSA.java )
* 
* Morph Object uses : QuadArray ( ColorCube.java, ColorPyramidDown.java, and
* ColorPyramidUp.java ).
*/

public class PickTest extends Applet implements ActionListener {

 private View view = null;
 private QuadArray geomMorph[] = new QuadArray[3];
 private Morph morph;
 private PickRotateBehavior behavior1;
 private PickZoomBehavior behavior2;
 private PickTranslateBehavior behavior3;
 private SimpleUniverse u = null;
 public BranchGroup createSceneGraph(Canvas3D canvas) {
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   // Create a Transformgroup to scale all objects so they
   // appear in the scene.
   TransformGroup objScale = new TransformGroup();
   Transform3D t3d = new Transform3D();
   t3d.setScale(1.0);
   objScale.setTransform(t3d);
   objRoot.addChild(objScale);
   // Create a bunch of objects with a behavior and add them
   // into the scene graph.
   int row, col;
   int numRows = 4, numCols = 4;
   for (int i = 0; i < numRows; i++) {
     double ypos = (double) (i - numRows / 2) * 0.45 + 0.25;
     for (int j = 0; j < numCols; j++) {
       double xpos = (double) (j - numCols / 2) * 0.45 + 0.25;
       objScale
           .addChild(createObject(i * numCols + j, 0.1, xpos, ypos));
     }
   }
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   // Add a light.
   Color3f lColor = new Color3f(1.0f, 1.0f, 1.0f);
   Vector3f lDir = new Vector3f(0.0f, 0.0f, -1.0f);
   DirectionalLight lgt = new DirectionalLight(lColor, lDir);
   lgt.setInfluencingBounds(bounds);
   objRoot.addChild(lgt);
   // Now create the Alpha object that controls the speed of the
   // morphing operation.
   Alpha morphAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE
       | Alpha.DECREASING_ENABLE, 0, 0, 4000, 1000, 500, 4000, 1000,
       500);
   // Finally, create the morphing behavior
   MorphingBehavior mBeh = new MorphingBehavior(morphAlpha, morph);
   mBeh.setSchedulingBounds(bounds);
   objRoot.addChild(mBeh);
   behavior1 = new PickRotateBehavior(objRoot, canvas, bounds);
   objRoot.addChild(behavior1);
   behavior2 = new PickZoomBehavior(objRoot, canvas, bounds);
   objRoot.addChild(behavior2);
   behavior3 = new PickTranslateBehavior(objRoot, canvas, bounds);
   objRoot.addChild(behavior3);
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 }
 private Group createObject(int index, double scale, double xpos, double ypos) {
   Shape3D shape = null;
   Geometry geom = null;
   // Create a transform group node to scale and position the object.
   Transform3D t = new Transform3D();
   t.set(scale, new Vector3d(xpos, ypos, 0.0));
   TransformGroup objTrans = new TransformGroup(t);
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   objTrans.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
   // Create a second transform group node and initialize it to the
   // identity. Enable the TRANSFORM_WRITE capability so that
   // our behavior code can modify it at runtime.
   TransformGroup spinTg = new TransformGroup();
   spinTg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   spinTg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   spinTg.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
   Appearance appearance = new Appearance();
   switch (index) {
   case 0:
     geom = new GullCG();
     break;
   case 1:
     geom = new TetrahedronTA();
     break;
   case 2:
     geom = new OctahedronTFA();
     break;
   case 3:
     geom = new IcosahedronTSA();
     break;
   case 4:
     geom = new CubeIQA();
     break;
   case 5:
     geom = new TetrahedronITA();
     break;
   case 6:
     geom = new OctahedronITFA();
     break;
   case 7:
     geom = new IcosahedronITSA();
     break;
   case 8:
     geomMorph[0] = new ColorPyramidUp();
     geomMorph[1] = new ColorCube();
     geomMorph[2] = new ColorPyramidDown();
     break;
   case 9:
     geom = new TetrahedronLA();
     break;
   case 10:
     geom = new TetrahedronILA();
     break;
   case 11:
     geom = new TetrahedronLSA();
     break;
   case 12:
     geom = new TetrahedronILSA();
     break;
   case 13:
     geom = new TetrahedronPA();
     break;
   case 14:
     geom = new TetrahedronIPA();
     break;
   // TODO: other geo types, Text3D?
   case 15:
     geom = new TetrahedronTA();
     break;
   }
   Material m = new Material();
   if (index == 8) {
     m.setLightingEnable(false);
     appearance.setMaterial(m);
     morph = new Morph((GeometryArray[]) geomMorph, appearance);
     morph.setCapability(Morph.ALLOW_WEIGHTS_READ);
     morph.setCapability(Morph.ALLOW_WEIGHTS_WRITE);
     PickTool.setCapabilities(morph, PickTool.INTERSECT_FULL);
     spinTg.addChild(morph);
   } else {
     // Geometry picking require this to be set.
     if (index == 0)
       m.setLightingEnable(true);
     else
       m.setLightingEnable(false);
     appearance.setMaterial(m);
     if ((index == 13) || (index == 14)) {
       PointAttributes pa = new PointAttributes();
       pa.setPointSize(4.0f);
       appearance.setPointAttributes(pa);
     }
     shape = new Shape3D(geom, appearance);
     shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
     shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
     shape.setCapability(Shape3D.ENABLE_PICK_REPORTING);
     PickTool.setCapabilities(shape, PickTool.INTERSECT_FULL);
     spinTg.addChild(shape);
   }
   // add it to the scene graph.
   objTrans.addChild(spinTg);
   return objTrans;
 }
 private void setPickMode(int mode) {
   behavior1.setMode(mode);
   behavior2.setMode(mode);
   behavior3.setMode(mode);
 }
 private void setPickTolerance(float tolerance) {
   behavior1.setTolerance(tolerance);
   behavior2.setTolerance(tolerance);
   behavior3.setTolerance(tolerance);
 }
 private void setViewMode(int mode) {
   view.setProjectionPolicy(mode);
 }
 // GUI stuff
 String pickModeString = new String("Pick Mode");
 String boundsString = new String("BOUNDS");
 String geometryString = new String("GEOMETRY");
 String geometryIntersectString = new String("GEOMETRY_INTERSECT_INFO");
 String toleranceString = new String("Pick Tolerance");
 String tolerance0String = new String("0");
 String tolerance2String = new String("2");
 String tolerance4String = new String("4");
 String tolerance8String = new String("8");
 String viewModeString = new String("View Mode");
 String perspectiveString = new String("Perspective");
 String parallelString = new String("Parallel");
 private void addRadioButton(JPanel panel, ButtonGroup bg, String ownerName,
     String buttonName, boolean selected) {
   JRadioButton item;
   item = new JRadioButton(buttonName);
   item.setName(ownerName);
   item.addActionListener(this);
   if (selected) {
     item.setSelected(true);
   }
   panel.add(item);
   bg.add(item);
 }
 private void setupGUI(JPanel panel) {
   ButtonGroup bg;
   panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
   panel.setBorder(new BevelBorder(BevelBorder.RAISED));
   panel.add(new JLabel(pickModeString));
   bg = new ButtonGroup();
   addRadioButton(panel, bg, pickModeString, boundsString, true);
   addRadioButton(panel, bg, pickModeString, geometryString, false);
   addRadioButton(panel, bg, pickModeString, geometryIntersectString,
       false);
   panel.add(new JLabel(toleranceString));
   bg = new ButtonGroup();
   addRadioButton(panel, bg, toleranceString, tolerance0String, false);
   addRadioButton(panel, bg, toleranceString, tolerance2String, true);
   addRadioButton(panel, bg, toleranceString, tolerance4String, false);
   addRadioButton(panel, bg, toleranceString, tolerance8String, false);
   panel.add(new JLabel(viewModeString));
   bg = new ButtonGroup();
   addRadioButton(panel, bg, viewModeString, perspectiveString, true);
   addRadioButton(panel, bg, viewModeString, parallelString, false);
 }
 public void actionPerformed(ActionEvent e) {
   String name = ((Component) e.getSource()).getName();
   String value = e.getActionCommand();
   //System.out.println("action: name = " + name + " value = " + value);
   if (name == pickModeString) {
     if (value == boundsString) {
       setPickMode(PickCanvas.BOUNDS);
     } else if (value == geometryString) {
       setPickMode(PickCanvas.GEOMETRY);
     } else if (value == geometryIntersectString) {
       setPickMode(PickCanvas.GEOMETRY_INTERSECT_INFO);
     } else {
       System.out.println("Unknown pick mode: " + value);
     }
   } else if (name == toleranceString) {
     if (value == tolerance0String) {
       setPickTolerance(0.0f);
     } else if (value == tolerance2String) {
       setPickTolerance(2.0f);
     } else if (value == tolerance4String) {
       setPickTolerance(4.0f);
     } else if (value == tolerance8String) {
       setPickTolerance(8.0f);
     } else {
       System.out.println("Unknown tolerance: " + value);
     }
   } else if (name == viewModeString) {
     if (value == perspectiveString) {
       setViewMode(View.PERSPECTIVE_PROJECTION);
     } else if (value == parallelString) {
       setViewMode(View.PARALLEL_PROJECTION);
     }
   } else {
     System.out.println("Unknown action name: " + name);
   }
 }
 public PickTest() {
 }
 public void init() {
   setLayout(new BorderLayout());
   Canvas3D c = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
   add("Center", c);
   JPanel guiPanel = new JPanel();
   setupGUI(guiPanel);
   add(guiPanel, BorderLayout.EAST);
   // Create a scene and attach it to the virtual universe
   BranchGroup scene = createSceneGraph(c);
   u = new SimpleUniverse(c);
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   u.getViewingPlatform().setNominalViewingTransform();
   view = u.getViewer().getView();
   u.addBranchGraph(scene);
 }
 public void destroy() {
   u.cleanup();
 }
 public static void main(String argv[]) {
   BranchGroup group;
   new MainFrame(new PickTest(), 750, 550);
 }

} class TetrahedronILSA extends IndexedLineStripArray {

 private static final int[] lineLengths = { 4, 4 };
 TetrahedronILSA() {
   super(4, GeometryArray.COORDINATES | GeometryArray.COLOR_3, 8,
       lineLengths);
   Point3f verts[] = new Point3f[4];
   Color3f colors[] = new Color3f[4];
   verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
   verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
   verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
   verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   int pntsIndex[] = new int[8];
   int clrsIndex[] = new int[8];
   pntsIndex[0] = 0;
   clrsIndex[0] = 0;
   pntsIndex[1] = 1;
   clrsIndex[1] = 1;
   pntsIndex[2] = 3;
   clrsIndex[2] = 3;
   pntsIndex[3] = 2;
   clrsIndex[3] = 2;
   pntsIndex[4] = 1;
   clrsIndex[4] = 1;
   pntsIndex[5] = 2;
   clrsIndex[5] = 2;
   pntsIndex[6] = 0;
   clrsIndex[6] = 0;
   pntsIndex[7] = 3;
   clrsIndex[7] = 3;
   setCoordinates(0, verts);
   setCoordinateIndices(0, pntsIndex);
   setColors(0, colors);
   setColorIndices(0, clrsIndex);
 }

} class TetrahedronILA extends IndexedLineArray {

 TetrahedronILA() {
   super(4, GeometryArray.COORDINATES | GeometryArray.COLOR_3, 12);
   Point3f verts[] = new Point3f[4];
   Color3f colors[] = new Color3f[4];
   verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
   verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
   verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
   verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   int[] pntsIndex = new int[12];
   int[] clrsIndex = new int[12];
   pntsIndex[0] = 0;
   clrsIndex[0] = 0;
   pntsIndex[1] = 1;
   clrsIndex[1] = 1;
   pntsIndex[2] = 1;
   clrsIndex[2] = 1;
   pntsIndex[3] = 2;
   clrsIndex[3] = 2;
   pntsIndex[4] = 2;
   clrsIndex[4] = 2;
   pntsIndex[5] = 0;
   clrsIndex[5] = 0;
   pntsIndex[6] = 1;
   clrsIndex[6] = 1;
   pntsIndex[7] = 3;
   clrsIndex[7] = 3;
   pntsIndex[8] = 2;
   clrsIndex[8] = 2;
   pntsIndex[9] = 3;
   clrsIndex[9] = 3;
   pntsIndex[10] = 0;
   clrsIndex[10] = 0;
   pntsIndex[11] = 3;
   clrsIndex[11] = 3;
   setCoordinates(0, verts);
   setCoordinateIndices(0, pntsIndex);
   setColors(0, colors);
   setColorIndices(0, clrsIndex);
 }

} class TetrahedronTA extends TriangleArray {

 TetrahedronTA() {
   super(12, GeometryArray.COORDINATES | GeometryArray.COLOR_3);
   Point3f verts[] = new Point3f[4];
   Color3f colors[] = new Color3f[4];
   verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
   verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
   verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
   verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   Point3f pnts[] = new Point3f[12];
   Color3f clrs[] = new Color3f[12];
   pnts[0] = verts[2];
   clrs[0] = colors[0];
   pnts[1] = verts[1];
   clrs[1] = colors[0];
   pnts[2] = verts[0];
   clrs[2] = colors[0];
   pnts[3] = verts[3];
   clrs[3] = colors[1];
   pnts[4] = verts[2];
   clrs[4] = colors[1];
   pnts[5] = verts[0];
   clrs[5] = colors[1];
   pnts[6] = verts[1];
   clrs[6] = colors[2];
   pnts[7] = verts[2];
   clrs[7] = colors[2];
   pnts[8] = verts[3];
   clrs[8] = colors[2];
   pnts[9] = verts[1];
   clrs[9] = colors[3];
   pnts[10] = verts[3];
   clrs[10] = colors[3];
   pnts[11] = verts[0];
   clrs[11] = colors[3];
   setCoordinates(0, pnts);
   setColors(0, clrs);
 }

} class TetrahedronPA extends PointArray {

 TetrahedronPA() {
   super(4, GeometryArray.COORDINATES | GeometryArray.COLOR_3);
   Point3f verts[] = new Point3f[4];
   Color3f colors[] = new Color3f[4];
   verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
   verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
   verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
   verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   setCoordinates(0, verts);
   setColors(0, colors);
 }

} class TetrahedronLSA extends LineStripArray {

 private static final int[] lineLengths = { 4, 4 };
 TetrahedronLSA() {
   super(8, GeometryArray.COORDINATES | GeometryArray.COLOR_3, lineLengths);
   Point3f verts[] = new Point3f[4];
   Color3f colors[] = new Color3f[4];
   verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
   verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
   verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
   verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   Point3f pnts[] = new Point3f[8];
   Color3f clrs[] = new Color3f[8];
   pnts[0] = verts[0];
   clrs[0] = colors[0];
   pnts[1] = verts[1];
   clrs[1] = colors[1];
   pnts[2] = verts[3];
   clrs[2] = colors[3];
   pnts[3] = verts[2];
   clrs[3] = colors[2];
   pnts[4] = verts[1];
   clrs[4] = colors[1];
   pnts[5] = verts[2];
   clrs[5] = colors[2];
   pnts[6] = verts[0];
   clrs[6] = colors[0];
   pnts[7] = verts[3];
   clrs[7] = colors[3];
   setCoordinates(0, pnts);
   setColors(0, clrs);
 }

} class TetrahedronLA extends LineArray {

 TetrahedronLA() {
   super(12, GeometryArray.COORDINATES | GeometryArray.COLOR_3);
   Point3f verts[] = new Point3f[4];
   Color3f colors[] = new Color3f[4];
   verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
   verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
   verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
   verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   Point3f pnts[] = new Point3f[12];
   Color3f clrs[] = new Color3f[12];
   pnts[0] = verts[0];
   clrs[0] = colors[0];
   pnts[1] = verts[1];
   clrs[1] = colors[1];
   pnts[2] = verts[1];
   clrs[2] = colors[1];
   pnts[3] = verts[2];
   clrs[3] = colors[2];
   pnts[4] = verts[2];
   clrs[4] = colors[2];
   pnts[5] = verts[0];
   clrs[5] = colors[0];
   pnts[6] = verts[1];
   clrs[6] = colors[1];
   pnts[7] = verts[3];
   clrs[7] = colors[3];
   pnts[8] = verts[2];
   clrs[8] = colors[2];
   pnts[9] = verts[3];
   clrs[9] = colors[3];
   pnts[10] = verts[0];
   clrs[10] = colors[0];
   pnts[11] = verts[3];
   clrs[11] = colors[3];
   setCoordinates(0, pnts);
   setColors(0, clrs);
 }

} class TetrahedronITA extends IndexedTriangleArray {

 TetrahedronITA() {
   super(4, GeometryArray.COORDINATES | GeometryArray.COLOR_3, 12);
   Point3f verts[] = new Point3f[4];
   Color3f colors[] = new Color3f[4];
   verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
   verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
   verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
   verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   int pntsIndex[] = new int[12];
   int clrsIndex[] = new int[12];
   pntsIndex[0] = 2;
   clrsIndex[0] = 0;
   pntsIndex[1] = 1;
   clrsIndex[1] = 0;
   pntsIndex[2] = 0;
   clrsIndex[2] = 0;
   pntsIndex[3] = 3;
   clrsIndex[3] = 1;
   pntsIndex[4] = 2;
   clrsIndex[4] = 1;
   pntsIndex[5] = 0;
   clrsIndex[5] = 1;
   pntsIndex[6] = 1;
   clrsIndex[6] = 2;
   pntsIndex[7] = 2;
   clrsIndex[7] = 2;
   pntsIndex[8] = 3;
   clrsIndex[8] = 2;
   pntsIndex[9] = 1;
   clrsIndex[9] = 3;
   pntsIndex[10] = 3;
   clrsIndex[10] = 3;
   pntsIndex[11] = 0;
   clrsIndex[11] = 3;
   setCoordinates(0, verts);
   setCoordinateIndices(0, pntsIndex);
   setColors(0, colors);
   setColorIndices(0, clrsIndex);
 }

} class TetrahedronIPA extends IndexedPointArray {

 TetrahedronIPA() {
   super(4, GeometryArray.COORDINATES | GeometryArray.COLOR_3, 4);
   Point3f verts[] = new Point3f[4];
   Color3f colors[] = new Color3f[4];
   verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
   verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
   verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
   verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   int pntsIndex[] = new int[4];
   int clrsIndex[] = new int[4];
   pntsIndex[0] = clrsIndex[0] = 0;
   pntsIndex[1] = clrsIndex[1] = 1;
   pntsIndex[2] = clrsIndex[2] = 2;
   pntsIndex[3] = clrsIndex[3] = 3;
   setCoordinates(0, verts);
   setCoordinateIndices(0, pntsIndex);
   setColors(0, colors);
   setColorIndices(0, clrsIndex);
 }

} class IcosahedronTSA extends TriangleStripArray {

 private static final int[] sVertCnt = { 3, 11, 5, 4, 5, 4 };
 IcosahedronTSA() {
   super(32, GeometryArray.COORDINATES | GeometryArray.COLOR_3, sVertCnt);
   Point3f verts[] = new Point3f[12];
   Color3f colors[] = new Color3f[12];
   verts[0] = new Point3f(0.0f, 1.4f, 0.8652f);
   verts[1] = new Point3f(0.0f, 1.4f, -0.8652f);
   verts[2] = new Point3f(1.4f, 0.8652f, 0.0f);
   verts[3] = new Point3f(1.4f, -0.8652f, 0.0f);
   verts[4] = new Point3f(0.0f, -1.4f, -0.8652f);
   verts[5] = new Point3f(0.0f, -1.4f, 0.8652f);
   verts[6] = new Point3f(0.8652f, 0.0f, 1.4f);
   verts[7] = new Point3f(-0.8652f, 0.0f, 1.4f);
   verts[8] = new Point3f(0.8652f, 0.0f, -1.4f);
   verts[9] = new Point3f(-0.8652f, 0.0f, -1.4f);
   verts[10] = new Point3f(-1.4f, 0.8652f, 0.0f);
   verts[11] = new Point3f(-1.4f, -0.8652f, 0.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   colors[4] = new Color3f(0.0f, 1.0f, 1.0f);
   colors[5] = new Color3f(1.0f, 0.0f, 1.0f);
   colors[6] = new Color3f(0.0f, 0.5f, 0.0f);
   colors[7] = new Color3f(0.0f, 0.0f, 0.5f);
   colors[8] = new Color3f(0.5f, 0.5f, 0.0f);
   colors[9] = new Color3f(0.0f, 0.5f, 0.5f);
   colors[10] = new Color3f(0.5f, 0.0f, 0.5f);
   colors[11] = new Color3f(0.5f, 0.5f, 0.5f);
   Point3f pnts[] = new Point3f[32];
   Color3f clrs[] = new Color3f[32];
   pnts[0] = verts[4];
   clrs[0] = colors[4];
   pnts[1] = verts[5];
   clrs[1] = colors[5];
   pnts[2] = verts[11];
   clrs[2] = colors[11];
   pnts[3] = verts[11];
   clrs[3] = colors[11];
   pnts[4] = verts[5];
   clrs[4] = colors[5];
   pnts[5] = verts[7];
   clrs[5] = colors[7];
   pnts[6] = verts[6];
   clrs[6] = colors[6];
   pnts[7] = verts[0];
   clrs[7] = colors[0];
   pnts[8] = verts[2];
   clrs[8] = colors[2];
   pnts[9] = verts[1];
   clrs[9] = colors[1];
   pnts[10] = verts[8];
   clrs[10] = colors[8];
   pnts[11] = verts[9];
   clrs[11] = colors[9];
   pnts[12] = verts[4];
   clrs[12] = colors[4];
   pnts[13] = verts[11];
   clrs[13] = colors[11];
   pnts[14] = verts[2];
   clrs[14] = colors[2];
   pnts[15] = verts[6];
   clrs[15] = colors[6];
   pnts[16] = verts[3];
   clrs[16] = colors[3];
   pnts[17] = verts[5];
   clrs[17] = colors[5];
   pnts[18] = verts[4];
   clrs[18] = colors[4];
   pnts[19] = verts[4];
   clrs[19] = colors[4];
   pnts[20] = verts[8];
   clrs[20] = colors[8];
   pnts[21] = verts[3];
   clrs[21] = colors[3];
   pnts[22] = verts[2];
   clrs[22] = colors[2];
   pnts[23] = verts[0];
   clrs[23] = colors[0];
   pnts[24] = verts[1];
   clrs[24] = colors[1];
   pnts[25] = verts[10];
   clrs[25] = colors[10];
   pnts[26] = verts[9];
   clrs[26] = colors[9];
   pnts[27] = verts[11];
   clrs[27] = colors[11];
   pnts[28] = verts[0];
   clrs[28] = colors[0];
   pnts[29] = verts[10];
   clrs[29] = colors[10];
   pnts[30] = verts[7];
   clrs[30] = colors[7];
   pnts[31] = verts[11];
   clrs[31] = colors[11];
   setCoordinates(0, pnts);
   setColors(0, clrs);
 }

} class IcosahedronITSA extends IndexedTriangleStripArray {

 private static final int[] sVertCnt = { 3, 11, 5, 4, 5, 4 };
 IcosahedronITSA() {
   super(12, GeometryArray.COORDINATES | GeometryArray.COLOR_3, 32,
       sVertCnt);
   Point3f verts[] = new Point3f[12];
   Color3f colors[] = new Color3f[12];
   verts[0] = new Point3f(0.0f, 1.4f, 0.8652f);
   verts[1] = new Point3f(0.0f, 1.4f, -0.8652f);
   verts[2] = new Point3f(1.4f, 0.8652f, 0.0f);
   verts[3] = new Point3f(1.4f, -0.8652f, 0.0f);
   verts[4] = new Point3f(0.0f, -1.4f, -0.8652f);
   verts[5] = new Point3f(0.0f, -1.4f, 0.8652f);
   verts[6] = new Point3f(0.8652f, 0.0f, 1.4f);
   verts[7] = new Point3f(-0.8652f, 0.0f, 1.4f);
   verts[8] = new Point3f(0.8652f, 0.0f, -1.4f);
   verts[9] = new Point3f(-0.8652f, 0.0f, -1.4f);
   verts[10] = new Point3f(-1.4f, 0.8652f, 0.0f);
   verts[11] = new Point3f(-1.4f, -0.8652f, 0.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   colors[4] = new Color3f(0.0f, 1.0f, 1.0f);
   colors[5] = new Color3f(1.0f, 0.0f, 1.0f);
   colors[6] = new Color3f(0.0f, 0.5f, 0.0f);
   colors[7] = new Color3f(0.0f, 0.0f, 0.5f);
   colors[8] = new Color3f(0.5f, 0.5f, 0.0f);
   colors[9] = new Color3f(0.0f, 0.5f, 0.5f);
   colors[10] = new Color3f(0.5f, 0.0f, 0.5f);
   colors[11] = new Color3f(0.5f, 0.5f, 0.5f);
   int pntsIndex[] = new int[32];
   int clrsIndex[] = new int[32];
   pntsIndex[0] = 4;
   clrsIndex[0] = 4;
   pntsIndex[1] = 5;
   clrsIndex[1] = 5;
   pntsIndex[2] = 11;
   clrsIndex[2] = 11;
   pntsIndex[3] = 11;
   clrsIndex[3] = 11;
   pntsIndex[4] = 5;
   clrsIndex[4] = 5;
   pntsIndex[5] = 7;
   clrsIndex[5] = 7;
   pntsIndex[6] = 6;
   clrsIndex[6] = 6;
   pntsIndex[7] = 0;
   clrsIndex[7] = 0;
   pntsIndex[8] = 2;
   clrsIndex[8] = 2;
   pntsIndex[9] = 1;
   clrsIndex[9] = 1;
   pntsIndex[10] = 8;
   clrsIndex[10] = 8;
   pntsIndex[11] = 9;
   clrsIndex[11] = 9;
   pntsIndex[12] = 4;
   clrsIndex[12] = 4;
   pntsIndex[13] = 11;
   clrsIndex[13] = 11;
   pntsIndex[14] = 2;
   clrsIndex[14] = 2;
   pntsIndex[15] = 6;
   clrsIndex[15] = 6;
   pntsIndex[16] = 3;
   clrsIndex[16] = 3;
   pntsIndex[17] = 5;
   clrsIndex[17] = 5;
   pntsIndex[18] = 4;
   clrsIndex[18] = 4;
   pntsIndex[19] = 4;
   clrsIndex[19] = 4;
   pntsIndex[20] = 8;
   clrsIndex[20] = 8;
   pntsIndex[21] = 3;
   clrsIndex[21] = 3;
   pntsIndex[22] = 2;
   clrsIndex[22] = 2;
   pntsIndex[23] = 0;
   clrsIndex[23] = 0;
   pntsIndex[24] = 1;
   clrsIndex[24] = 1;
   pntsIndex[25] = 10;
   clrsIndex[25] = 10;
   pntsIndex[26] = 9;
   clrsIndex[26] = 9;
   pntsIndex[27] = 11;
   clrsIndex[27] = 11;
   pntsIndex[28] = 0;
   clrsIndex[28] = 0;
   pntsIndex[29] = 10;
   clrsIndex[29] = 10;
   pntsIndex[30] = 7;
   clrsIndex[30] = 7;
   pntsIndex[31] = 11;
   clrsIndex[31] = 11;
   setCoordinates(0, verts);
   setCoordinateIndices(0, pntsIndex);
   setColors(0, colors);
   setColorIndices(0, clrsIndex);
 }

} class OctahedronTFA extends TriangleFanArray {

 private static final int[] sVertCnt = { 6, 6 };
 OctahedronTFA() {
   super(12, GeometryArray.COORDINATES | GeometryArray.COLOR_3, sVertCnt);
   Point3f verts[] = new Point3f[6];
   Color3f colors[] = new Color3f[6];
   verts[0] = new Point3f(0.0f, 0.0f, -1.5f);
   verts[1] = new Point3f(0.0f, 0.0f, 1.5f);
   verts[2] = new Point3f(0.0f, -1.5f, 0.0f);
   verts[3] = new Point3f(0.0f, 1.5f, 0.0f);
   verts[4] = new Point3f(1.5f, 0.0f, 0.0f);
   verts[5] = new Point3f(-1.5f, 0.0f, 0.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   colors[4] = new Color3f(1.0f, 0.0f, 1.0f);
   colors[5] = new Color3f(0.0f, 1.0f, 1.0f);
   Point3f pnts[] = new Point3f[12];
   Color3f clrs[] = new Color3f[12];
   pnts[0] = verts[4];
   clrs[0] = colors[4];
   pnts[1] = verts[2];
   clrs[1] = colors[2];
   pnts[2] = verts[0];
   clrs[2] = colors[0];
   pnts[3] = verts[3];
   clrs[3] = colors[3];
   pnts[4] = verts[1];
   clrs[4] = colors[1];
   pnts[5] = verts[2];
   clrs[5] = colors[2];
   pnts[6] = verts[5];
   clrs[6] = colors[5];
   pnts[7] = verts[1];
   clrs[7] = colors[1];
   pnts[8] = verts[3];
   clrs[8] = colors[3];
   pnts[9] = verts[0];
   clrs[9] = colors[0];
   pnts[10] = verts[2];
   clrs[10] = colors[2];
   pnts[11] = verts[1];
   clrs[11] = colors[1];
   setCoordinates(0, pnts);
   setColors(0, clrs);
 }

} class OctahedronITFA extends IndexedTriangleFanArray {

 private static final int[] sVertCnt = { 6, 6 };
 OctahedronITFA() {
   super(6, GeometryArray.COORDINATES | GeometryArray.COLOR_3, 12,
       sVertCnt);
   Point3f verts[] = new Point3f[6];
   Color3f colors[] = new Color3f[6];
   verts[0] = new Point3f(0.0f, 0.0f, -1.5f);
   verts[1] = new Point3f(0.0f, 0.0f, 1.5f);
   verts[2] = new Point3f(0.0f, -1.5f, 0.0f);
   verts[3] = new Point3f(0.0f, 1.5f, 0.0f);
   verts[4] = new Point3f(1.5f, 0.0f, 0.0f);
   verts[5] = new Point3f(-1.5f, 0.0f, 0.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   colors[4] = new Color3f(1.0f, 0.0f, 1.0f);
   colors[5] = new Color3f(0.0f, 1.0f, 1.0f);
   int pntsIndex[] = new int[12];
   int clrsIndex[] = new int[12];
   pntsIndex[0] = 4;
   clrsIndex[0] = 4;
   pntsIndex[1] = 2;
   clrsIndex[1] = 2;
   pntsIndex[2] = 0;
   clrsIndex[2] = 0;
   pntsIndex[3] = 3;
   clrsIndex[3] = 3;
   pntsIndex[4] = 1;
   clrsIndex[4] = 1;
   pntsIndex[5] = 2;
   clrsIndex[5] = 2;
   pntsIndex[6] = 5;
   clrsIndex[6] = 5;
   pntsIndex[7] = 1;
   clrsIndex[7] = 1;
   pntsIndex[8] = 3;
   clrsIndex[8] = 3;
   pntsIndex[9] = 0;
   clrsIndex[9] = 0;
   pntsIndex[10] = 2;
   clrsIndex[10] = 2;
   pntsIndex[11] = 1;
   clrsIndex[11] = 1;
   setCoordinates(0, verts);
   setCoordinateIndices(0, pntsIndex);
   setColors(0, colors);
   setColorIndices(0, clrsIndex);
 }

} class GullCG extends CompressedGeometry {

 GullCG() {
   super(cgHeader, cgData);
 }
 private static final byte cgData[] = { 25, 0, -120, 16, -58, -52, 33, -35,
     -128, 67, -36, 0, -127, -72, 97, 14, 64, 2, 29, 104, 4, 2, -45, 8,
     125, -89, 16, 51, -116, 33, -1, -104, 71, -64, 48, -106, 31, 1, 32,
     -52, 2, -127, 6, 5, 5, 32, 10, -78, -128, 20, 14, 6, 40, 74, -128,
     81, -43, 24, -94, 44, 1, 86, -104, 98, -96, 49, 5, 34, 112, 10,
     -68, -29, 21, -115, -56, 40, 8, -64, 81, -74, -128, -90, 13, 49,
     71, 30, 2, -81, -68, -30, -62, 122, 56, 37, -107, 60, -109, 120, 0,
     0, 26, -32, 18, 85, -128, 14, -16, 71, -13, 66, -33, 103, 127, -81,
     78, -61, -106, -112, 0, 1, -32, 13, -86, -96, 4, -103, -36, 59,
     -23, 25, 39, 18, 11, 122, -80, 1, -34, -22, -112, -109, -80, -71,
     -7, -39, -40, 0, -127, 0, 0, 0, 0, 43, 97, -102, 118, 16, 83, -32,
     -121, -87, -32, -86, -4, 32, 121, 8, 33, -48, -100, -39, 64, 0, 0,
     50, 0, -47, -9, -97, -118, 53, 75, -122, 89, -54, -10, 8, 0, 69,
     -98, 0, 0, 54, 3, -67, 0, 29, -17, 2, 64, 0, 5, 126, -93, -56, -31,
     15, 74, -95, -128, 5, -64, 0, 3, -46, 8, 0, 36, 0, 0, 58, 93, -92,
     0, 0, 30, 0, 87, 4, 0, 23, 4, 68, 36, 64, 30, -17, -25, -121, -40,
     22, 13, 48, 78, -43, 73, -64, -10, 48, 51, -25, -1, -82, -65, 3,
     55, -71, 41, 124, -50, -118, -64, 4, -102, 112, 0, 1, -20, 5, 98,
     59, -58, -95, -87, 42, -9, -112, -99, -107, -91, -11, 127, 5, 36,
     -46, -112, 121, 9, -39, -17, -1, -41, 0, 0, 0, 112, 4, -121, -19,
     -124, -16, -44, 66, -40, 36, 116, -83, -96, -128, 7, -37, 100, -37,
     121, 11, 123, -81, -106, 43, 82, 14, -85, -8, 41, -95, 67, 81, 18,
     125, 15, 39, -114, -88, 63, -10, 0, -11, 5, 4, 73, -38, 13, 80,
     -64, 7, 64, 56, 14, -56, 108, 3, -64, 96, 5, -33, 81, 24, 11, -115,
     26, -95, -104, 95, -69, -95, -112, 15, 0, -128, 40, 30, 67, -27, 1,
     107, -55, 102, -39, 97, 67, 103, 66, 79, 67, 37, -60, 62, -95, -88,
     -32, 105, 72, 106, -113, -59, -108, 54, -64, 43, 50, 9, 86, 30, 45,
     72, 101, 31, -51, -120, 106, -8, 75, -24, 98, 111, -106, -12, 54,
     104, 54, 47, 87, -115, -61, -106, 64, -47, 13, -80, 10, -116, -122,
     39, -3, 118, -7, 0, 0, 0, 0, 42, -13, -118, 27, 96, 9, 27, -20, 71,
     -8, -96, -50, 61, 111, 87, 102, -83, -93, -54, 47, -37, 51, -113,
     27, 122, 98, -52, -91, -75, 1, 53, -96, 8, 97, -120, 54, -44, 55,
     -1, -10, 105, -108, -84, -4, -101, -64, 67, 41, -4, 105, 67, 117,
     -60, 92, 67, 115, -4, -65, 124, -125, 90, 64, 118, -85, 97, 67, 39,
     126, 96, 67, 78, 80, 65, -15, 12, -57, 61, 94, 67, 50, 3, -93, 33,
     -107, -2, -44, 16, 91, -34, -115, -88, 109, 24, 75, -120, 109,
     -113, -108, 20, 49, 52, 59, 122, 25, 51, -29, 23, -85, -39, 33,
     -50, -28, 104, -122, -16, 2, 0, -128, 90, 67, 20, 1, -93, 124,
     -122, 31, 91, 113, -59, 13, -55, -7, 121, 12, -57, 10, -10, -122,
     120, 0, 1, -8, 8, -56, 33, -49, -59, 94, -78, -45, -85, 6, -33,
     105, -55, -121, -77, 99, -113, 91, 105, -2, 77, -37, 70, -118, -2,
     52, 102, -122, -45, -120, -66, -122, 25, -7, 65, 65, 19, 67, -69,
     33, -92, 1, 0, 0, 23, 16, -37, 31, 40, 113, -90, 120, 118, -84,
     -48, -55, -17, -37, 16, -59, 62, -88, 28, -126, 21, 70, 1, -108, 3,
     80, 1, -96, 45, 107, -115, 124, 58, -60, 102, -128, 0, 7, 64, 27,
     -60, 125, -107, 127, 42, -40, -83, 57, -15, -71, 1, -32, -50, -60,
     42, 123, 106, 60, -16, -32, -66, 85, 26, -14, -31, 82, -20, -49,
     -128, -120, 94, -64, 0, -25, 50, 85, 26, -52, -80, 23, -21, 7,
     -120, 1, 118, 53, -55, 75, -83, -96, 2, 24, -16, 0, 0, 0, 4, 18,
     -77, 92, -101, -64, 8, 84, 72, -22, -33, 85, -126, -42, -69, -41,
     -79, -49, -69, 126, -128, 5, 0, -1, -128, 125, 54, 0, -53, 47, 110,
     91, -59, 64, 13, 119, 115, -59, 63, 93, -28, -6, -23, -61, -128, 1,
     40, 0, 0, 80, 75, 64, -18, -33, -123, -2, -117, -74, -116, 26,
     -106, -80, 6, 91, -70, 21, -23, -44, 0, -121, 12, 7, 64, 0, 5, 38,
     -73, 118, -79, -114, 104, 118, 0, -5, 87, 2, 85, -46, 94, 115,
     -112, -117, 72, 124, 100, -32, 106, 106, 81, -98, -121, -100, 116,
     76, -121, -23, -112, 40, 43, 40, -92, 57, -96, 4, 121, 47, -29,
     -65, 81, -26, 2, -128, 16, 6, 62, -85, 86, -67, -8, 74, -35, -77,
     -62, -5, -81, -106, 56, 0, 0, 31, 1, -91, -48, 0, 67, 27, -62, 100,
     43, 80, 68, 61, -48, 1, 24, 0, 45, 1, -16, 7, 18, 1, -23, -88, -84,
     127, -6, 11, 37, -98, 14, 57, 107, -61, -52, -114, -128, 1, 91,
     -92, -95, -82, -128, 16, -64, 1, 108, 0, -128, 55, 111, -101, 96,
     -80, 61, -90, -94, 122, 49, -21, 14, -2, -73, 99, 115, 81, 11, 90,
     -118, 74, -99, 30, -9, -9, 67, -57, 80, 42, 79, -14, 3, -86, -91,
     -94, 51, -1, 83, 64, -118, 50, 53, -59, 74, -89, 126, -23, 32, 13,
     57, 40, -123, 76, 97, -41, 91, -115, -23, 107, -83, -37, 81, 67,
     27, -73, -113, 58, 22, -80, 4, 88, 64, 109, -10, -64, 14, -80, -19,
     -43, 15, 62, -80, -116, -14, -121, -11, 110, -25, 38, -109, 3, 55,
     -103, 85, -65, -79, -117, -37, 66, -102, 97, -70, -123, 43, 104,
     -128, 21, 100, 40, 71, -55, -125, 104, 33, -43, 82, 84, -102, 7,
     -3, -32, -114, 20, -37, -27, -4, -107, 116, 67, 3, -7, -91, -9,
     -99, -25, -44, -71, -57, 4, 5, -75, 74, 0, 1, 107, -120, -19, -92,
     21, -66, 100, 8, -124, -6, -79, 18, -44, -27, 12, 12, -112, -32,
     -108, -68, 99, 123, -89, -39, 98, -53, 51, -10, -128, 10, 42, -48,
     -9, -108, -34, -100, -7, -52, -123, -39, 100, -46, 85, 45, 16, 0,
     12, 97, -58, -25, 32, 111, -32, 0, -48, 0, -48, 10, -73, 86, -18,
     104, 114, -102, -80, 32, 0, 88, 0, 64, 7, -25, -127, 66, -6, -75,
     74, 73, 78, -51, -125, 4, -103, -88, 1, 78, -62, 54, 84, 90, -14,
     32, 35, -18, -40, -67, -44, 106, -102, -128, 2, 107, -24, -124,
     -64, 66, -51, 15, 100, -87, 44, 0, 70, 125, -120, 95, 33, 50, 123,
     70, 83, 0, -115, 122, 22, -102, 35, 92, -112, 94, -87, -121, -66,
     -64, -105, -65, -15, 17, -22, 122, -80, 33, 94, -5, 5, 75, -35,
     114, 65, 99, 99, 94, 28, -52, -3, -77, 42, -16, -24, -87, 84, 12,
     -76, 76, 90, 110, -120, 0, 86, -36, -95, 85, 0, -122, -62, -125,
     97, 67, 13, 0, -127, -78, -19, 63, -3, -46, 80, 0, -84, 0, 10,
     -128, 46, 3, 40, 4, 55, 114, -8, -38, 16, -59, -12, 84, -90, -35,
     -83, 111, 64, 21, -128, 3, 96, 30, 3, -112, 12, -111, -120, 13,
     -24, 14, -32, 5, 29, 16, 1, 12, 123, -6, -60, 86, 82, 25, 59, -56,
     11, -74, -16, 4, 0, -104, -91, 0, 16, -53, 59, 29, 101, 43, 119,
     -41, -23, -100, 6, 74, 81, 56, 10, -6, 32, 1, 91, -27, -31, -124,
     5, -40, -22, -90, 46, -78, -128, 5, 99, -64, 0, 0, 0, 19, -128, 33,
     -106, 5, -44, -26, -57, -97, -113, -64, 20, -93, 72, 2, 55, 48, 8,
     111, 80, 31, -32, 31, -16, 12, -30, -26, -88, 9, -69, -128, 8, 98,
     3, 64, 120, 5, -67, 118, -12, 59, -118, -122, -115, 122, -6, -122,
     -125, -95, -77, -95, -105, 73, -28, -6, -122, -86, -127, 51, -95,
     -105, 125, -22, -6, -122, -38, -31, -65, 84, -86, -14, 95, 71, -97,
     67, 111, -66, -81, -47, -124, 92, 22, 1, -43, 16, 1, 13, 97, -18,
     -63, -82, -46, -120, 106, -110, -122, -17, 120, 97, -87, 82, 67,
     -99, 75, -48, -33, 95, 79, 2, -32, -32, -104, 13, 41, 0, 8, 103,
     79, -105, -115, 112, 112, 70, 3, 21, 84, 51, -101, -53, 18, 8, 14,
     -62, -83, 72, 100, 72, 72, -24, 102, 71, -73, -117, 17, 30, -65,
     -32, -40, 36, 4, 46, -51, 76, 44, 96, -44, 0, -57, 102, 54, -31,
     -2, 80, 0, -71, 98, -72, 80, 46, 82, -64, 8, 96, -80, 0, 32, 0, 16,
     8, 55, 106, -98, -121, -19, 64, 11, -108, 36, 103, 8, -88, 8, 0,
     46, -116, -101, 104, -128, 50, -54, 112, 93, 73, 64, 0, 115, -128,
     0, 3, -32, 14, -100, 25, 96, 0, -66, 0, 0, 22, 49, -64, 12, -76,
     -124, 35, -95, 56, 1, -10, 0, 11, -32, 122, 1, 98, 20, 114, -38,
     16, -18, -124, -32, 7, -40, 0, 47, -128, 0, 5, 104, 97, -53, 8,
     127, -70, 35, -128, 29, -32, 0, -66, 0, 0, 20, 7, -17, 104, 124,
     -70, 47, -34, 0, 11, -32, 0, 1, 93, 124, -78, -121, -29, -93, 56,
     0, 22, 0, 11, -32, 0, 1, 82, -58, 122, -38, 31, 110, -101, 125,
     -128, 2, -8, 0, 0, 86, -26, 28, -74, -121, -29, -92, 56, 1, -106,
     0, 11, -32, 0, 1, -2, -104, 0, 35, 53, -127, 65, -82, 34, 38, -51,
     -74, -34, 0, -71, 123, 66, 111, -63, -24, 16, 1, 12, 0, 17, 0, 0,
     21, 5, -48, -125, 109, 48, 7, -118, -125, 83, -68, 10, 115, -112,
     1, 0, -128, 18, -47, -89, 61, 121, -86, 77, 58, 16, 109, 92, 65,
     86, 127, -82, -100, 31, 96, 0, 64, 0, 0, 30, -7, 68, -116, 32, 0,
     3, -32, 28, 72, 13, -110, -125, 43, 0, 17, 107, -64, 23, -92, 0,
     46, -64, 1, -96, 13, 1, 91, -112, 1, 12, 5, -2, -66, -122, -110,
     -104, 81, 19, 30, -2, 60, 2, 18, 96, 48, -112, 20, 51, 16, 38, -51,
     126, 67, 56, 33, -82, -78, -87, -117, -10, 10, -52, -86, -18, -97,
     120, 62, -47, 67, -9, -86, 81, -17, 0, 8, 0, 24, 5, -127, -5, -38,
     0, 47, 67, -9, -128, 4, 0, 0, 2, -80, -1, 97, 7, -9, -82, 81, -53,
     0, 8, 0, 0, 5, 4, 112, 3, -19, -96, -14, -11, -56, 57, 96, 1, 0, 0,
     0, -82, -116, 0, 125, -108, 31, 30, -71, 71, -68, 0, 32, 0, 0, 21,
     7, -53, 104, 61, -67, 35, 0, 5, 96, 1, 0, 0, 0, -84, 3, 45, -96,
     -8, -11, 12, 0, 21, -128, 4, 0, 0, 3, -8, 15, -77, -64, -108, 16,
     -30, 14, 61, 105, -40, -81, 27, 124, -75, 64, 40, 6, -11, -54, 32,
     -32, 1, 0, 0, 0, -111, -63, -106, -116, -125, 115, 5, 0, 33, 76, 0,
     1, -64, 61, -96, 25, 26, -116, 24, 37, 66, -113, -55, 42, 77, 19,
     -35, -4, -73, -111, -110, -14, 12, -23, 12, 0, 101, -91, 0, 0, 1,
     0, 104, 70, 0, 43, -39, -99, -46, 78, 45, -5, 58, -30, 2, -127, 27,
     44, -22, 80, -118, 53, -24, 58, -3, -17, -76, -90, 95, 18, 55, -16,
     -39, -4, -121, -55, -25, -11, -38, 85, 68, 60, -76, 15, -5, 124,
     40, 0, 86, -14, 12, -2, 3, 124, -16, 63, 0, -69, -91, 102, 2, -128,
     16, 6, 48, 31, 43, 94, -4, 50, 42, 14, 90, -126, -95, 107, -18,
     -96, 0, -102, 71, -11, -68, 16, -37, 11, -59, 122, -2, 64, 1, -64,
     59, 1, -38, 24, 80, -48, 5, 64, 0, 15, -46, 104, -82, -57, -19, -4,
     -115, 115, 112, 92, 20, -28, -3, -127, 64, 125, -64, 127, -64, 56,
     -125, -113, 74, 118, 43, 78, -35, 107, 47, -18, 91, -121, -111, 0,
     0, 0, 126, -128, 63, -23, 31, 102, -65, 32, 53, -30, -104, 102, 86,
     -16, -16, 8, 86, 2, -20, 31, 24, -11, -56, 1, 78, 0, 16, -127,
     -104, 10, 18, 102, -51, 8, 122, 0, 86, 0, 19, 1, -120, 10, -32, 34,
     -55, 65, 111, 64, 16, 119, -128, 5, -128, 98, 3, -82, -103, 100,
     -64, 0, 7, -80, 31, -111, -128, 11, -108, 89, 16, 106, -107, -56,
     1, 118, -75, -10, 121, -92, 0, -69, 121, 5, 32, -79, 43, -104, 2,
     -20, 123, -2, -51, 72, 1, 118, -6, 40, -5, -105, 48, 2, 24, 56, 0,
     4, 0, 4, 2, -15, 90, 90, 93, -4, 1, -117, 86, -87, -89, 67, 0, 86,
     -98, -94, 121, 1, -66, -34, 0, -64, 18, 10, 86, -40, 21, 115, 0,
     70, -28, 1, -22, 1, -14, 0, -126, 33, 12, -87, 38, -3, -30, -104,
     -28, 124, 89, -63, -58, 77, -76, -79, -89, 98, 8, -64, 7, 0, 56,
     11, -62, 59, -45, 18, 46, -62, -51, -128, 14, 0, 96, 25, -128, -33,
     93, 64, 45, -35, -101, 120, 31, 0, -96, 58, -128, -122, -120, 7, 0,
     0, 1, -39, 12, 0, 124, 2, 0, -80, 70, -36, -127, 119, 16, -122,
     -16, 62, 0, -128, 126, -19, 54, 70, 121, 108, 26, 17, -117, 107,
     -52, -30, 35, -36, 19, 93, -128, 28, 102, -39, -122, -61, 118, 1,
     12, 0, 28, 10, -128, -13, 114, -33, 14, 66, -109, 7, 48, 2, 24,
     -24, 3, -52, -92, 110, 123, 124, -96, 8, 67, 40, 8, -87, -111,
     -117, -71, -98, -124, 73, -128, 3, 96, 30, 2, 105, 8, 32, 64, -74,
     41, 48, -6, -67, -105, -56, 43, 106, -53, -75, 0, 67, 113, 2, 121,
     -89, 114, 4, -128, 57, -60, 80, -50, 56, -107, 16, -46, -64, 45,
     72, 96, 88, 107, 8, 105, -64, 55, -31, -112, 108, -89, -76, -59, 0,
     107, -124, 42, 26, -53, -21, -116, 92, 14, -100, -107, -109, -62,
     94, 64, 33, -75, -128, -121, -12, -102, -122, 17, -119, 101, 67,
     88, 27, -27, 41, 13, -76, 22, -20, -126, 0, 0, 0, 0, 71, 67, 113,
     -66, 51, -95, -92, -122, 12, -94, -126, 33, -13, 103, 35, 46, -1,
     -47, 40, 68, -101, 48, 41, -100, -119, -79, 47, 60, 83, 64, 67,
     101, -122, 51, -103, -119, 107, -62, -102, 1, 12, 8, 22, -2, 42,
     -73, 77, 6, 91, 32, 2, 49, -73, -89, -63, 8, 98, -45, -21, -16, 10,
     50, 41, -87, 74, -76, 53, 91, 75, -43, -40, 0, 42, 1, -96, 36, -46,
     0, 111, -85, 57, 94, 93, 119, -104, 116, 17, -104, -65, 84, 97,
     100, -102, 37, 15, -68, 126, 73, 47, -111, 115, -53, -46, -72, 0,
     102, -60, -123, 119, 1, -54, 64, 4, 2, 0, 118, 71, 92, 0, 12, 12,
     -128, -34, -55, -65, 74, -85, -111, 78, -125, -3, 127, -100, -111,
     -80, -128, 10, -108, -56, 16, 1, -109, -24, 21, -44, -115, -9, -32,
     -16, 35, 37, 14, -22, -69, -106, -15, 64, 3, 45, -22, 33, 86, -64,
     32, -41, 32, 117, 52, 62, -27, -101, -118, -74, -125, -66, 56, -13,
     93, 113, -56, 21, 79, -76, -128, 0, -103, 122, 126, -48, 20, 93,
     -90, 47, 42, -40, 8, 17, -83, -94, -33, 8, 93, -113, 10, 79, 62,
     -128, 23, 109, -25, -8, 1, 33, 90, 0, 33, -118, 5, -44, -54, -64,
     127, -113, 64, 16, -64, 2, 80, 15, 1, -5, -27, -38, -16, -83, 41,
     -118, 15, -37, -57, -79, -94, -51, 50, -59, -47, 20, -59, 64, 15,
     -75, 107, -53, -91, -96, -9, -128, 1, 48, 0, 0, 80, 94, -19, 92,
     -10, -127, -20, 0, 14, 82, 125, 83, -24, -121, 56, -124, 61, -67,
     -88, -73, 64, 120, 0, 0, 84, 0, -61, -19, 99, 32, -33, -26, -76,
     -26, -17, -51, -122, 38, -111, -84, -36, 12, 93, -77, -66, -85,
     -86, 0, 107, -68, 6, -36, 92, -74, 30, 102, 71, 64, 3, 93, 78, -80,
     -75, -7, 5, 93, -6, -57, -74, -79, 79, -109, 78, 22, 117, 108,
     -111, 122, 52, 96, -49, 38, -117, -125, 123, 10, 114, 121, 85, 96,
     -48, 0, -96, 31, 16, 13, 39, -42, 113, 50, -109, -9, 90, 59, 93,
     15, -8, -79, 116, -14, 77, -128, 29, 104, -19, -42, -97, -94, -62,
     6, -33, 44, 0, -5, 108, -3, 91, -19, 7, -83, -27, 81, 49, 24, -12,
     -109, 123, -51, 60, 39, 111, -50, 23, -78, 53, -10, 14, -80, -93,
     122, -87, 33, -78, -30, 59, -95, -96, 10, -128, 0, 30, 61, 92,
     -112, -53, -25, 104, -76, 24, -79, 9, 37, 32, 22, 4, -57, 1, 109,
     65, 7, 26, -98, 59, 106, -101, 103, -64, -116, -52, 11, 29, 23,
     106, 107, 106, -51, -15, 120, -5, -20, 1, 54, -16, -47, -77, 0, 38,
     -81, -54, 18, -8, 32, -122, 69, 70, 117, 23, 44, 0, 0, 30, 0, -68,
     0, 109, -128, -45, -37, 80, 48, 5, 118, -25, -85, 50, 110, 108,
     -111, 51, -47, 23, 16, -96, 45, 99, -51, -110, -12, 96, -63, -42,
     20, 120, 89, 86, 41, 120, 32, 5, 41, -5, 0, 13, -99, 104, -100,
     -128, 10, -80, 16, 0, 104, 15, -104, 5, 106, -85, 125, 9, 57, -1,
     91, -16, 0, 44, 7, -32, 3, -10, 55, 40, -1, 80, 65, -126, -64, 66,
     -20, -37, 66, -59, 95, 64, 4, 55, -20, 26, 13, -37, -126, 125,
     -106, -48, 1, 13, -48, -65, -90, -126, -79, -123, 21, 32, 8, 108,
     95, -91, -111, 115, 44, -101, -112, 1, 82, 16, 0, 103, 1, -51, 0,
     -112, -14, 103, -112, -122, 98, 46, -43, -71, 41, 126, -76, 0, -71,
     79, 2, 127, 108, -2, -128, 23, 109, 93, -111, -74, 90, 0, 33, -96,
     63, -94, -107, -86, 70, 92, -64, 21, -67, 64, 0, -128, 127, -64,
     51, 0, 23, 126, -40, 69, 68, 0, -101, 71, -5, -84, -127, -82, 104,
     -123, 85, 80, -55, -81, 47, -88, 109, -46, 27, -11, 74, -83, 49,
     -35, 116, 113, 112, 0, 86, 0, -72, 15, 32, 4, -37, 124, 11, 126,
     -116, -32, 11, -113, 126, 40, -92, 0, 33, -110, -2, 87, 53, -51,
     64, -81, -51, 74, -36, 121, -4, 102, -15, 117, -19, 4, 93, -32, 4,
     49, 0, 96, 60, 3, -23, 26, 19, -124, -92, 33, 13, -94, -16, -6,
     -122, -83, -127, 54, 33, -118, -99, -79, 32, -107, 112, 30, -8,
     -122, -125, -66, -77, -95, -91, 122, 16, -114, -122, 92, 123, 113,
     65, 69, 125, 125, 67, 66, 48, -43, 80, -53, 78, -49, 29, 37, 10,
     121, -59, 36, -61, -114, -109, -28, 103, -92, 0, 46, -57, -115, 72,
     127, -12, 0, -55, 101, -48, -119, -117, 22, -64, 1, 25, -110, 21,
     -60, 66, 26, 43, -21, -59, -55, -62, -58, -21, 46, -96, -128, 25,
     101, 0, 0, 1, -64, 31, 9, 64, 1, -75, -73, -55, 82, 0, -89, 94, 13,
     -76, -56, 74, -1, 83, 115, 72, -21, -104, 43, 56, -75, -32, -10,
     74, -11, -66, 126, 11, 72, 113, -40, 29, -51, -12, -127, 6, -85,
     -116, -85, 78, 30, -65, -44, -111, -1, -95, -111, 62, -33, 68, -55,
     -29, -91, 112, -93, 37, 1, 72, -111, -114, 0, 125, -96, -32, -38,
     9, 70, 76, -102, 5, -28, -116, -109, -53, -58, -7, -37, -7, 0, 10,
     114, 100, -105, -47, -53, 59, 46, -37, -23, 64, 2, -73, 112, 103,
     -16, 4, 102, -18, 104, 21, -40, 70, -70, 0, 88, 0, 1, -113, -123,
     88, -89, -55, -112, -84, -45, -107, -82, 28, -128, 40, 105, 24, 55,
     61, -73, -40, 15, -72, 0, 8, 4, 47, -27, 88, -18, -3, 74, 50, 104,
     -111, 31, -27, -4, -115, 115, 111, -92, 22, -12, -10, -128, 3,
     -128, 10, 3, 78, -56, 97, 127, 104, 8, 105, 24, 53, -2, -43, 119,
     -21, -12, -13, 104, -95, 71, -19, -4, 13, -13, -57, -20, 16, -16,
     -36, -84, 95, 88, 52, -5, 8, 1, 78, 97, -68, -67, 120, -40, 0, 66,
     1, -96, 40, 64, 2, -20, -2, -57, -88, 2, -84, 0, 38, 0, -16, 21,
     -2, 60, -102, -38, -12, -115, 88, 0, 88, 1, -32, 43, 95, 57, -9,
     -115, 32, -3, 113, -28, -45, 31, -62, 57, 7, -5, -30, -105, 106,
     102, 59, -44, 32, 7, 56, 0, 52, 6, 96, 61, 3, 54, -24, 0, 1, -56,
     11, 0, 92, -70, 40, 85, 113, 0, 16, -42, -79, 73, -73, 106, 66, 21,
     104, 64, 11, -79, -20, 11, 14, 32, 1, 88, 119, -60, 14, 96, 16,
     -34, 64, 0, 32, 63, -32, 23, -48, -35, 82, -20, -92, 110, -102,
     -15, 52, 8, 67, 24, 17, 83, 35, 2, 58, -84, -120, -41, 50, -55,
     -65, 123, 39, -42, 6, -71, 71, 19, 1, 126, 60, 2, 4, 98, 87, 124,
     19, 60, -112, -41, 111, 63, -96, 9, -119, -109, 47, 24, 113, -108,
     -126, 55, 2, -66, 88, -60, 120, -127, -24, 18, -64, 78, 40, 99, 32,
     -21, 56, -5, -66, 100, -80, 19, -116, -37, 77, -75, -18, -64, 33,
     -128, 3, -128, -80, 25, -4, 71, -122, 61, 103, 39, 20, 54, -81,
     -54, -99, -112, -64, 7, 0, -56, 11, -63, 106, -71, -25, 100, -103,
     51, 0, 28, 3, 64, 51, 0, -33, 90, -44, 89, -39, -101, 8, 31, 3, 96,
     44, 0, -122, 101, 9, 114, 67, 0, 0, -1, -64, -1, 0, 88, 35, 82, 67,
     -71, 8, 43, 0, 64, -1, -64, -1, -128, 126, 1, -110, 101, 95, -6,
     -37, 113, 0, 9, -79, 19, -26, 112, 41, -51, -83, 18, 113, -108, 52,
     -113, -25, -44, 54, 33, 13, -59, 13, 5, -11, 97, 12, -58, 8, -50,
     -122, 90, -17, -102, -46, 26, -82, 9, -80, -116, 83, -23, -56, 69,
     73, 84, 0, -28, 7, -12, 3, 47, 17, -68, 43, -26, -62, 32, 92, 25,
     -15, -43, 24, 1, 13, -98, -18, -64, -122, -51, 120, 98, -102, 24,
     71, -35, -127, 5, 90, 48, -42, -92, 49, -36, 36, 116, 52, -29, -21,
     -11, 72, -59, 21, -22, 106, -14, -73, -16, 36, 16, 19, 105, 110,
     -105, -16, 41, 71, 54, 80, -38, 109, 73, -110, -63, 21, 72, 35, 38,
     59, 49, 8, -109, 24, 88, 29, 72, -125, 50, 91, -93, 16, 9, -77,
     -53, 126, 20, -64, 33, 2, 58, -90, 8, -109, 102, 61, 41, -112, 70,
     65, -9, 75, 17, 38, 22, -12, 83, 35, 125, -4, -14, -62, -95, -106,
     -103, -66, -82, 70, -60, -16, 115, 17, 30, -4, 0, 11, 1, -8, 0,
     -126, -120, 75, 65, -47, -42, -58, 126, -55, -128, 0, 15, 96, 52,
     115, 14, -37, 79, -70, 71, 10, 60, -102, 74, 34, 124, -25, 10, 5,
     112, -24, -46, -68, 105, 23, -34, -3, 4, 95, -20, 69, -37, 50, -98,
     8, 17, -113, 97, 20, 72, 33, -107, 88, -45, -56, -49, -80, -85,
     -30, 36, 85, -77, 9, 68, 33, -94, -67, -97, 72, -52, 35, -108, -95,
     23, 96, 40, 22, 40, 64, 12, 87, -122, -9, 27, -23, 2, 8, -73, -6,
     -26, -112, 22, 4, -44, 116, 85, 2, -116, -109, -24, -101, -34, 56,
     1, -74, 16, 0, 1, -16, 14, 61, 89, 56, 51, -21, -107, -101, -72,
     -17, 64, 46, -64, 2, -80, 13, 1, -37, 16, 1, 4, 0, 0, 0, 0, -63,
     118, 101, -103, 91, -60, 32, 4, -40, 52, 58, 119, 64, 32, 0, -52,
     0, 0, 0, -120 };
 private static final CompressedGeometryHeader cgHeader;
 static {
   cgHeader = new CompressedGeometryHeader();
   cgHeader.majorVersionNumber = 1;
   cgHeader.minorVersionNumber = 0;
   cgHeader.minorMinorVersionNumber = 1;
   cgHeader.bufferType = CompressedGeometryHeader.TRIANGLE_BUFFER;
   cgHeader.bufferDataPresent = CompressedGeometryHeader.NORMAL_IN_BUFFER;
   cgHeader.start = 0;
   cgHeader.size = cgData.length;
 }

} class CubeQA extends QuadArray {

 CubeQA() {
   super(24, GeometryArray.COORDINATES | GeometryArray.COLOR_3);
   Point3f verts[] = new Point3f[8];
   Color3f colors[] = new Color3f[6];
   verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
   verts[1] = new Point3f(-1.0f, 1.0f, 1.0f);
   verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
   verts[3] = new Point3f(1.0f, -1.0f, 1.0f);
   verts[4] = new Point3f(1.0f, 1.0f, -1.0f);
   verts[5] = new Point3f(-1.0f, 1.0f, -1.0f);
   verts[6] = new Point3f(-1.0f, -1.0f, -1.0f);
   verts[7] = new Point3f(1.0f, -1.0f, -1.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   colors[4] = new Color3f(1.0f, 0.0f, 1.0f);
   colors[5] = new Color3f(0.0f, 1.0f, 1.0f);
   Point3f pnts[] = new Point3f[24];
   Color3f clrs[] = new Color3f[24];
   pnts[0] = verts[0];
   clrs[0] = colors[0];
   pnts[1] = verts[3];
   clrs[1] = colors[0];
   pnts[2] = verts[7];
   clrs[2] = colors[0];
   pnts[3] = verts[4];
   clrs[3] = colors[0];
   pnts[4] = verts[1];
   clrs[4] = colors[1];
   pnts[5] = verts[5];
   clrs[5] = colors[1];
   pnts[6] = verts[6];
   clrs[6] = colors[1];
   pnts[7] = verts[2];
   clrs[7] = colors[1];
   pnts[8] = verts[0];
   clrs[8] = colors[2];
   pnts[9] = verts[4];
   clrs[9] = colors[2];
   pnts[10] = verts[5];
   clrs[10] = colors[2];
   pnts[11] = verts[1];
   clrs[11] = colors[2];
   pnts[12] = verts[3];
   clrs[12] = colors[3];
   pnts[13] = verts[2];
   clrs[13] = colors[3];
   pnts[14] = verts[6];
   clrs[14] = colors[3];
   pnts[15] = verts[7];
   clrs[15] = colors[3];
   pnts[16] = verts[0];
   clrs[16] = colors[4];
   pnts[17] = verts[1];
   clrs[17] = colors[4];
   pnts[18] = verts[2];
   clrs[18] = colors[4];
   pnts[19] = verts[3];
   clrs[19] = colors[4];
   pnts[20] = verts[7];
   clrs[20] = colors[5];
   pnts[21] = verts[6];
   clrs[21] = colors[5];
   pnts[22] = verts[5];
   clrs[22] = colors[5];
   pnts[23] = verts[4];
   clrs[23] = colors[5];
   setCoordinates(0, pnts);
   setColors(0, clrs);
 }

} class CubeIQA extends IndexedQuadArray {

 CubeIQA() {
   super(8, GeometryArray.COORDINATES | GeometryArray.COLOR_3, 24);
   Point3f verts[] = new Point3f[8];
   Color3f colors[] = new Color3f[8];
   verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
   verts[1] = new Point3f(-1.0f, 1.0f, 1.0f);
   verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
   verts[3] = new Point3f(1.0f, -1.0f, 1.0f);
   verts[4] = new Point3f(1.0f, 1.0f, -1.0f);
   verts[5] = new Point3f(-1.0f, 1.0f, -1.0f);
   verts[6] = new Point3f(-1.0f, -1.0f, -1.0f);
   verts[7] = new Point3f(1.0f, -1.0f, -1.0f);
   colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
   colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
   colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
   colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
   colors[4] = new Color3f(1.0f, 0.0f, 1.0f);
   colors[5] = new Color3f(0.0f, 1.0f, 1.0f);
   colors[6] = new Color3f(0.0f, 1.0f, 1.0f);
   colors[7] = new Color3f(0.0f, 1.0f, 1.0f);
   int pntsIndex[] = new int[24];
   int clrsIndex[] = new int[24];
   pntsIndex[0] = 0;
   clrsIndex[0] = 0;
   pntsIndex[1] = 3;
   clrsIndex[1] = 0;
   pntsIndex[2] = 7;
   clrsIndex[2] = 0;
   pntsIndex[3] = 4;
   clrsIndex[3] = 0;
   pntsIndex[4] = 1;
   clrsIndex[4] = 1;
   pntsIndex[5] = 5;
   clrsIndex[5] = 1;
   pntsIndex[6] = 6;
   clrsIndex[6] = 1;
   pntsIndex[7] = 2;
   clrsIndex[7] = 1;
   pntsIndex[8] = 0;
   clrsIndex[8] = 2;
   pntsIndex[9] = 4;
   clrsIndex[9] = 2;
   pntsIndex[10] = 5;
   clrsIndex[10] = 2;
   pntsIndex[11] = 1;
   clrsIndex[11] = 2;
   pntsIndex[12] = 3;
   clrsIndex[12] = 3;
   pntsIndex[13] = 2;
   clrsIndex[13] = 3;
   pntsIndex[14] = 6;
   clrsIndex[14] = 3;
   pntsIndex[15] = 7;
   clrsIndex[15] = 3;
   pntsIndex[16] = 0;
   clrsIndex[16] = 4;
   pntsIndex[17] = 1;
   clrsIndex[17] = 4;
   pntsIndex[18] = 2;
   clrsIndex[18] = 4;
   pntsIndex[19] = 3;
   clrsIndex[19] = 4;
   pntsIndex[20] = 7;
   clrsIndex[20] = 5;
   pntsIndex[21] = 6;
   clrsIndex[21] = 5;
   pntsIndex[22] = 5;
   clrsIndex[22] = 5;
   pntsIndex[23] = 4;
   clrsIndex[23] = 5;
   setCoordinates(0, verts);
   setCoordinateIndices(0, pntsIndex);
   setColors(0, colors);
   setColorIndices(0, clrsIndex);
 }

} class ColorPyramidUp extends QuadArray {

 private static final float[] verts = {
 // front face
     1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f,
     -1.0f, 1.0f,
     // back face
     -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
     -1.0f, -1.0f,
     // right face
     1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
     -1.0f, 1.0f,
     // left face
     -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f,
     -1.0f, -1.0f,
     // top face
     0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
     0.0f,
     // bottom face
     -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
     -1.0f, 1.0f, };
 private static final float[] colors = {
 // front face (cyan)
     0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
     1.0f,
     // back face (magenta)
     1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
     1.0f,
     // right face (yellow)
     1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
     0.0f,
     // left face (blue)
     0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
     1.0f,
     // top face (green)
     0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
     0.0f,
     // bottom face (red)
     1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
     0.0f,
 };
 ColorPyramidUp() {
   super(24, QuadArray.COORDINATES | QuadArray.COLOR_3);
   setCoordinates(0, verts);
   setColors(0, colors);
 }

} class ColorPyramidDown extends QuadArray {

 private static final float[] verts = {
 // front face
     0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f,
     -1.0f, 0.0f,
     // back face
     0.0f, -1.0f, 0.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 0.0f,
     -1.0f, 0.0f,
     // right face
     0.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
     -1.0f, 0.0f,
     // left face
     0.0f, -1.0f, 0.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 0.0f,
     -1.0f, 0.0f,
     // top face
     1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
     1.0f, 1.0f,
     // bottom face
     0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
     -1.0f, 0.0f, };
 private static final float[] colors = {
 // front face (green)
     0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
     0.0f,
     // back face (red)
     1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
     0.0f,
     // right face (yellow)
     1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
     0.0f,
     // left face (magenta)
     1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
     1.0f,
     // top face (blue)
     0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
     1.0f,
     // bottom face (cyan)
     0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
     1.0f, };
 ColorPyramidDown() {
   super(24, QuadArray.COORDINATES | QuadArray.COLOR_3);
   setCoordinates(0, verts);
   setColors(0, colors);
 }

} class ColorCube extends QuadArray {

 private static final float[] verts = {
 // front face
     1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f,
     -1.0f, 1.0f,
     // back face
     -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
     -1.0f, -1.0f,
     // right face
     1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
     -1.0f, 1.0f,
     // left face
     -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
     -1.0f, -1.0f,
     // top face
     1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
     1.0f, 1.0f,
     // bottom face
     -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
     -1.0f, 1.0f, };
 private static final float[] colors = {
 // front face (red)
     1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
     0.0f,
     // back face (green)
     0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
     0.0f,
     // right face (blue)
     0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
     1.0f,
     // left face (yellow)
     1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
     0.0f,
     // top face (magenta)
     1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
     1.0f,
     // bottom face (cyan)
     0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
     1.0f, };
 ColorCube() {
   super(24, QuadArray.COORDINATES | QuadArray.COLOR_3);
   setCoordinates(0, verts);
   setColors(0, colors);
 }

} //User-defined morphing behavior class class MorphingBehavior extends Behavior {

 Alpha alpha;
 Morph morph;
 double weights[];
 WakeupOnElapsedFrames w = new WakeupOnElapsedFrames(0);
 // Override Behavior"s initialize method to setup wakeup criteria
 public void initialize() {
   alpha.setStartTime(System.currentTimeMillis());
   // Establish initial wakeup criteria
   wakeupOn(w);
 }
 // Override Behavior"s stimulus method to handle the event
 public void processStimulus(Enumeration criteria) {
   // NOTE: This assumes 3 objects. It should be generalized to
   // "n" objects.
   double val = alpha.value();
   if (val < 0.5) {
     double a = val * 2.0;
     weights[0] = 1.0 - a;
     weights[1] = a;
     weights[2] = 0.0;
   } else {
     double a = (val - 0.5) * 2.0;
     weights[0] = 0.0;
     weights[1] = 1.0f - a;
     weights[2] = a;
   }
   morph.setWeights(weights);
   // Set wakeup criteria for next time
   wakeupOn(w);
 }
 public MorphingBehavior(Alpha a, Morph m) {
   alpha = a;
   morph = m;
   weights = morph.getWeights();
 }

}

class BoltCG extends CompressedGeometry {

 BoltCG() {
   super(cgHeader, cgData);
 }
 private static final byte cgData[] = { 25, 0, -120, 16, -124, 64, 33, -35,
     0, 67, 60, 48, -121, 90, 1, 3, 116, -62, 25, 105, -60, 60, -32, 8,
     5, -58, 16, -9, -114, 32, -1, -104, 67, 16, 0, -117, -128, 97, 40,
     62, -62, -128, -122, 5, 67, 48, 10, -76, -32, 21, 1, 6, 40, 10,
     -128, 86, -123, 24, -96, 76, 65, 74, 88, 2, -117, -80, -59, 21,
     113, -118, -40, -28, 21, 110, 6, 40, 27, 64, 81, 23, -124, -7, 47,
     54, 13, -3, -4, 69, 40, 25, -69, -99, -123, 64, 8, 48, 3, 64, 16,
     23, 16, 97, -39, 8, -20, -125, 0, 36, 2, 1, -123, 2, 8, -120, 48,
     27, 122, 91, 65, -67, 108, 18, 26, 13, -12, -35, 95, -48, 107, 63,
     -5, 91, -46, 12, 84, -44, -53, -120, 54, -45, -98, 115, 64, -69,
     92, 126, -55, 1, 6, -80, 34, -49, -24, 53, -30, 61, -19, 9, 6, -76,
     10, -115, -24, 53, 87, -54, -2, -127, 113, 68, -15, -33, 16, 97,
     -9, 113, -54, -30, 12, 75, 34, -48, -48, 107, 86, -32, -10, -125,
     97, -42, 19, -78, 12, 0, -48, 4, 4, 68, 8, 12, -67, -69, 32, -64,
     9, 0, 0, 92, 65, -121, 116, 42, 10, 13, 98, -52, -97, 16, 34, 104,
     114, 75, 66, 12, -45, 11, -82, 32, -34, -74, -127, -15, 6, 74, 51,
     70, -81, 32, -42, 27, 105, 13, 6, -97, 13, 111, -24, 22, -12, 22,
     -19, -95, 6, -49, -85, -48, 16, 107, 2, 44, -8, -125, 6, 73, -123,
     -97, 16, 37, 40, 68, -22, -30, 12, 58, 97, 80, -112, 104, -16,
     -104, -72, -125, 122, -38, 22, -12, 25, -114, -39, 124, 64, -111,
     -115, -112, -49, -24, 53, -34, 85, -23, 5, 6, -82, -26, 15, 104,
     54, 1, -31, 62, 32, 68, -17, 100, -58, 84, 27, 33, -54, -66, -125,
     55, -2, -89, 32, -119, 122, -73, -25, -36, 105, -128, 8, 53, -128,
     2, 76, -71, 9, -56, -128, 30, 112, -59, -48, 96, -37, 0, 0, 0, 9,
     -112, 28, -117, 100, 64, 127, 58, 113, -58, 13, 96, 0, -109, 46,
     70, 50, 80, 103, -88, 56, -86, 13, 96, 0, -109, 46, 67, 114, -112,
     95, -74, 49, 84, 49, -74, -72, 15, 96, 2, 80, 6, 55, 80, 0, -36,
     82, 0, 40, 3, 108, 1, -58, -95, -63, -84, 0, 18, 101, -56, -74, 87,
     10, 56, 39, 31, -32, -43, -32, 9, 50, -28, 87, 46, -125, 28, -61,
     -117, -48, 107, 0, 4, -103, 114, 19, -105, -65, -98, 117, -60, 32,
     -63, -84, 0, 18, 101, -116, -74, 45, 1, -15, 1, -57, 0, -29, -116,
     26, -64, 1, 38, 92, -116, 101, 111, 79, 124, 113, 83, -6, -68, 8,
     37, -36, -83, -4, -93, -4, 109, 46, 55, 6, -81, 0, 73, -105, 33,
     -71, 63, -57, -40, -36, 82, 28, 26, -64, 1, 38, 92, -117, 100,
     -113, 71, 71, 113, -2, 13, 96, 0, -109, 46, 69, 114, 47, -41, -99,
     -72, -67, 6, -80, 0, 73, -107, -63, 72, -64, -113, -83, 99, 72, 53,
     97, -6, 65, 57, -67, 60, -38, -26, -63, -78, 105, 11, 112, 85, 110,
     101, -95, 58, -128, 16, 107, -125, 90, -60, 3, 0, 0, 1, 0, 32, 64,
     67, -32, -54, -41, -103, 113, 6, -55, -92, 45, -63, 85, -71, -106,
     -34, -22, 0, 55, -79, -36, -28, 62, -95, -68, 97, -73, -41, -70,
     -122, -13, 117, -50, 94, -22, 32, 80, 21, 77, -39, 6, 0, 48, 6, 2,
     10, 13, 61, 106, -104, 80, 32, -68, -125, 64, -75, 100, 17, 91,
     -78, 90, -67, -42, 24, 55, 27, -39, 61, 0, -56, 63, -40, -71, -95,
     -124, 49, 74, 37, 3, 7, -83, 118, -18, 13, -79, 30, -96, -126, 80,
     77, 53, 19, -32, -47, -121, -103, 104, -122, 82, 89, -19, 56, 92,
     45, -96, -73, 42, -128, 16, 109, -120, -11, 4, 18, -126, 105, -88,
     126, 70, -127, -56, -24, 48, -43, -36, 20, -25, -48, -60, -115, -4,
     -98, -42, -31, -84, 8, -35, -13, 59, -96, -36, 11, 1, 64, 69, 65,
     -126, 80, -85, 10, 4, 22, -48, 97, 109, -42, -114, 71, 112, -106,
     -58, -51, 6, 104, 48, 82, 8, -19, -74, -36, -81, -100, -56, -122,
     85, 34, -111, -37, 125, -83, 103, 65, -89, 125, -30, -15, 36, -20,
     -5, 81, -63, 68, 27, -17, -89, -83, 3, -63, -89, 33, -24, 66, 0, 7,
     50, 45, 2, -56, 17, 6, -99, -9, -117, -60, -109, -77, -19, 122, 5,
     14, 96, 110, 114, 71, -92, 117, 39, 107, 93, -50, 105, 49, 110,
     -75, 80, 46, -125, -68, -18, -125, 80, 60, 10, 1, -111, 6, -76, 10,
     48, -96, 65, 105, 6, -120, 27, 8, 68, -77, -109, -59, 90, -64, 16,
     106, -61, -12, -26, 17, 26, 10, 54, -53, 40, -88, 1, 6, -14, 124,
     52, 32, -39, 13, -117, 66, 13, 63, -111, -80, -96, 65, 117, 6, 103,
     -11, -120, 104, 54, -49, 116, 92, 65, -102, -84, -125, 50, 12, 87,
     -109, 67, 64, -124, 106, -22, -22, 12, 28, -24, -48, -48, 109, 94,
     -22, -48, -125, 10, -96, 75, -120, 17, 39, -119, 104, 65, -92,
     -110, 68, 36, 27, 99, -87, -73, -96, -56, -42, -85, 18, 12, 8, 3,
     -22, 0, 28, 1, 120, 34, -112, -6, -81, 52, -64, 4, 24, -88, 0, 0,
     14, 0, -104, 39, 32, 44, 23, -98, -125, 6, 44, 0, 0, 3, -128, 38,
     22, -56, 95, 13, -25, 24, 49, 80, 0, 0, 28, 1, 48, -58, -28, -38,
     -113, 42, -125, 21, 0, 0, 1, -80, 19, 70, -24, 73, -46, -13, 80,
     -32, -59, 64, 0, 0, 108, 7, -94, -37, -127, -1, 30, 127, -125, 21,
     0, 0, 1, -64, 30, -118, -18, -124, -124, 121, 122, 12, 84, 0, 0, 7,
     0, 78, 19, -81, -32, 99, -56, 65, -125, 22, 0, 0, 1, -64, 30, 11,
     110, 64, 117, 0, 0, 2, -106, 48, 106, 2, 56, -102, 99, 126, 15, 53,
     37, 65, -81, -8, -30, 104, -36, -75, -8, -98, 82, 28, 24, -88, 0,
     0, 13, -128, -104, 91, 93, -20, -41, -97, -32, -59, 64, 0, 0, 112,
     7, -94, -69, 31, 56, -98, 94, -125, 21, 0, 0, 1, -64, 24, 77, -96,
     -39, -12, 65, -125, 41, 86, -79, 58, 14, -56, 87, 102, -112, 105,
     -50, 18, -42, 11, 91, 10, -54, -9, 6, 61, -1, -87, 3, 51, 55, -14,
     86, 108, 80, 111, -5, -18, -110, 55, 34, 112, -43, 114, -123, 6, 1,
     63, 9, 32, -11, 21, 28, 87, 36, 4, 32, -56, 83, -3, 36, -82, -1,
     -60, -86, -31, -63, -88, -40, 98, 73, -99, -72, 71, 27, 59, 6, 3,
     38, -110, 12, 111, -92, 4, -39, -8, 49, -111, 74, -112, 51, 28,
     -18, -90, -64, 37, 6, 80, -54, -38, -51, 106, -93, 73, -80, 5, 8,
     50, 119, 84, -116, 47, 110, 123, -10, -60, 45, 6, 45, 104, 81,
     -116, 106, 15, 126, -40, -40, 48, 101, 42, -30, 109, 90, -16, 69,
     123, -81, -47, 6, 112, 0, 0, 9, 1, 4, 78, 1, 17, -114, -67, 6, 12,
     -32, 0, 0, 18, 2, 9, 108, -111, -28, 29, 113, -125, 56, 0, 0, 4,
     -128, -124, 99, 119, 92, 87, 85, 65, -100, 0, 0, 2, 64, 106, 53,
     -112, 31, 101, -80, 30, 13, -35, -80, 85, -86, -95, -63, -109, -1,
     117, -46, -38, 46, -94, -70, 127, 6, -112, 0, 0, 119, 1, 124, -82,
     39, 15, 46, -113, 65, -92, 0, 0, 29, -128, 127, 19, -67, -4, -112,
     -82, -127, 6, 13, 40, 0, 0, -18, 2, -15, 108, -81, -40, 29, 49,
     -125, 72, 0, 0, 59, 0, -70, 99, 9, -61, -106, -91, 65, -112, 31,
     102, -44, 27, 62, -118, 116, 65, -92, 0, 0, 29, -64, 117, 65, -100,
     0, 0, 2, 64, 122, 27, -111, -127, -35, -75, 33, -63, -80, 8, -92,
     34, -40, -52, 86, -70, -1, 6, 108, 0, 0, 10, 1, 4, -82, 122, 114,
     -114, -81, 65, -100, 0, 0, 2, 64, 115, 26, -113, -107, -98, -115,
     -46, -95, -63, -71, 0, 0, 28, -128, 87, 65, -123, -57, -69, -22,
     12, 4, 9, -32, 118, 65, -128, 24, 7, -128, -96, -127, 27, -128,
     101, -12, 27, 36, 13, -93, -96, -50, -29, 89, -31, 6, -114, 0, 0,
     29, -96, 48, -96, 65, -7, 6, -4, 72, 30, -79, 32, -56, 32, 59, -32,
     60, 96, 23, -48, 110, -124, 50, -80, -127, 116, -126, -89, 100, 25,
     -128, 0, 120, 15, 72, 51, 119, -74, 52, 32, -38, -8, -94, -70, 5,
     65, -123, 30, 16, 104, -96, 0, 1, -36, 3, 42, 13, -1, 127, 124, 26,
     -122, -64, 5, -22, -4, 74, 12, 0, 68, -102, -48, 99, 117, 1, 73, 6,
     -72, -55, -17, -120, 54, 115, -83, -3, 73, 6, -46, 15, -85, -88,
     50, 112, -91, 104, 65, -110, 43, 22, -12, 27, 27, 83, 104, 65,
     -114, -126, -105, -64, -119, -33, 105, -120, -71, 76, 0, 65, -81,
     -99, -54, 82, 13, 3, 78, 81, 80, 107, -25, 76, -122, -125, 0, -60,
     23, -28, 10, -17, -97, 42, -24, -125, 112, 0, 0, 56, -128, -76,
     -125, 32, -43, -89, -92, 27, -65, 50, -99, -112, 96, 1, 0, -32, 40,
     -96, 72, 49, -107, 57, 6, -34, -109, 104, 40, 51, 12, 68, 67, 64,
     -128, 98, 11, -78, 12, -64, 16, 24, 7, -108, 25, -64, 0, 0, 9,
     -128, -16, 109, 72, 0, 0, 14, -48, 30, -20, 56, 55, -23, 7, 43,
     -96, -54, -29, -35, 97, 6, -88, 69, 13, 8, 49, 69, -46, -6, -127,
     14, 68, -125, -34, 80, 103, 0, 0, 0, 36, 2, 58, 12, 110, 53, -44,
     80, 110, -112, 112, -54, -125, 127, -33, -40, 80, 32, -68, -125,
     59, -18, -74, 36, 25, 0, 0, 0, 7, -66, 3, -14, 13, -1, -12, 31,
     104, 64, -118, 46, -105, 100, 24, 1, 32, 104, 14, -120, 55, 32, 0,
     3, -112, 15, -29, 85, 84, -127, 5, -120, 9, 65, -112, 0, 0, 0, 123,
     -32, 63, 32, -38, -57, 127, 55, -44, 24, -97, 40, 18, -4, -125,
     105, 56, -15, 95, 80, 96, -68, 16, -93, 122, 5, 110, -88, 40, 32,
     -64, 20, 113, -11, 6, 11, -59, 8, -69, 32, -64, 12, 0, -64, 111,
     64, -83, -43, 7, 100, 24, -128, -96, 88, 12, 104, 53, -4, 0, 0, 0,
     -124, 7, -64, -118, -33, -106, -102, -13, -84, 0, 65, -100, 0, 0,
     0, -104, 9, 72, 50, 13, 56, 126, 65, -70, -4, -6, -49, -88, 50,
     112, -39, -59, -115, 6, -83, 1, -13, 1, -53, 0, -8, -125, 37, 13,
     34, -41, 16, 107, -25, 116, -122, -125, 0, -60, 7, -16, -118, 102,
     102, -36, -66, -118, 0, 65, -67, -1, -30, 10, 12, -99, 74, 94, -48,
     110, -31, 108, 104, 65, -102, -87, 103, -60, 8, 34, -100, 36, -2,
     -125, 124, -84, -5, -97, 16, 98, 43, -46, 27, 34, 12, 127, -101,
     127, 64, -80, -47, -16, -19, 8, 53, -33, 88, -8, -125, 20, 109, 19,
     95, -48, 111, -111, -1, -117, 66, 13, -57, 92, 63, -96, 93, -104,
     -99, 119, -60, 24, 84, -16, 82, -8, -125, 3, 80, 2, -38, 16, 103,
     -116, 101, -19, 2, -18, 110, -26, 68, 24, -117, -98, -56, -125, 5,
     -64, -35, -112, 96, 4, 0, 32, 63, -102, 89, 15, 119, -122, 112, 12,
     32, -38, -68, 70, -110, 91, -114, -68, 111, 2, 16, 96, -65, -23,
     -123, 2, 13, 7, 118, -36, 104, -127, 46, -26, -117, -92, -19, 36,
     102, 0, -128, -64, 61, -61, 84, 87, -73, 74, 32, -24, 50, 11, 10,
     111, 57, -79, -36, -28, 10, 93, 24, 4, 22, 106, -32, -42, 17, -42,
     -29, -104, -37, 74, 105, -73, -9, -48, 112, -35, -82, 107, 119, 73,
     10, -33, 78, -4, -79, -97, 96, -54, -14, 54, -128, 58, 97, 8, 111,
     4, 3, -50, -37, -53, 64, -124, 0, 14, -103, 65, -41, -127, 8, 53,
     6, -14, 65, 65, -97, -48, 115, 113, -51, -74, 42, 50, 82, 57, 40,
     -86, -53, -100, -41, -66, -74, 106, -125, 82, 116, -39, -48, 38,
     51, 107, 121, 44, 88, -28, 34, 96, 4, -78, 4, 75, 118, -64, 16, 96,
     4, -127, -96, 45, -110, 88, 14, -31, 3, 0, 65, -65, -128, 10, 25,
     44, -61, 81, -40, -16, 3, -85, -100, 0, 20, 6, -12, 3, 49, -63,
     -107, 14, 15, 71, -16, 99, 19, -81, -37, -102, -15, -37, 32, -21,
     -7, 6, -91, -81, 91, -119, -4, 88, -77, -20, 26, -49, -96, -54, 23,
     112, -72, -41, -35, 64, 8, 53, 11, 14, 102, 65, -123, -35, -52,
     -94, 55, 24, -7, -45, -72, -75, -123, 0, 0, 22, -64, 111, -16, 2,
     13, 97, -46, 48, -96, 65, 0, 86, 40, 32, -120, 21, -124, -115, 46,
     54, 29, -69, 11, 88, 0, -96, 96, 11, -32, 60, 20, -94, 25, 99, 53,
     97, -125, 8, 91, -48, 2, 101, 113, -54, -128, -20, 0, 10, -85, -70,
     -117, 50, 32, 1, 6, 75, 84, 46, -99, -38, -53, -51, 9, -59, -59,
     52, 25, 121, 16, 0, 119, 27, -114, -108, 39, 21, 4, -111, -26, 116,
     64, 2, 13, 121, -104, 105, 63, -115, 58, -42, 122, -125, 106, -15,
     25, -112, 99, 35, -32, 8, 5, -96, 0 };
 private static final CompressedGeometryHeader cgHeader;
 static {
   cgHeader = new CompressedGeometryHeader();
   cgHeader.majorVersionNumber = 1;
   cgHeader.minorVersionNumber = 0;
   cgHeader.minorMinorVersionNumber = 1;
   cgHeader.bufferType = CompressedGeometryHeader.TRIANGLE_BUFFER;
   cgHeader.bufferDataPresent = CompressedGeometryHeader.NORMAL_IN_BUFFER;
   cgHeader.start = 0;
   cgHeader.size = cgData.length;
 }

}


      </source>
   
  
 
  



Rotate when any key is pressed

   <source lang="java">

/*

* @(#)SimpleBehaviorApp.java 1.0 99/03/25 11:42:40
* 
* Copyright (c) 1996-1999 Sun Microsystems, Inc. All Rights Reserved.
* 
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
* 
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
* 
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear facility.
* Licensee represents and warrants that it will not use or redistribute the
* Software for such purposes.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import java.awt.event.KeyEvent; import java.util.Enumeration; import javax.media.j3d.Behavior; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.WakeupOnAWTEvent; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.SimpleUniverse; // SimpleBehaviorApp renders a single ColorCube // that rotates when any key is pressed. public class SimpleBehaviorApp extends Applet {

 public class SimpleBehavior extends Behavior {
   private TransformGroup targetTG;
   private Transform3D rotation = new Transform3D();
   private double angle = 0.0;
   // create SimpleBehavior
   SimpleBehavior(TransformGroup targetTG) {
     this.targetTG = targetTG;
   }
   // initialize the Behavior
   //     set initial wakeup condition
   //     called when behavior beacomes live
   public void initialize() {
     // set initial wakeup condition
     this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
   }
   // behave
   // called by Java 3D when appropriate stimulus occures
   public void processStimulus(Enumeration criteria) {
     // decode event
     // do what is necessary
     angle += 0.1;
     rotation.rotY(angle);
     targetTG.setTransform(rotation);
     this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
   }
 } // end of class SimpleBehavior
 public BranchGroup createSceneGraph() {
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   TransformGroup objRotate = new TransformGroup();
   objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objRoot.addChild(objRotate);
   objRotate.addChild(new ColorCube(0.4));
   SimpleBehavior myRotationBehavior = new SimpleBehavior(objRotate);
   myRotationBehavior.setSchedulingBounds(new BoundingSphere());
   objRoot.addChild(myRotationBehavior);
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 } // end of CreateSceneGraph method of SimpleBehaviorApp
 // Create a simple scene and attach it to the virtual universe
 public SimpleBehaviorApp() {
   setLayout(new BorderLayout());
   Canvas3D canvas3D = new Canvas3D(null);
   add("Center", canvas3D);
   BranchGroup scene = createSceneGraph();
   // SimpleUniverse is a Convenience Utility class
   SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   simpleU.getViewingPlatform().setNominalViewingTransform();
   simpleU.addBranchGraph(scene);
 } // end of SimpleBehaviorApp (constructor)
 //  The following allows this to be run as an application
 //  as well as an applet
 public static void main(String[] args) {
   System.out
       .print("SimpleBehaviorApp.java \n- a demonstration of creating a simple");
   System.out
       .println("behavior class to provide interaction in a Java 3D scene.");
   System.out
       .println("When the app loads, press any key to make the cube rotate.");
   System.out
       .println("This is a simple example progam from The Java 3D API Tutorial.");
   System.out.println("The Java 3D Tutorial is available on the web at:");
   System.out.println("http://www.sun.ru/desktop/java3d/collateral");
   Frame frame = new MainFrame(new SimpleBehaviorApp(), 256, 256);
 } // end of main (method of SimpleBehaviorApp)

} // end of class SimpleBehaviorApp


      </source>
   
  
 
  



This application demonstrates the use of a billboard node

   <source lang="java">

/* Essential Java 3D Fast Ian Palmer Publisher: Springer-Verlag ISBN: 1-85233-394-4

  • /

import java.awt.BorderLayout; import java.awt.Button; import java.awt.Frame; import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.Billboard; import javax.media.j3d.BoundingLeaf; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.media.j3d.ViewPlatform; import javax.media.j3d.VirtualUniverse; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior; import com.sun.j3d.utils.geometry.Box; import com.sun.j3d.utils.geometry.ColorCube; /**

* This application demonstrates the use of a billboard node. Two cubes are
* created, one yellow and the other with a a different colour on each face. The
* billboard is created so that the red face of the right cube is always facing
* the viewer. A key board utility class is used to allow modification of the
* view angle.
* 
* @author I.J.Palmer
* @version 1.0
*/

public class SimpleBillboard extends Frame implements ActionListener {

 protected Canvas3D myCanvas3D = new Canvas3D(null);
 protected Button exitButton = new Button("Exit");
 protected BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0,
     0.0), 100.0);
 /**
  * Build the view branch of the scene graph. In this case a key navigation
  * utility object is created and associated with the view transform so that
  * the view can be changed via the keyboard.
  * 
  * @return BranchGroup that is the root of the view branch
  */
 protected BranchGroup buildViewBranch(Canvas3D c) {
   BranchGroup viewBranch = new BranchGroup();
   Transform3D viewXfm = new Transform3D();
   viewXfm.set(new Vector3f(0.0f, 0.0f, 10.0f));
   TransformGroup viewXfmGroup = new TransformGroup(viewXfm);
   viewXfmGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   viewXfmGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   BoundingSphere movingBounds = new BoundingSphere(new Point3d(0.0, 0.0,
       0.0), 100.0);
   BoundingLeaf boundLeaf = new BoundingLeaf(movingBounds);
   ViewPlatform myViewPlatform = new ViewPlatform();
   viewXfmGroup.addChild(boundLeaf);
   PhysicalBody myBody = new PhysicalBody();
   PhysicalEnvironment myEnvironment = new PhysicalEnvironment();
   viewXfmGroup.addChild(myViewPlatform);
   viewBranch.addChild(viewXfmGroup);
   View myView = new View();
   myView.addCanvas3D(c);
   myView.attachViewPlatform(myViewPlatform);
   myView.setPhysicalBody(myBody);
   myView.setPhysicalEnvironment(myEnvironment);
   KeyNavigatorBehavior keyNav = new KeyNavigatorBehavior(viewXfmGroup);
   keyNav.setSchedulingBounds(movingBounds);
   viewBranch.addChild(keyNav);
   return viewBranch;
 }
 /**
  * Add some lights to the scene graph
  * 
  * @param b
  *            BranchGroup that the lights are added to
  */
 protected void addLights(BranchGroup b) {
   Color3f ambLightColour = new Color3f(0.5f, 0.5f, 0.5f);
   AmbientLight ambLight = new AmbientLight(ambLightColour);
   ambLight.setInfluencingBounds(bounds);
   Color3f dirLightColour = new Color3f(1.0f, 1.0f, 1.0f);
   Vector3f dirLightDir = new Vector3f(-1.0f, -1.0f, -1.0f);
   DirectionalLight dirLight = new DirectionalLight(dirLightColour,
       dirLightDir);
   dirLight.setInfluencingBounds(bounds);
   b.addChild(ambLight);
   b.addChild(dirLight);
 }
 /**
  * Build the content branch for the scene graph. This creates two cubes and
  * uses a billboard node to keep one face of one of the cubes facing the
  * viewer.
  * 
  * @return BranchGroup that is the root of the content
  */
 protected BranchGroup buildContentBranch() {
   //Create the appearance
   Appearance app = new Appearance();
   Color3f ambientColour = new Color3f(1.0f, 1.0f, 0.0f);
   Color3f emissiveColour = new Color3f(0.0f, 0.0f, 0.0f);
   Color3f specularColour = new Color3f(1.0f, 1.0f, 1.0f);
   Color3f diffuseColour = new Color3f(1.0f, 1.0f, 0.0f);
   float shininess = 20.0f;
   app.setMaterial(new Material(ambientColour, emissiveColour,
       diffuseColour, specularColour, shininess));
   //Make the cubes
   Box leftCube = new Box(1.0f, 1.0f, 1.0f, app);
   ColorCube rightCube = new ColorCube();
   //Create the transformgroup used for the billboard
   TransformGroup billBoardGroup = new TransformGroup();
   //Set the access rights to the group
   billBoardGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   //Add the cube to the group
   billBoardGroup.addChild(rightCube);
   //Create and activate the billboard
   Billboard myBillboard = new Billboard(billBoardGroup,
       Billboard.ROTATE_ABOUT_AXIS, new Vector3f(0.0f, 1.0f, 0.0f));
   myBillboard.setSchedulingBounds(bounds);
   BranchGroup contentBranch = new BranchGroup();
   contentBranch.addChild(myBillboard);
   addLights(contentBranch);
   //Position the cubes
   TransformGroup bothGroup = new TransformGroup();
   Transform3D leftGroupXfm = new Transform3D();
   leftGroupXfm.set(new Vector3d(-1.5, 0.0, 0.0));
   TransformGroup leftGroup = new TransformGroup(leftGroupXfm);
   Transform3D rightGroupXfm = new Transform3D();
   rightGroupXfm.set(new Vector3d(1.5, 0.0, 0.0));
   TransformGroup rightGroup = new TransformGroup(rightGroupXfm);
   //Put it all together
   bothGroup.addChild(leftGroup);
   leftGroup.addChild(leftCube);
   bothGroup.addChild(rightGroup);
   rightGroup.addChild(billBoardGroup);
   contentBranch.addChild(bothGroup);
   return contentBranch;
 }
 /**
  * Use the action event of the exit button to end the application.
  */
 public void actionPerformed(ActionEvent e) {
   dispose();
   System.exit(0);
 }
 public SimpleBillboard() {
   VirtualUniverse myUniverse = new VirtualUniverse();
   Locale myLocale = new Locale(myUniverse);
   myLocale.addBranchGraph(buildViewBranch(myCanvas3D));
   myLocale.addBranchGraph(buildContentBranch());
   setTitle("SimpleBillboard");
   setSize(400, 400);
   setLayout(new BorderLayout());
   Panel bottom = new Panel();
   bottom.add(exitButton);
   add(BorderLayout.CENTER, myCanvas3D);
   add(BorderLayout.SOUTH, bottom);
   exitButton.addActionListener(this);
   setVisible(true);
 }
 public static void main(String[] args) {
   SimpleBillboard sw = new SimpleBillboard();
 }

}

      </source>
   
  
 
  



This is our first simple program that creates a cube

   <source lang="java">

/* Essential Java 3D Fast Ian Palmer Publisher: Springer-Verlag ISBN: 1-85233-394-4

  • /

//Import the Java3D classes import java.awt.BorderLayout; import java.awt.Button; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.media.j3d.Appearance; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Locale; import javax.media.j3d.Node; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.QuadArray; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.media.j3d.ViewPlatform; import javax.media.j3d.VirtualUniverse; import javax.vecmath.AxisAngle4d; import javax.vecmath.Vector3f; /**

* This is our first simple program that creates a cube. We have no lighting
* defined so the object appears a bright white colour. The cube is tilted
* slightly so that we can see its shape by creating a transform group.
* 
* @author I.J.Palmer
* @version 1.0
*/

public class SimpleWorld extends Frame implements ActionListener {

 /** The canvas 3D used to display the scene. */
 protected Canvas3D myCanvas3D = new Canvas3D(null);
 /** The AWT button used to exit the application. */
 protected Button myButton = new Button("Exit");
 /**
  * This function builds the view branch of the scene graph. It creates a
  * branch group and then creates the necessary view elements to give a
  * useful view of our content.
  * 
  * @param c
  *            Canvas3D that will display the view
  * @return BranchGroup that is the root of the view elements
  */
 protected BranchGroup buildViewBranch(Canvas3D c) {
   //This is the root of our view branch
   BranchGroup viewBranch = new BranchGroup();
   //The transform that will move our view
   //back 5 units along the z-axis
   Transform3D viewXfm = new Transform3D();
   viewXfm.set(new Vector3f(0.0f, 0.0f, 5.0f));
   //The transform group that will be the parent
   //of our view platform elements
   TransformGroup viewXfmGroup = new TransformGroup(viewXfm);
   ViewPlatform myViewPlatform = new ViewPlatform();
   //Next the physical elements are created
   PhysicalBody myBody = new PhysicalBody();
   PhysicalEnvironment myEnvironment = new PhysicalEnvironment();
   //Then we put it all together
   viewXfmGroup.addChild(myViewPlatform);
   viewBranch.addChild(viewXfmGroup);
   View myView = new View();
   myView.addCanvas3D(c);
   myView.attachViewPlatform(myViewPlatform);
   myView.setPhysicalBody(myBody);
   myView.setPhysicalEnvironment(myEnvironment);
   return viewBranch;
 }
 /**
  * This builds the content branch of our scene graph. It uses the buildCube
  * function to create the actual shape, adding to to the transform group so
  * that the shape is slightly tilted to reveal its 3D shape.
  * 
  * @param shape
  *            Node that represents the geometry for the content
  * @return BranchGroup that is the root of the content branch
  */
 protected BranchGroup buildContentBranch(Node shape) {
   //Create the branch group that will be the root of the content branch
   BranchGroup contentBranch = new BranchGroup();
   //Create the transform that will cause the shape to appear tilted
   Transform3D rotateCube = new Transform3D();
   rotateCube.set(new AxisAngle4d(1.0, 1.0, 0.0, Math.PI / 4.0));
   TransformGroup rotationGroup = new TransformGroup(rotateCube);
   //Put the branch together
   contentBranch.addChild(rotationGroup);
   rotationGroup.addChild(shape);
   return contentBranch;
 }
 /**
  * This constructs a cube as an array of quadrilateral polygons. There are
  * six faces, each with four vertices (obviously!). The cube extends 1 unit
  * along each axis in the positive and negavtive directions and is centred
  * on the origin.
  * 
  * @return Shape3D that is the cube
  */
 protected Shape3D buildCube() {
   //Create the array of numbers that will form the
   //vertex information.
   float[] cubeFaces = { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
       1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f,
       -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
       -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
       -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f,
       -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
       -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
       -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f };
   //Create the array of quadrilaterals from the vertices
   QuadArray cubeData = new QuadArray(24, QuadArray.COORDINATES);
   cubeData.setCoordinates(0, cubeFaces);
   //Create a default appearance
   Appearance app = new Appearance();
   //Create and return the cube
   return new Shape3D(cubeData, app);
 }
 /**
  * Handles the exit button action to quit the program.
  */
 public void actionPerformed(ActionEvent e) {
   dispose();
   System.exit(0);
 }
 /**
  * This creates a default universe and locale, creates a window and uses the
  * functions defined in this class to build the view and content branches of
  * the scene graph.
  */
 public SimpleWorld() {
   //Create a default universe and locale
   VirtualUniverse myUniverse = new VirtualUniverse();
   Locale myLocale = new Locale(myUniverse);
   //Use the functions to build the scene graph
   myLocale.addBranchGraph(buildViewBranch(myCanvas3D));
   myLocale.addBranchGraph(buildContentBranch(buildCube()));
   //Do some AWT stuff to set up the window
   setTitle("SimpleWorld");
   setSize(400, 400);
   setLayout(new BorderLayout());
   add("Center", myCanvas3D);
   myButton.addActionListener(this);
   add("South", myButton);
   setVisible(true);
 }
 /**
  * Just create the class and run!
  */
 public static void main(String[] args) {
   SimpleWorld sw = new SimpleWorld();
 }

}

      </source>