Java/3D/Object Model — различия между версиями

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

Версия 21:01, 31 мая 2010

A basic hierarchical model of the top part of a human torso

   <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.BorderLayout; import java.awt.GraphicsConfigTemplate; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.io.File; import java.net.URL; import javax.media.j3d.Alpha; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.AudioDevice; import javax.media.j3d.Background; import javax.media.j3d.BoundingSphere; import javax.media.j3d.Bounds; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.GraphicsConfigTemplate3D; import javax.media.j3d.Group; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.RotationInterpolator; 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.audioengines.javasound.JavaSoundMixer; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.Cylinder; import com.sun.j3d.utils.geometry.Primitive; import com.sun.j3d.utils.geometry.Sphere; /**

* This example builds a basic hierarchical model of the top part of a human
* torso (2 arms, neck and head). the arms are built using a hierarchy of
* TransformGroups with Cylinders used for the geometry itself.
* RotationInterpolators are used to crudely animate the model.
*/

public class ScenegraphTest extends Java3dApplet {

 private static int m_kWidth = 400;
 private static int m_kHeight = 400;
 public ScenegraphTest() {
   initJava3d();
 }
 protected double getScale() {
   return 8.0;
 }
 protected BranchGroup createSceneBranchGroup() {
   BranchGroup objRoot = super.createSceneBranchGroup();
   // create some lights for the scene
   Color3f lColor1 = new Color3f(0.7f, 0.7f, 0.7f);
   Vector3f lDir1 = new Vector3f(-1.0f, -1.0f, -1.0f);
   Color3f alColor = new Color3f(0.2f, 0.2f, 0.2f);
   AmbientLight aLgt = new AmbientLight(alColor);
   aLgt.setInfluencingBounds(createApplicationBounds());
   DirectionalLight lgt1 = new DirectionalLight(lColor1, lDir1);
   lgt1.setInfluencingBounds(createApplicationBounds());
   objRoot.addChild(aLgt);
   objRoot.addChild(lgt1);
   // create a rotator to spin the whole model around the Y axis
   TransformGroup objTrans = new TransformGroup();
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   Transform3D yAxis = new Transform3D();
   Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0,
       4000, 0, 0, 0, 0, 0);
   RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
       objTrans, yAxis, 0.0f, (float) Math.PI * 2.0f);
   rotator.setSchedulingBounds(createApplicationBounds());
   objTrans.addChild(rotator);
   // build the model itself using helper methods
   addHead(objTrans);
   objTrans.addChild(createArm(0, 0, -Math.PI * 0.5));
   objTrans.addChild(createArm(0, Math.PI, Math.PI * 0.5));
   objRoot.addChild(objTrans);
   return objRoot;
 }
 private void addHead(Group parentGroup) {
   // add a cylinder for the Neck
   TransformGroup tgNeck = addLimb(parentGroup, "Neck", 0.05, 0.2, 0.0,
       0.0);
   Appearance app = new Appearance();
   Color3f black = new Color3f(0.4f, 0.2f, 0.1f);
   Color3f objColor = new Color3f(1, 0.8f, 0.6f);
   app.setMaterial(new Material(objColor, black, objColor, black, 90.0f));
   // position a Sphere for the head itself
   Sphere headSphere = new Sphere((float) 0.12,
       Primitive.GENERATE_NORMALS, app);
   tgNeck.addChild(headSphere);
 }
 // creates a hierarchical model of a basic arm.
 // the arm is aligned using the three rotations: rotX, rotY, rotZ.
 // by rotating the arm we are able to create a left and a right arm
 // from the same code.
 private TransformGroup createArm(double rotX, double rotY, double rotZ) {
   TransformGroup tgShoulder = new TransformGroup();
   Transform3D t3d = new Transform3D();
   t3d.setEuler(new Vector3d(rotX, rotY, rotZ));
   tgShoulder.setTransform(t3d);
   TransformGroup tgParent = null;
   tgParent = addLimb(tgShoulder, "Upper Arm", 0.05, 0.5, 0.0, 0.0);
   tgParent = addLimb(tgParent, "Lower Arm", 0.03, 0.4, Math.PI * -0.5,
       Math.PI * 0.8);
   TransformGroup tgWrist = addLimb(tgParent, "Wrist", 0.03, 0.07, 0.0,
       Math.PI * 0.5);
   addLimb(tgWrist, "Thumb", 0.01, 0.05, 0.0, Math.PI * 0.5);
   addLimb(tgWrist, "Finger 1", 0.01, 0.08, 0.0, Math.PI * 0.3);
   addLimb(tgWrist, "Finger 2", 0.01, 0.10, 0.0, Math.PI * 0.3);
   addLimb(tgWrist, "Finger 3", 0.01, 0.08, 0.0, Math.PI * 0.3);
   addLimb(tgWrist, "Finger 4", 0.01, 0.05, 0.0, Math.PI * 0.3);
   return tgShoulder;
 }
 // adds a cylinder for a limb to the parentGroup.
 // optionally adds a rotator to rotate the limb between rotMin and rotMax
 // radians.
 private TransformGroup addLimb(Group parentGroup, String szName,
     double radius, double length, double rotMin, double rotMax) {
   // create the rotator
   TransformGroup tgJoint = new TransformGroup();
   tgJoint.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   tgJoint.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   // add a rotator if necessary
   if (rotMin != rotMax) {
     Transform3D xAxis = new Transform3D();
     xAxis.rotX(Math.PI / 2.0);
     Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0,
         4000, 0, 0, 0, 0, 0);
     RotationInterpolator rotator = new RotationInterpolator(
         rotationAlpha, tgJoint, xAxis, (float) rotMin,
         (float) rotMax);
     rotator.setSchedulingBounds(createApplicationBounds());
     tgJoint.addChild(rotator);
   }
   // create a cylinder using length and radius
   tgJoint.addChild(createLimb(radius, length));
   // create the joint (the *next* TG should
   // be offset by the length of this limb)
   TransformGroup tgOffset = new TransformGroup();
   Transform3D t3d = new Transform3D();
   t3d.setTranslation(new Vector3d(0, length, 0));
   tgOffset.setTransform(t3d);
   tgJoint.addChild(tgOffset);
   parentGroup.addChild(tgJoint);
   // return the offset TG, so any child TG"s will be added
   // in the correct position.
   return tgOffset;
 }
 // creates and aligns a cylinder to represent a simple limb.
 TransformGroup createLimb(double radius, double length) {
   // because the cylinder is centered at 0,0,0
   // we need to shift the cylinder so that the bottom of
   // the cylinder is at 0,0,0 and the top is at 0, length, 0
   TransformGroup tg = new TransformGroup();
   Transform3D t3d = new Transform3D();
   t3d.setTranslation(new Vector3d(0, length / 2, 0));
   tg.setTransform(t3d);
   Appearance app = new Appearance();
   Color3f black = new Color3f(0.4f, 0.2f, 0.1f);
   Color3f objColor = new Color3f(1, 0.8f, 0.6f);
   app.setMaterial(new Material(objColor, black, objColor, black, 90.0f));
   Cylinder cylinder = new Cylinder((float) radius, (float) length,
       Primitive.GENERATE_NORMALS, app);
   tg.addChild(cylinder);
   return tg;
 }
 public static void main(String[] args) {
   ScenegraphTest sceneTest = new ScenegraphTest();
   sceneTest.saveCommandLineArguments(args);
   new MainFrame(sceneTest, m_kWidth, m_kHeight);
 }

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

* 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>
   
  
 
  



A large hollow box

   <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.BorderLayout; import java.awt.GraphicsConfigTemplate; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.net.URL; import javax.media.j3d.AmbientLight; 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.DirectionalLight; import javax.media.j3d.GraphicsConfigTemplate3D; import javax.media.j3d.Group; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.Node; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.PickBounds; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.SceneGraphObject; 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.WakeupCondition; import javax.media.j3d.WakeupCriterion; import javax.media.j3d.WakeupOnElapsedFrames; import javax.media.j3d.WakeupOr; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import com.sun.j3d.audioengines.javasound.JavaSoundMixer; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.geometry.Sphere; import com.sun.j3d.utils.picking.PickResult; import com.sun.j3d.utils.picking.PickTool; /**

* This example creates a large hollow box (out of ColorCubes, one for each side
* of the box). Within the box, four Spheres are created. Each Sphere has a
* behavior attached which detects collisions with the sides of the box, and the
* other Spheres. When a collision is detected the trajectory of the Sphere is
* reversed and the color of the Sphere changed. When a collision is not
* detected the Sphere is advanced along its current trajectory.
*/

public class PickCollisionTest extends Java3dApplet implements ActionListener {

 private static int m_kWidth = 400;
 private static int m_kHeight = 400;
 private static final int boxSize = 10;
 public PickCollisionTest() {
   initJava3d();
 }
 public void actionPerformed(ActionEvent event) {
 }
 protected double getScale() {
   return 0.5;
 }
 // method to recursively set the user data for objects in the scenegraph
 // tree
 // we also set the capabilites on Shape3D and Morph objects required by the
 // PickTool
 void recursiveSetUserData(SceneGraphObject root, Object value) {
   root.setUserData(value);
   // recursively process group
   if (root instanceof Group) {
     Group g = (Group) root;
     // recurse on child nodes
     java.util.Enumeration enumKids = g.getAllChildren();
     while (enumKids.hasMoreElements() != false)
       recursiveSetUserData((SceneGraphObject) enumKids.nextElement(),
           value);
   }
 }
 protected void addCube(BranchGroup bg, double x, double y, double z,
     double sx, double sy, double sz, String name, boolean wireframe) {
   // create four ColorCube objects
   TransformGroup cubeTg = new TransformGroup();
   Transform3D t3d = new Transform3D();
   t3d.setTranslation(new Vector3d(x, y, z));
   t3d.setScale(new Vector3d(sx, sy, sz));
   cubeTg.setTransform(t3d);
   ColorCube cube = new ColorCube(1.0);
   // we have to make the front face wireframe
   // or we can"t see inside the box!
   if (wireframe) {
     Appearance app = new Appearance();
     app.setPolygonAttributes(new PolygonAttributes(
         PolygonAttributes.POLYGON_LINE,
         PolygonAttributes.CULL_NONE, 0));
     cube.setAppearance(app);
   }
   cubeTg.addChild(cube);
   recursiveSetUserData(cubeTg, name);
   bg.addChild(cubeTg);
 }
 protected void addSphere(BranchGroup bg, double x, double y, double z,
     Vector3d incVector, String name) {
   Appearance app = new Appearance();
   TransformGroup sphereTg = new TransformGroup();
   Transform3D t3d = new Transform3D();
   t3d.setTranslation(new Vector3d(x, y, z));
   sphereTg.setTransform(t3d);
   sphereTg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   sphereTg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   sphereTg.addChild(new Sphere(1, app));
   bg.addChild(sphereTg);
   recursiveSetUserData(sphereTg, name);
   // create the collision behaviour
   CollisionBehavior collisionBehavior = new CollisionBehavior(bg,
       sphereTg, app, new Vector3d(x, y, z), incVector);
   collisionBehavior.setSchedulingBounds(getApplicationBounds());
   bg.addChild(collisionBehavior);
 }
 protected BranchGroup createSceneBranchGroup() {
   BranchGroup objRoot = super.createSceneBranchGroup();
   Bounds lightBounds = getApplicationBounds();
   AmbientLight ambLight = new AmbientLight(true, new Color3f(1.0f, 1.0f,
       1.0f));
   ambLight.setInfluencingBounds(lightBounds);
   objRoot.addChild(ambLight);
   DirectionalLight headLight = new DirectionalLight();
   headLight.setInfluencingBounds(lightBounds);
   objRoot.addChild(headLight);
   // create ColorCube objects, one for each side of a cube
   addCube(objRoot, 0, boxSize, 0, boxSize, 0.1, boxSize, "Top", false);
   addCube(objRoot, 0, -boxSize, 0, boxSize, 0.1, boxSize, "Bottom", false);
   addCube(objRoot, boxSize, 0, 0, 0.1, boxSize, boxSize, "Right", false);
   addCube(objRoot, -boxSize, 0, 0, 0.1, boxSize, boxSize, "Left", false);
   addCube(objRoot, 0, 0, -boxSize, boxSize, boxSize, 0.1, "Back", false);
   addCube(objRoot, 0, 0, boxSize, boxSize, boxSize, 0.1, "Front", true);
   // create the spheres
   addSphere(objRoot, 0, 3, 4, new Vector3d(0.1, 0.3, 0.1), "Sphere 1");
   addSphere(objRoot, 3, 0, -2, new Vector3d(0.4, 0.1, 0.2), "Sphere 2");
   addSphere(objRoot, 0, -3, 0, new Vector3d(0.2, 0.2, 0.6), "Sphere 3");
   addSphere(objRoot, -3, 0, -4, new Vector3d(0.1, 0.6, 0.3), "Sphere 4");
   return objRoot;
 }
 public static void main(String[] args) {
   PickCollisionTest pickCollisionTest = new PickCollisionTest();
   pickCollisionTest.saveCommandLineArguments(args);
   new MainFrame(pickCollisionTest, m_kWidth, m_kHeight);
 }

} /**

* This behavior detects collisions between the branch of a scene, and a
* collision object. The Java 3D 1.2 picking utilities are used to implement
* collision detection. The objects in the scene that are collidable should have
* their user data set. The collision object"s user data is used to ignore
* collisions between the object and itself.
* 
* When a collision is detected the trajectory of the collision object is
* reversed (plus a small random factor) and an Appearance object is modified.
* 
* When a collision is not detected the collision object is moved along its
* current trajectory and the Appearance color is reset.
* 
* Colision checking is run after every frame.
*  
*/

class CollisionBehavior extends Behavior {

 // the wake up condition for the behavior
 protected WakeupCondition m_WakeupCondition = null;
 // how often we check for a collision
 private static final int ELAPSED_FRAME_COUNT = 1;
 // the branch that we check for collisions
 private BranchGroup pickRoot = null;
 // the collision object that we are controlling
 private TransformGroup collisionObject = null;
 // the appearance object that we are controlling
 private Appearance objectAppearance = null;
 // cached PickBounds object used for collision detection
 private PickBounds pickBounds = null;
 // cached Material objects that define the collided and missed colors
 private Material collideMaterial = null;
 private Material missMaterial = null;
 // the current trajectory of the object
 private Vector3d incrementVector = null;
 // the current position of the object
 private Vector3d positionVector = null;
 public CollisionBehavior(BranchGroup pickRoot,
     TransformGroup collisionObject, Appearance app, Vector3d posVector,
     Vector3d incVector) {
   // save references to the objects
   this.pickRoot = pickRoot;
   this.collisionObject = collisionObject;
   this.objectAppearance = app;
   incrementVector = incVector;
   positionVector = posVector;
   // create the WakeupCriterion for the behavior
   WakeupCriterion criterionArray[] = new WakeupCriterion[1];
   criterionArray[0] = new WakeupOnElapsedFrames(ELAPSED_FRAME_COUNT);
   objectAppearance.setCapability(Appearance.ALLOW_MATERIAL_WRITE);
   collisionObject.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   collisionObject.setCapability(Node.ALLOW_BOUNDS_READ);
   // save the WakeupCriterion for the behavior
   m_WakeupCondition = new WakeupOr(criterionArray);
 }
 public void initialize() {
   // apply the initial WakeupCriterion
   wakeupOn(m_WakeupCondition);
   Color3f objColor = new Color3f(1.0f, 0.1f, 0.2f);
   Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
   collideMaterial = new Material(objColor, black, objColor, black, 80.0f);
   objColor = new Color3f(0.0f, 0.1f, 0.8f);
   missMaterial = new Material(objColor, black, objColor, black, 80.0f);
   objectAppearance.setMaterial(missMaterial);
 }
 protected void onCollide() {
   objectAppearance.setMaterial(collideMaterial);
   incrementVector.negate();
   // add a little randomness
   incrementVector.x += (Math.random() - 0.5) / 20.0;
   incrementVector.y += (Math.random() - 0.5) / 20.0;
   incrementVector.z += (Math.random() - 0.5) / 20.0;
 }
 protected void onMiss() {
   objectAppearance.setMaterial(missMaterial);
 }
 protected void moveCollisionObject() {
   Transform3D t3d = new Transform3D();
   positionVector.add(incrementVector);
   t3d.setTranslation(positionVector);
   collisionObject.setTransform(t3d);
 }
 public boolean isCollision(PickResult[] resultArray) {
   if (resultArray == null || resultArray.length == 0)
     return false;
   // we use the user data on the nodes to ignore the
   // case of the collisionObject having collided with itself!
   // the user data also gives us a good mechanism for reporting the
   // collisions.
   for (int n = 0; n < resultArray.length; n++) {
     Object userData = resultArray[n].getObject().getUserData();
     if (userData != null && userData instanceof String) {
       // check that we are not colliding with ourselves...
       if (((String) userData).equals((String) collisionObject
           .getUserData()) == false) {
         System.out.println("Collision between: "
             + collisionObject.getUserData() + " and: "
             + userData);
         return true;
       }
     }
   }
   return false;
 }
 public void processStimulus(java.util.Enumeration criteria) {
   while (criteria.hasMoreElements()) {
     WakeupCriterion wakeUp = (WakeupCriterion) criteria.nextElement();
     // every N frames, check for a collision
     if (wakeUp instanceof WakeupOnElapsedFrames) {
       // create a PickBounds
       PickTool pickTool = new PickTool(pickRoot);
       pickTool.setMode(PickTool.BOUNDS);
       BoundingSphere bounds = (BoundingSphere) collisionObject
           .getBounds();
       pickBounds = new PickBounds(new BoundingSphere(new Point3d(
           positionVector.x, positionVector.y, positionVector.z),
           bounds.getRadius()));
       pickTool.setShape(pickBounds, new Point3d(0, 0, 0));
       PickResult[] resultArray = pickTool.pickAll();
       if (isCollision(resultArray))
         onCollide();
       else
         onMiss();
       moveCollisionObject();
     }
   }
   // assign the next WakeUpCondition, so we are notified again
   wakeupOn(m_WakeupCondition);
 }

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

* 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>
   
  
 
  



A Morph object to animate a shape between two key shapes

   <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.GeometryArray; import javax.media.j3d.IndexedQuadArray; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.Morph; 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.AxisAngle4d; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3f; /**

* This uses a Morph object to animate a shape between two key shapes: a cube
* and a pyramid. Buttons are used to change the weight values.
* 
* @author I.J.Palmer
* @version 1.0
*/

public class SimpleMorph extends Frame implements ActionListener {

 protected Canvas3D myCanvas3D = new Canvas3D(null);
 /** The button that will animate towards the cube key shape */
 protected Button cubeButton = new Button("Cube");
 /** The button that will animate towards the pyramid key shape */
 protected Button pyraButton = new Button("Pyramid");
 /** The exit button */
 protected Button exitButton = new Button("Exit");
 /** This performs the animation */
 protected Morph myMorph;
 /** The weight values for the morph */
 protected double[] weights = { 0.5, 0.5 };
 /**
  * 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, 5.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) {
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   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);
 }
 /**
  * Create the Morph from the given shapes
  * 
  * @param theShapes
  *            GeometryArray that stores the shapes for the Morph
  * @param app
  *            Appearnce used for the shapes
  * @return Morph that uses the given shapes
  */
 protected Morph createMorph(GeometryArray[] theShapes, Appearance app) {
   //Create the morph from the given shapes and appearance
   myMorph = new Morph(theShapes, app);
   //Set the weights
   myMorph.setWeights(weights);
   //Set the capabilities so that we can read and write the weights
   myMorph.setCapability(Morph.ALLOW_WEIGHTS_READ);
   myMorph.setCapability(Morph.ALLOW_WEIGHTS_WRITE);
   return myMorph;
 }
 /**
  * Build the content branch for the scene graph
  * 
  * @return BranchGroup that is the root of the content
  */
 protected BranchGroup buildContentBranch() {
   //Create the appearance object
   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));
   //Make the cube key shape
   IndexedQuadArray indexedCube = new IndexedQuadArray(8,
       IndexedQuadArray.COORDINATES | IndexedQuadArray.NORMALS, 24);
   Point3f[] cubeCoordinates = { new Point3f(1.0f, 1.0f, 1.0f),
       new Point3f(-1.0f, 1.0f, 1.0f),
       new Point3f(-1.0f, -1.0f, 1.0f),
       new Point3f(1.0f, -1.0f, 1.0f), new Point3f(1.0f, 1.0f, -1.0f),
       new Point3f(-1.0f, 1.0f, -1.0f),
       new Point3f(-1.0f, -1.0f, -1.0f),
       new Point3f(1.0f, -1.0f, -1.0f) };
   Vector3f[] cubeNormals = { new Vector3f(0.0f, 0.0f, 1.0f),
       new Vector3f(0.0f, 0.0f, -1.0f),
       new Vector3f(1.0f, 0.0f, 0.0f),
       new Vector3f(-1.0f, 0.0f, 0.0f),
       new Vector3f(0.0f, 1.0f, 0.0f), new Vector3f(0.0f, -1.0f, 0.0f) };
   int cubeCoordIndices[] = { 0, 1, 2, 3, 7, 6, 5, 4, 0, 3, 7, 4, 5, 6, 2,
       1, 0, 4, 5, 1, 6, 7, 3, 2 };
   int cubeNormalIndices[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
       3, 3, 4, 4, 4, 4, 5, 5, 5, 5 };
   indexedCube.setCoordinates(0, cubeCoordinates);
   indexedCube.setNormals(0, cubeNormals);
   indexedCube.setCoordinateIndices(0, cubeCoordIndices);
   indexedCube.setNormalIndices(0, cubeNormalIndices);
   //Make the pyramid key shape. Although this needs
   //only five vertices to create the desired shape, we
   //need to use six vertices so that it has the same
   //number as the cube.
   IndexedQuadArray indexedPyramid = new IndexedQuadArray(8,
       IndexedQuadArray.COORDINATES | IndexedQuadArray.NORMALS, 24);
   Point3f[] pyramidCoordinates = { new Point3f(0.0f, 1.0f, 0.0f),
       new Point3f(0.0f, 1.0f, 0.0f), new Point3f(-1.0f, -1.0f, 1.0f),
       new Point3f(1.0f, -1.0f, 1.0f), new Point3f(0.0f, 1.0f, 0.0f),
       new Point3f(0.0f, 1.0f, 0.0f),
       new Point3f(-1.0f, -1.0f, -1.0f),
       new Point3f(1.0f, -1.0f, -1.0f) };
   Vector3f[] pyramidNormals = { new Vector3f(0.0f, 0.0f, 1.0f),
       new Vector3f(0.0f, 0.0f, -1.0f),
       new Vector3f(1.0f, 0.0f, 0.0f),
       new Vector3f(-1.0f, 0.0f, 0.0f),
       new Vector3f(0.0f, 1.0f, 0.0f), new Vector3f(0.0f, -1.0f, 0.0f) };
   int pyramidCoordIndices[] = { 0, 1, 2, 3, 7, 6, 5, 4, 0, 3, 7, 4, 5, 6,
       2, 1, 0, 4, 5, 1, 6, 7, 3, 2 };
   int pyramidNormalIndices[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3,
       3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 };
   indexedPyramid.setCoordinates(0, pyramidCoordinates);
   indexedPyramid.setNormals(0, pyramidNormals);
   indexedPyramid.setCoordinateIndices(0, pyramidCoordIndices);
   indexedPyramid.setNormalIndices(0, pyramidNormalIndices);
   //Set the contents of the array to the two shapes
   GeometryArray[] theShapes = new GeometryArray[2];
   theShapes[0] = indexedCube;
   theShapes[1] = indexedPyramid;
   BranchGroup contentBranch = new BranchGroup();
   //Create a transform to rotate the shape slightly
   Transform3D rotateCube = new Transform3D();
   rotateCube.set(new AxisAngle4d(1.0, 1.0, 0.0, Math.PI / 4.0));
   TransformGroup rotationGroup = new TransformGroup(rotateCube);
   contentBranch.addChild(rotationGroup);
   addLights(contentBranch);
   //Call the function to build the morph
   rotationGroup.addChild(createMorph(theShapes, app));
   return contentBranch;
 }
 /**
  * Process the actions from the buttons. The two shape buttons change the
  * geometry so that it is nearer to its corresponding key shape.
  * 
  * @param e
  *            ActionEvent to be processed
  */
 public void actionPerformed(ActionEvent e) {
   //If its the exit button, quit the program
   if (e.getSource() == exitButton) {
     dispose();
     System.exit(0);
   }
   //If its the cube button, increase the weight
   //associated with the cube key shape and reduce
   //the other.
   else if (e.getSource() == cubeButton) {
     if (weights[0] <= 0.9) {
       weights[0] += 0.1;
       weights[1] -= 0.1;
       myMorph.setWeights(weights);
     }
   }
   //If its the pyramid button, increase the weight
   //associated with the pyramid key shape and reduce
   //the cube weight
   else if (e.getSource() == pyraButton) {
     if (weights[1] <= 0.9) {
       weights[0] -= 0.1;
       weights[1] += 0.1;
       myMorph.setWeights(weights);
     }
   }
 }
 /**
  * Constructor that generates the content using the class methods
  */
 public SimpleMorph() {
   VirtualUniverse myUniverse = new VirtualUniverse();
   Locale myLocale = new Locale(myUniverse);
   myLocale.addBranchGraph(buildViewBranch(myCanvas3D));
   myLocale.addBranchGraph(buildContentBranch());
   setTitle("SimpleMorph");
   setSize(400, 400);
   setLayout(new BorderLayout());
   Panel bottom = new Panel();
   bottom.add(pyraButton);
   bottom.add(cubeButton);
   bottom.add(exitButton);
   add(BorderLayout.CENTER, myCanvas3D);
   add(BorderLayout.SOUTH, bottom);
   pyraButton.addActionListener(this);
   cubeButton.addActionListener(this);
   exitButton.addActionListener(this);
   setVisible(true);
 }
 public static void main(String[] args) {
   SimpleMorph sw = new SimpleMorph();
 }

}


      </source>
   
  
 
  



An Object

   <source lang="java">

// From: http://www.micg.et.fh-stralsund.de/Java3D/java3D.htm#Bild1

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import java.awt.GraphicsConfiguration; import javax.media.j3d.Appearance; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.GeometryArray; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.QuadArray; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Color3f; import javax.vecmath.Point3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.universe.SimpleUniverse; public class FarbWurfelAsQuads extends Applet {

 /**
  * init Methoden fur die Darstellung als Applet
  */
 public void init() {
   setLayout(new BorderLayout());
   GraphicsConfiguration config = SimpleUniverse
       .getPreferredConfiguration();
   canvas3D = new Canvas3D(config);
   add("Center", canvas3D);
   BranchGroup szene = macheSzene();
   szene.rupile();
   universe = new SimpleUniverse(canvas3D);
   universe.getViewingPlatform().setNominalViewingTransform();
   universe.addBranchGraph(szene);
 }
 /**
  * Erstellt den Szenegraphen
  * 
  * @return BranchGroup
  */
 public BranchGroup macheSzene() {
   BranchGroup objWurzel = new BranchGroup();
   // Transformation, 2 Rotationen:
   Transform3D drehung = new Transform3D();
   Transform3D drehung2 = new Transform3D();
   drehung.rotX(Math.PI / 4.0d);
   drehung2.rotY(Math.PI / 5.0d);
   drehung.mul(drehung2);
   drehung.setScale(0.5d);
   TransformGroup objDreh = new TransformGroup(drehung);
   Shape3D shape = new Shape3D(makeCube(), makeAppearance());
   objDreh.addChild(shape);
   objWurzel.addChild(objDreh);
   return objWurzel;
 }
 /**
  * Erstellung des ColorCube
  * 
  * @return
  */
 private QuadArray makeCube() {
   QuadArray plane = new QuadArray(24, GeometryArray.COORDINATES
       | GeometryArray.COLOR_3);
   // Punkte und Farben
   Point3f pa = new Point3f(-1.0f, 1.0f, -1.0f);
   Point3f pb = new Point3f(-1.0f, -1.0f, -1.0f);
   Point3f pc = new Point3f(1.0f, -1.0f, -1.0f);
   Point3f pd = new Point3f(1.0f, 1.0f, -1.0f);
   Point3f pe = new Point3f(-1.0f, 1.0f, 1.0f);
   Point3f pf = new Point3f(-1.0f, -1.0f, 1.0f);
   Point3f pg = new Point3f(1.0f, -1.0f, 1.0f);
   Point3f ph = new Point3f(1.0f, 1.0f, 1.0f);
   // Coloreigenschaften
   Color3f red = new Color3f(1.0f, 0.0f, 0.0f);
   Color3f blue = new Color3f(0.0f, 0.0f, 1.0f);
   Color3f green = new Color3f(0.0f, 1.0f, 0.0f);
   Color3f cyan = new Color3f(0.0f, 1.0f, 1.0f);
   Color3f yellow = new Color3f(1.0f, 1.0f, 0.0f);
   Color3f magenta = new Color3f(1.0f, 0.0f, 1.0f);
   // 1. Seite
   plane.setCoordinate(0, pa);
   plane.setColor(0, red);
   plane.setCoordinate(1, pb);
   plane.setColor(1, red);
   plane.setCoordinate(2, pc);
   plane.setColor(2, red);
   plane.setCoordinate(3, pd);
   plane.setColor(3, red);
   // 2. Seite
   plane.setCoordinate(4, pe);
   plane.setColor(4, blue);
   plane.setCoordinate(5, pf);
   plane.setColor(5, blue);
   plane.setCoordinate(6, pg);
   plane.setColor(6, blue);
   plane.setCoordinate(7, ph);
   plane.setColor(7, blue);
   // 3. Seite
   plane.setCoordinate(8, pe);
   plane.setColor(8, green);
   plane.setCoordinate(9, pf);
   plane.setColor(9, green);
   plane.setCoordinate(10, pb);
   plane.setColor(10, green);
   plane.setCoordinate(11, pa);
   plane.setColor(11, green);
   // 4. Seite
   plane.setCoordinate(12, pd);
   plane.setColor(12, cyan);
   plane.setCoordinate(13, pc);
   plane.setColor(13, cyan);
   plane.setCoordinate(14, pg);
   plane.setColor(14, cyan);
   plane.setCoordinate(15, ph);
   plane.setColor(15, cyan);
   // 5. Seite
   plane.setCoordinate(16, pe);
   plane.setColor(16, yellow);
   plane.setCoordinate(17, pa);
   plane.setColor(17, yellow);
   plane.setCoordinate(18, pd);
   plane.setColor(18, yellow);
   plane.setCoordinate(19, ph);
   plane.setColor(19, yellow);
   // 6. Seite
   plane.setCoordinate(20, pf);
   plane.setColor(20, magenta);
   plane.setCoordinate(21, pb);
   plane.setColor(21, magenta);
   plane.setCoordinate(22, pc);
   plane.setColor(22, magenta);
   plane.setCoordinate(23, pg);
   plane.setColor(23, magenta);
   // ubergib den Wurfel
   return plane;
 }
 /**
  * Wurfeldarstellung
  * 
  * @return Appearance
  */
 private Appearance makeAppearance() {
   Appearance a = new Appearance();
   PolygonAttributes p = new PolygonAttributes();
   p.setCullFace(PolygonAttributes.CULL_NONE);
   a.setPolygonAttributes(p);
   return a;
 }
 /**
  * gibt speicher frei
  */
 public void destroy() {
   universe.removeAllLocales();
 }
 public static void main(String[] args) {
   frame = new MainFrame(new FarbWurfelAsQuads(), 500, 500);
   frame.setTitle("ColorCube mittels Geometrieklassen");
 }
 //---- Attribute -----------------------
 private SimpleUniverse universe;
 private Canvas3D canvas3D;
 private static Frame frame;

}

      </source>
   
  
 
  



Appearance Is Everything

   <source lang="java">

/* The Joy of Java 3D by Greg Hopkins Copyright Copyright 2001

  • /

/* There are many ways to change the way that objects in your scene look. You can change their color, how much light they reflect. You can paint them with two-dimensional images, or add rough textures to their surfaces. The Appearance class contains the functions for making these changes. This section shows you how to use these functions. The simplest way of setting the appearance is by specifying only the color and the shading method. This works for setting an object to being a simple color, but to make an object look realistic, you need to specify how an object appears under lights. You do this by creating a Material.

Step Example 1. Create an object Sphere sphere = new Sphere();


2. Create an appearance Appearance ap = new Appearance();


3. Create a color Color3f col = new Color3f(0.0f, 0.0f, 1.0f);


4. Create the coloring attributes ColoringAttributes ca = new ColoringAttributes

                                                (col, ColoringAttributes.NICEST);

5. Add the attributes to the appearance ap.setColoringAttributes(ca);


6. Set the appearance for the object sphere.setAppearance(ap);

  • /


      </source>
   
  
 
  



A simple class using the an indexed quadrilateral array

   <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.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.IndexedQuadArray; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.Node; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; 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.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3f; /**

* This builds a simple class using the an indexed quadrilateral array. This
* demonstrates the use of the IndexedQuadArray class. It defines both the
* vertices and the normals of the shape such that each vertex has only one
* normal and it appears to have smooth edges.
* 
* @author I.J.Palmer
* @version 1.0
*/

public class SimpleIndexedQuadSmooth extends Frame implements ActionListener {

 protected Canvas3D myCanvas3D = new Canvas3D(null);
 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) {
   BranchGroup viewBranch = new BranchGroup();
   Transform3D viewXfm = new Transform3D();
   viewXfm.set(new Vector3f(0.0f, 0.0f, 5.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 so that we can illuminate the scene. This adds one
  * ambient light to bring up the overall lighting level and one directional
  * shape to show the shape of the objects in the scene.
  * 
  * @param b
  *            BranchGroup that the lights are to be added to.
  */
 protected void addLights(BranchGroup b) {
   //Create a bounding sphere to act as the active bounds
   //of the lights
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   //Create the colours and directions
   Color3f lightColour = new Color3f(1.0f, 1.0f, 1.0f);
   Vector3f lightDir = new Vector3f(-1.0f, -1.0f, -1.0f);
   Color3f ambientColour = new Color3f(0.2f, 0.2f, 0.2f);
   //Create the lights
   AmbientLight ambientLight = new AmbientLight(ambientColour);
   ambientLight.setInfluencingBounds(bounds);
   DirectionalLight directionalLight = new DirectionalLight(lightColour,
       lightDir);
   directionalLight.setInfluencingBounds(bounds);
   //Add the lights to the branch
   b.addChild(ambientLight);
   b.addChild(directionalLight);
 }
 /**
  * This builds the content branch of our scene graph. It uses the buildShape
  * function to create the actual shape, adding to to the transform group so
  * that the shape is slightly tilted to reveal its 3D shape. It also uses
  * the addLights function to add some lights to the scene.
  * 
  * @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) {
   BranchGroup contentBranch = new BranchGroup();
   Transform3D rotateCube = new Transform3D();
   rotateCube.set(new AxisAngle4d(1.0, 1.0, 0.0, Math.PI / 4.0));
   TransformGroup rotationGroup = new TransformGroup(rotateCube);
   contentBranch.addChild(rotationGroup);
   rotationGroup.addChild(shape);
   addLights(contentBranch);
   return contentBranch;
 }
 /**
  * Build a cube from an IndexedQuadArray. This method creates the vertices
  * as a set of eight points and the normals as a set of six vectors (one for
  * each face). The data is then defined such that each vertex has a
  * different normal associated with it when it is being used for a different
  * face.
  * 
  * @return Node that is the shape.
  */
 protected Node buildShape() {
   //The shape. The constructor specifies 8 vertices, that both
   //vertices and normals are to be defined and that there are
   //24 normals to be specified (4 for each of the 6 faces).
   IndexedQuadArray indexedCube = new IndexedQuadArray(8,
       IndexedQuadArray.COORDINATES | IndexedQuadArray.NORMALS, 24);
   //The vertex coordinates defined as an array of points.
   Point3f[] cubeCoordinates = { new Point3f(1.0f, 1.0f, 1.0f),
       new Point3f(-1.0f, 1.0f, 1.0f),
       new Point3f(-1.0f, -1.0f, 1.0f),
       new Point3f(1.0f, -1.0f, 1.0f), new Point3f(1.0f, 1.0f, -1.0f),
       new Point3f(-1.0f, 1.0f, -1.0f),
       new Point3f(-1.0f, -1.0f, -1.0f),
       new Point3f(1.0f, -1.0f, -1.0f) };
   //The vertex normals defined as an array of vectors
   Vector3f[] normals = { new Vector3f(1.0f, 1.0f, 1.0f),
       new Vector3f(-1.0f, 1.0f, 1.0f),
       new Vector3f(-1.0f, -1.0f, 1.0f),
       new Vector3f(1.0f, -1.0f, 1.0f),
       new Vector3f(1.0f, 1.0f, -1.0f),
       new Vector3f(-1.0f, 1.0f, -1.0f),
       new Vector3f(-1.0f, -1.0f, -1.0f),
       new Vector3f(1.0f, -1.0f, -1.0f) };
   //Define the indices used to reference vertex array
   int coordIndices[] = { 0, 1, 2, 3, 7, 6, 5, 4, 0, 3, 7, 4, 5, 6, 2, 1,
       0, 4, 5, 1, 6, 7, 3, 2 };
   //Define the indices used to reference normal array
   int normalIndices[] = { 0, 1, 2, 3, 7, 6, 5, 4, 0, 3, 7, 4, 5, 6, 2, 1,
       0, 4, 5, 1, 6, 7, 3, 2 };
   //Set the data
   indexedCube.setCoordinates(0, cubeCoordinates);
   indexedCube.setNormals(0, normals);
   indexedCube.setCoordinateIndices(0, coordIndices);
   indexedCube.setNormalIndices(0, normalIndices);
   //Define an appearance for the shape
   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));
   //Create and return the shape
   return new Shape3D(indexedCube, app);
 }
 /**
  * Handles the exit button action to quit the program.
  */
 public void actionPerformed(ActionEvent e) {
   dispose();
   System.exit(0);
 }
 public SimpleIndexedQuadSmooth() {
   VirtualUniverse myUniverse = new VirtualUniverse();
   Locale myLocale = new Locale(myUniverse);
   myLocale.addBranchGraph(buildViewBranch(myCanvas3D));
   myLocale.addBranchGraph(buildContentBranch(buildShape()));
   setTitle("SimpleIndexedQuadSmooth");
   setSize(400, 400);
   setLayout(new BorderLayout());
   add("Center", myCanvas3D);
   add("South", myButton);
   myButton.addActionListener(this);
   setVisible(true);
 }
 public static void main(String[] args) {
   SimpleIndexedQuadSmooth siqs = new SimpleIndexedQuadSmooth();
 }

}

      </source>
   
  
 
  



cg viewer

   <source lang="java">

/*

* 
* This directory contains example code for using compressed geometry in Java 3D
* through the com.sun.j3d.utils.rupression package.
* 
* Applications:
* 
* obj2cg -- takes the names of .obj files to compress followed by the name of a
* .cg compressed geometry resource file. If the .cg file doesn"t exist, then an
* attempt is made to create it; otherwise, new compressed geometry objects are
* appended to the end.
* 
* The .obj files are compressed and stored into the .cg file in the order in
* which they appear in the command line, and can be accessed through indices [0 ..
* fileCount-1]
* 
* cgview -- takes the name of a .cg file and the index of the object to
* display, which can range from [0 .. objectCount-1]. The object may rotated,
* scaled, and translated in response to mouse drags.
* 
* 
* Utility classes:
* 
* ObjectFileCompressor.java -- Extends ObjectFile with compression methods.
*/

/*

* @(#)cgview.java 1.15 02/10/21 13:42:58
* 
* 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.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; import java.net.URL; import java.util.Hashtable; 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.rupressedGeometry; import javax.media.j3d.rupressedGeometryHeader; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Material; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import com.sun.j3d.loaders.IncorrectFormatException; import com.sun.j3d.loaders.ParsingErrorException; import com.sun.j3d.loaders.Scene; import com.sun.j3d.loaders.objectfile.ObjectFile; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.vp.OrbitBehavior; import com.sun.j3d.utils.rupression.rupressedGeometryFile; import com.sun.j3d.utils.rupression.rupressionStream; import com.sun.j3d.utils.rupression.GeometryCompressor; import com.sun.j3d.utils.universe.SimpleUniverse; import com.sun.j3d.utils.universe.ViewingPlatform; public class cgview extends Applet {

 private SimpleUniverse u = null;
 public BranchGroup createSceneGraph(CompressedGeometry cg) {
   // 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(0.7);
   objScale.setTransform(t3d);
   objRoot.addChild(objScale);
   // 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);
   objScale.addChild(objTrans);
   // Add compressed geometry to the scene graph.
   CompressedGeometryHeader hdr = new CompressedGeometryHeader();
   cg.getCompressedGeometryHeader(hdr);
   // There isn"t really enough information in the compressed geometry
   // header to unamiguously determine the proper rendering attributes.
   // The bufferDataPresent field specifies whether or not normals are
   // bundled with vertices, but the compressed buffer can still contain
   // normals that should be lit. Assume that any surface geometry
   // should be lit and that lines and points should not unless the
   // header contains the NORMAL_IN_BUFFER bit.
   Material m = new Material();
   if ((hdr.bufferType == hdr.TRIANGLE_BUFFER)
       || ((hdr.bufferDataPresent & hdr.NORMAL_IN_BUFFER) == 1))
     m.setLightingEnable(true);
   else
     m.setLightingEnable(false);
   Appearance a = new Appearance();
   a.setMaterial(m);
   objTrans.addChild(new Shape3D(cg, a));
   // Create mouse behavior scheduling bounds.
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   // 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, -0.9f);
   DirectionalLight light1 = new DirectionalLight(light1Color,
       light1Direction);
   light1.setInfluencingBounds(bounds);
   objRoot.addChild(light1);
   DirectionalLight light2 = new DirectionalLight(light2Color,
       light2Direction);
   light2.setInfluencingBounds(bounds);
   objRoot.addChild(light2);
   return objRoot;
 }
 private void usage() {
   System.out.println("Usage: cgview <.cg file> <object index>");
   System.exit(0);
 }
 public cgview(String args[]) {
   if (args.length < 1)
     usage();
   int index;
   if (args.length < 2)
     index = 0;
   else
     index = Integer.parseInt(args[1]);
   String filename = args[0];
   if (filename == null)
     usage();
   // Read the compressed geometry.
   CompressedGeometry cg = null;
   try {
     CompressedGeometryFile cgf;
     cgf = new CompressedGeometryFile(filename, false);
     if (cgf.getObjectCount() == 0) {
       System.out.println("no objects were found in " + filename);
       System.exit(0);
     }
     cg = cgf.read(index);
     cgf.close();
   } catch (IOException e) {
     System.out.println(e);
     System.exit(0);
   }
   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(cg);
   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.
   viewingPlatform.setNominalViewingTransform();
   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 cgview to be run as an application
 // as well as an applet.
 //
 public static void main(String[] args) {
   new MainFrame(new cgview(args), 700, 700);
 }

} class obj2cg {

 public static void main(String args[]) throws IOException {
   if (args.length < 2) {
     System.out
         .println("obj2cg wants the names of .obj files to compress,\n"
             + "followed by the name of a .cg file to create or to\n"
             + "which to append.");
     System.exit(0);
   }
   CompressedGeometryFile file;
   file = new CompressedGeometryFile(args[args.length - 1], true);
   ObjectFileCompressor compressor;
   compressor = new ObjectFileCompressor();
   for (int i = 0; i < args.length - 1; i++)
     compressor.rupress(args[i], file);
   file.close();
 }

} /**

* This extension of ObjectFile provides the methods setQuantization() and
* compress() to compress Wavefront .obj files into the format described by
* appendix B of the Java 3D specification.
*/

class ObjectFileCompressor extends ObjectFile {

 private GeometryCompressor compressor = null;
 public ObjectFileCompressor() {
   super(STRIPIFY | TRIANGULATE);
   compressor = new GeometryCompressor();
 }
 public ObjectFileCompressor(int flags) {
   super(flags | STRIPIFY | TRIANGULATE);
   compressor = new GeometryCompressor();
 }
 public ObjectFileCompressor(int flags, float radians) {
   super(flags | STRIPIFY | TRIANGULATE, radians);
   compressor = new GeometryCompressor();
 }
 public void setFlags(int flags) {
   super.setFlags(flags | STRIPIFY | TRIANGULATE);
 }
 private int positionQuant = 10;
 private int colorQuant = 8;
 private int normalQuant = 3;
 /**
  * Set the position, normal, and color quantization values for compression.
  * 
  * @param positionQuant
  *            number of bits to quantize each position"s X, Y, and Z
  *            components, ranging from 1 to 16 with a default of 10
  * @param colorQuant
  *            number of bits to quantize each color"s R, G, B, and alpha
  *            components, ranging from 2 to 16 with a default of 8
  * @param normalQuant
  *            number of bits for quantizing each normal"s U and V
  *            components, ranging from 0 to 6 with a default of 3
  */
 public void setQuantization(int positionQuant, int colorQuant,
     int normalQuant) {
   this.positionQuant = positionQuant;
   this.colorQuant = colorQuant;
   this.normalQuant = normalQuant;
 }
 /**
  * Compress the specified .obj file into a CompressedGeometry node
  * component.
  * 
  * @param objFileName
  *            String object representing the path to a .obj file
  * @return a CompressedGeometry node component
  */
 public CompressedGeometry compress(String objFileName) {
   return compressScene(getScene(objFileName));
 }
 /**
  * Compress the specified .obj file and add it to the end of an open
  * compressed geometry file.
  * 
  * @param objFileName
  *            String object representing the path to a .obj file
  * @param file
  *            a currently open CompressedGeometryFile object
  * @exception IOException -
  *                if write fails
  */
 public void compress(String objFileName, CompressedGeometryFile file)
     throws IOException {
   compressScene(getScene(objFileName), file);
 }
 /**
  * Compress the specified .obj file into a CompressedGeometry node
  * component.
  * 
  * @param reader
  *            an open .obj file
  * @return a CompressedGeometry node component
  */
 public CompressedGeometry compress(Reader reader) {
   return compressScene(getScene(reader));
 }
 /**
  * Compress the specified .obj file and add it to the end of an open
  * compressed geometry file.
  * 
  * @param reader
  *            an open .obj file
  * @param file
  *            an open CompressedGeometryFile object
  * @exception IOException -
  *                if write fails
  */
 public void compress(Reader reader, CompressedGeometryFile file)
     throws IOException {
   compressScene(getScene(reader), file);
 }
 /**
  * Compress the specified .obj file into a CompressedGeometry node
  * component.
  * 
  * @param url
  *            Uniform Resource Locator for the .obj file
  * @return a CompressedGeometry node component
  */
 public CompressedGeometry compress(URL url) {
   return compressScene(getScene(url));
 }
 /**
  * Compress the specified .obj file and add it to the end of an open
  * compressed geometry file.
  * 
  * @param url
  *            Uniform Resource Locator for the .obj file
  * @param file
  *            a currently open CompressedGeometryFile object
  * @exception IOException -
  *                if write fails
  */
 public void compress(URL url, CompressedGeometryFile file)
     throws IOException {
   compressScene(getScene(url), file);
 }
 private CompressedGeometry compressScene(Scene scene) {
   return compressor.rupress(getStream(scene));
 }
 private void compressScene(Scene scene, CompressedGeometryFile file)
     throws IOException {
   compressor.rupress(getStream(scene), file);
 }
 private CompressionStream getStream(Scene scene) {
   Hashtable objs = scene.getNamedObjects();
   Shape3D shapes[] = new Shape3D[objs.size()];
   objs.values().toArray(shapes);
   return new CompressionStream(positionQuant, colorQuant, normalQuant,
       shapes);
 }
 private Scene getScene(String objFileName) {
   Scene scene = null;
   try {
     scene = load(objFileName);
   } catch (FileNotFoundException e) {
     System.err.println(e);
     System.exit(1);
   } catch (ParsingErrorException e) {
     System.err.println(e);
     System.exit(1);
   } catch (IncorrectFormatException e) {
     System.err.println(e);
     System.exit(1);
   }
   return scene;
 }
 private Scene getScene(Reader reader) {
   Scene scene = null;
   try {
     scene = load(reader);
   } catch (FileNotFoundException e) {
     System.err.println(e);
     System.exit(1);
   } catch (ParsingErrorException e) {
     System.err.println(e);
     System.exit(1);
   } catch (IncorrectFormatException e) {
     System.err.println(e);
     System.exit(1);
   }
   return scene;
 }
 private Scene getScene(URL url) {
   Scene scene = null;
   try {
     scene = load(url);
   } catch (FileNotFoundException e) {
     System.err.println(e);
     System.exit(1);
   } catch (ParsingErrorException e) {
     System.err.println(e);
     System.exit(1);
   } catch (IncorrectFormatException e) {
     System.err.println(e);
     System.exit(1);
   }
   return scene;
 }

}


      </source>
   
  
 
  



Color Yoyo

   <source lang="java">

/*

* ColorYoyoApp.java 1.0 98/11/23
* 
* Copyright (c) 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.
*/

/*

* Getting Started with the Java 3D API written in Java 3D
* 
* This program demonstrates: 1. writing a visual object class In this program,
* Yoyo class defines a visual object by extneding Shape3D. 2. Using
* TriangleFanArray to create surfaces. Four TriangleFan array surfaces are
* contained in an instance of Yoyo. In addition, the color for the Yoyo is set
* in its geometry.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.Alpha; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Geometry; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TriangleFanArray; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.universe.SimpleUniverse; public class ColorYoyoApp extends Applet {

 /////////////////////////////////////////////////
 //
 // create scene graph branch group
 //
 public class Yoyo extends Shape3D {
   ////////////////////////////////////////////
   //
   // create Shape3D with geometry and appearance
   // the geometry is created in method yoyoGeometry
   // the appearance is created in method yoyoAppearance
   //
   public Yoyo() {
     this.setGeometry(yoyoGeometry());
   } // end of Yoyo constructor
   ////////////////////////////////////////////
   //
   // create yoyo geometry
   // four triangle fans represent the yoyo
   // strip indicies_______________
   //   0 0N+0 to 1N+0 ( 0 to N )
   //   1 1N+1 to 2N+1
   //   2 2N+2 to 3N+2
   //   3 3N+4 to 4N+3
   //
   private Geometry yoyoGeometry() {
     TriangleFanArray tfa;
     int N = 17;
     int totalN = 4 * (N + 1);
     Point3f coords[] = new Point3f[totalN];
     Color3f colors[] = new Color3f[totalN];
     Color3f red = new Color3f(1.0f, 0.0f, 0.0f);
     Color3f yellow = new Color3f(0.7f, 0.5f, 0.0f);
     int stripCounts[] = { N + 1, N + 1, N + 1, N + 1 };
     float r = 0.6f;
     float w = 0.4f;
     int n;
     double a;
     float x, y;
     // set the central points for four triangle fan strips
     coords[0 * (N + 1)] = new Point3f(0.0f, 0.0f, w);
     coords[1 * (N + 1)] = new Point3f(0.0f, 0.0f, 0.0f);
     coords[2 * (N + 1)] = new Point3f(0.0f, 0.0f, 0.0f);
     coords[3 * (N + 1)] = new Point3f(0.0f, 0.0f, -w);
     colors[0 * (N + 1)] = red;
     colors[1 * (N + 1)] = yellow;
     colors[2 * (N + 1)] = yellow;
     colors[3 * (N + 1)] = red;
     for (a = 0, n = 0; n < N; a = 2.0 * Math.PI / (N - 1) * ++n) {
       x = (float) (r * Math.cos(a));
       y = (float) (r * Math.sin(a));
       coords[0 * (N + 1) + n + 1] = new Point3f(x, y, w);
       coords[1 * (N + 1) + N - n] = new Point3f(x, y, w);
       coords[2 * (N + 1) + n + 1] = new Point3f(x, y, -w);
       coords[3 * (N + 1) + N - n] = new Point3f(x, y, -w);
       colors[0 * (N + 1) + N - n] = red;
       colors[1 * (N + 1) + n + 1] = yellow;
       colors[2 * (N + 1) + N - n] = yellow;
       colors[3 * (N + 1) + n + 1] = red;
     }
     tfa = new TriangleFanArray(totalN, TriangleFanArray.COORDINATES
         | TriangleFanArray.COLOR_3, stripCounts);
     tfa.setCoordinates(0, coords);
     tfa.setColors(0, colors);
     return tfa;
   } // end of method yoyoGeometry in class Yoyo
 } // end of class Yoyo
 /////////////////////////////////////////////////
 //
 // create scene graph branch group
 //
 public BranchGroup createSceneGraph() {
   BranchGroup objRoot = new BranchGroup();
   // 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 objSpin = new TransformGroup();
   objSpin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objRoot.addChild(objSpin);
   objSpin.addChild(new Yoyo());
   // Create a new Behavior object that will perform the desired
   // operation on the specified transform object and add it into
   // the scene graph.
   Transform3D yAxis = new Transform3D();
   Alpha rotationAlpha = new Alpha(-1, 4000);
   RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
       objSpin);
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   rotator.setSchedulingBounds(bounds);
   objSpin.addChild(rotator);
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 } // end of CreateSceneGraph method of ColorYoyoApp
 // Create a simple scene and attach it to the virtual universe
 public ColorYoyoApp() {
   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 ColorYoyoApp constructor
 //  The following allows this to be run as an application
 //  as well as an applet
 public static void main(String[] args) {
   Frame frame = new MainFrame(new ColorYoyoApp(), 256, 256);
 } // end of main method of ColorYoyoApp

} // end of class ColorYoyoApp


      </source>
   
  
 
  



Door App

   <source lang="java">

/*

* @(#)DoorApp.java 1.0 99/06/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 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.WakeupCriterion; import javax.media.j3d.WakeupOnAWTEvent; import javax.media.j3d.WakeupOnBehaviorPost; import javax.media.j3d.WakeupOnElapsedFrames; import javax.vecmath.Matrix3d; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.SimpleUniverse; public class DoorApp extends Applet {

 public class OpenBehavior extends Behavior {
   private TransformGroup targetTG;
   private WakeupCriterion pairPostCondition;
   private WakeupCriterion wakeupNextFrame;
   private WakeupCriterion AWTEventCondition;
   private Transform3D t3D = new Transform3D();
   private Matrix3d rotMat = new Matrix3d();
   private double doorAngle;
   OpenBehavior(TransformGroup targetTG) {
     this.targetTG = targetTG;
     AWTEventCondition = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);
     wakeupNextFrame = new WakeupOnElapsedFrames(0);
   }
   public void setBehaviorObjectPartner(Behavior behaviorObject) {
     pairPostCondition = new WakeupOnBehaviorPost(behaviorObject, 1);
   }
   public void initialize() {
     this.wakeupOn(AWTEventCondition);
     doorAngle = 0.0;
   }
   public void processStimulus(Enumeration criteria) {
     if (criteria.nextElement().equals(pairPostCondition)) {
       System.out.println("ready to open door");
       this.wakeupOn(AWTEventCondition);
       doorAngle = 0.0f;
     } else { // could be KeyPress or nextFrame, in either case: open
       if (doorAngle < 1.6) {
         doorAngle += 0.1;
         if (doorAngle > 1.6)
           doorAngle = 1.6;
         // get rotation and scale portion of transform
         targetTG.getTransform(t3D);
         t3D.getRotationScale(rotMat);
         // set y-axis rotation to doorAngle
         // (clobber any previous y-rotation, x and z scale)
         rotMat.m00 = Math.cos(doorAngle);
         rotMat.m22 = rotMat.m00;
         rotMat.m02 = Math.sin(doorAngle);
         rotMat.m20 = -rotMat.m02;
         t3D.setRotation(rotMat);
         targetTG.setTransform(t3D);
         this.wakeupOn(wakeupNextFrame);
       } else { // finished opening door, signal other behavior
         System.out.println("door is open");
         this.wakeupOn(pairPostCondition);
         postId(1);
       }
     }
   }
 } // end of class OpenBehavior
 public class CloseBehavior extends Behavior {
   private TransformGroup targetTG;
   private WakeupCriterion pairPostCondition;
   private WakeupCriterion wakeupNextFrame;
   private WakeupCriterion AWTEventCondition;
   private Transform3D t3D = new Transform3D();
   private Matrix3d rotMat = new Matrix3d();
   private double doorAngle;
   CloseBehavior(TransformGroup targetTG) {
     this.targetTG = targetTG;
     AWTEventCondition = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);
     wakeupNextFrame = new WakeupOnElapsedFrames(0);
   }
   public void setBehaviorObjectPartner(Behavior behaviorObject) {
     pairPostCondition = new WakeupOnBehaviorPost(behaviorObject, 1);
   }
   public void initialize() {
     this.wakeupOn(pairPostCondition);
     doorAngle = 1.6;
   }
   public void processStimulus(Enumeration criteria) {
     if (criteria.nextElement().equals(pairPostCondition)) {
       System.out.println("ready to close door");
       this.wakeupOn(AWTEventCondition);
       doorAngle = 1.6f;
     } else { // could be KeyPress or nextFrame, in either case: close
       if (doorAngle > 0.0) {
         doorAngle -= 0.1;
         if (doorAngle < 0.0)
           doorAngle = 0.0;
         // get rotation and scale portion of transform
         targetTG.getTransform(t3D);
         t3D.getRotationScale(rotMat);
         // set y-axis rotation to doorAngle
         // (clobber any previous y-rotation, x and z scale)
         rotMat.m00 = Math.cos(doorAngle);
         rotMat.m22 = rotMat.m00;
         rotMat.m02 = Math.sin(doorAngle);
         rotMat.m20 = -rotMat.m02;
         t3D.setRotation(rotMat);
         targetTG.setTransform(t3D);
         this.wakeupOn(wakeupNextFrame);
       } else { // finished opening door, signal other behavior
         System.out.println("door is closed");
         this.wakeupOn(pairPostCondition);
         postId(1);
       }
     }
   }
 } // end of class CloseBehavior
 public BranchGroup createSceneGraph() {
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   TransformGroup doorTG = new TransformGroup();
   doorTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   doorTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   OpenBehavior openObject = new OpenBehavior(doorTG);
   CloseBehavior closeObject = new CloseBehavior(doorTG);
   //prepare the behavior objects
   openObject.setBehaviorObjectPartner(closeObject);
   closeObject.setBehaviorObjectPartner(openObject);
   // set scheduling bounds for behavior objects
   BoundingSphere bounds = new BoundingSphere();
   openObject.setSchedulingBounds(bounds);
   closeObject.setSchedulingBounds(bounds);
   // assemble scene graph
   objRoot.addChild(openObject);
   objRoot.addChild(closeObject);
   objRoot.addChild(doorTG);
   doorTG.addChild(new ColorCube(0.4));
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 } // end of CreateSceneGraph method of DoorApp
 public DoorApp() {
   setLayout(new BorderLayout());
   Canvas3D canvas3D = new Canvas3D(null);
   add("Center", canvas3D);
   // SimpleUniverse is a Convenience Utility class
   SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
   simpleU.getViewingPlatform().setNominalViewingTransform();
   BranchGroup scene = createSceneGraph();
   simpleU.addBranchGraph(scene);
 } // end of DoorApp (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("DoorApp.java \n- a demonstration of coordinating behavior ");
   System.out.println("objects for complex behaviors in a Java 3D scene.");
   System.out
       .println("When the app loads, press a key to make the "door" open and close.");
   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 DoorApp(), 256, 256);
 } // end of main (method of DoorApp)

} // end of class DoorApp


      </source>
   
  
 
  



Example Switch

   <source lang="java">

/*

* 
* Copyright (c) 1998 David R. Nadeau
*  
*/

import java.applet.Applet; import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.CheckboxMenuItem; import java.awt.ruponent; import java.awt.Cursor; import java.awt.Frame; import java.awt.Menu; import java.awt.MenuBar; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.io.File; import java.util.BitSet; import java.util.Enumeration; import java.util.EventListener; 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.DirectionalLight; import javax.media.j3d.GeometryArray; import javax.media.j3d.Group; import javax.media.j3d.IndexedQuadArray; import javax.media.j3d.IndexedTriangleStripArray; import javax.media.j3d.Light; import javax.media.j3d.Link; import javax.media.j3d.Material; import javax.media.j3d.Shape3D; import javax.media.j3d.SharedGroup; import javax.media.j3d.Switch; import javax.media.j3d.Texture; 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.media.j3d.WakeupOnElapsedFrames; import javax.media.j3d.WakeupOr; 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.geometry.Primitive; import com.sun.j3d.utils.geometry.Sphere; import com.sun.j3d.utils.image.TextureLoader; import com.sun.j3d.utils.universe.PlatformGeometry; import com.sun.j3d.utils.universe.SimpleUniverse; import com.sun.j3d.utils.universe.Viewer; import com.sun.j3d.utils.universe.ViewingPlatform; public class ExSwitch extends Java3DFrame {

 //--------------------------------------------------------------
 //  SCENE CONTENT
 //--------------------------------------------------------------
 //
 //  Nodes (updated via menu)
 //
 private Switch swtch = null;
 private int currentSwitch = 0;
 //
 //  Build scene
 //
 public Group buildScene() {
   // Turn on the example headlight
   setHeadlightEnable(true);
   // Default to walk navigation
   setNavigationType(Walk);
   // Build the scene group
   Group scene = new Group();
   if (debug)
     System.err.println("  switch shapes...");
   // BEGIN EXAMPLE TOPIC
   // Build the switch group and allow its switch
   // value to be changed via menu items
   swtch = new Switch();
   swtch.setCapability(Switch.ALLOW_SWITCH_WRITE);
   //  Create several shapes to place in a switch group
   // Child 0: a red sphere
   Appearance app0 = new Appearance();
   Material mat0 = new Material();
   mat0.setAmbientColor(0.2f, 0.2f, 0.2f);
   mat0.setDiffuseColor(1.0f, 0.0f, 0.2f);
   mat0.setSpecularColor(0.7f, 0.7f, 0.7f);
   app0.setMaterial(mat0);
   Transform3D t3d = new Transform3D();
   t3d.setTranslation(new Vector3f(-2.0f, 1.5f, 0.0f));
   TransformGroup tg0 = new TransformGroup(t3d);
   Sphere sph0 = new Sphere(0.5f, // radius
       Primitive.GENERATE_NORMALS, // components
       16, // facets
       app0); // appearance
   tg0.addChild(sph0);
   swtch.addChild(tg0); // Child 0
   // Child 1: a green sphere
   Appearance app1 = new Appearance();
   Material mat1 = new Material();
   mat1.setAmbientColor(0.2f, 0.2f, 0.2f);
   mat1.setDiffuseColor(0.0f, 1.0f, 0.0f);
   mat1.setSpecularColor(0.7f, 0.7f, 0.7f);
   app1.setMaterial(mat1);
   t3d.setTranslation(new Vector3f(0.0f, 1.5f, 0.0f));
   TransformGroup tg1 = new TransformGroup(t3d);
   Sphere sph1 = new Sphere(0.5f, // radius
       Primitive.GENERATE_NORMALS, // components
       16, // facets
       app1); // appearance
   tg1.addChild(sph1);
   swtch.addChild(tg1); // Child 1
   // Child 2: a blue sphere
   Appearance app2 = new Appearance();
   Material mat2 = new Material();
   mat2.setAmbientColor(0.2f, 0.2f, 0.2f);
   mat2.setDiffuseColor(0.0f, 0.6f, 1.0f);
   mat2.setSpecularColor(0.7f, 0.7f, 0.7f);
   app2.setMaterial(mat2);
   t3d.setTranslation(new Vector3f(2.0f, 1.5f, 0.0f));
   TransformGroup tg2 = new TransformGroup(t3d);
   Sphere sph2 = new Sphere(0.5f, // radius
       Primitive.GENERATE_NORMALS, // components
       16, // facets
       app2); // appearance
   tg2.addChild(sph2);
   swtch.addChild(tg2);
   // Set the initial child choice
   swtch.setWhichChild(options[currentSwitch].child);
   scene.addChild(swtch);
   // END EXAMPLE TOPIC
   // Build foreground geometry including a floor and
   // columns on which the switchable shapes stand
   // Load textures
   TextureLoader texLoader = new TextureLoader("granite07rev.jpg", this);
   Texture columnTex = texLoader.getTexture();
   if (columnTex == null)
     System.err.println("Cannot load granite07rev.jpg texture");
   else {
     columnTex.setBoundaryModeS(Texture.WRAP);
     columnTex.setBoundaryModeT(Texture.WRAP);
     columnTex.setMinFilter(Texture.NICEST);
     columnTex.setMagFilter(Texture.NICEST);
     columnTex.setMipMapMode(Texture.BASE_LEVEL);
     columnTex.setEnable(true);
   }
   texLoader = new TextureLoader("flooring.jpg", this);
   Texture groundTex = texLoader.getTexture();
   if (groundTex == null)
     System.err.println("Cannot load flooring.jpg texture");
   else {
     groundTex.setBoundaryModeS(Texture.WRAP);
     groundTex.setBoundaryModeT(Texture.WRAP);
     groundTex.setMinFilter(Texture.NICEST);
     groundTex.setMagFilter(Texture.NICEST);
     groundTex.setMipMapMode(Texture.BASE_LEVEL);
     groundTex.setEnable(true);
   }
   //
   // Build several columns on the floor
   //
   if (debug)
     System.err.println("  columns...");
   SharedGroup column = new SharedGroup();
   Appearance columnApp = new Appearance();
   Material columnMat = new Material();
   columnMat.setAmbientColor(0.6f, 0.6f, 0.6f);
   columnMat.setDiffuseColor(1.0f, 1.0f, 1.0f);
   columnMat.setSpecularColor(0.0f, 0.0f, 0.0f);
   columnApp.setMaterial(columnMat);
   TextureAttributes columnTexAtt = new TextureAttributes();
   columnTexAtt.setTextureMode(TextureAttributes.MODULATE);
   columnTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
   columnApp.setTextureAttributes(columnTexAtt);
   if (columnTex != null)
     columnApp.setTexture(columnTex);
   GothicColumn columnShape = new GothicColumn(1.8f, // height
       0.25f, // radius
       GothicColumn.BUILD_TOP, // flags
       columnApp); // appearance
   column.addChild(columnShape);
   Vector3f trans = new Vector3f();
   Transform3D tr = new Transform3D();
   TransformGroup tg;
   // Left
   trans.set(-2.0f, -1.0f, 0.0f);
   tr.set(trans);
   tg = new TransformGroup(tr);
   tg.addChild(new Link(column));
   scene.addChild(tg);
   // Middle
   trans.set(0.0f, -1.0f, 0.0f);
   tr.set(trans);
   tg = new TransformGroup(tr);
   tg.addChild(new Link(column));
   scene.addChild(tg);
   // Right
   trans.set(2.0f, -1.0f, 0.0f);
   tr.set(trans);
   tg = new TransformGroup(tr);
   tg.addChild(new Link(column));
   scene.addChild(tg);
   //
   //  Add the ground
   //
   if (debug)
     System.err.println("  ground...");
   Appearance groundApp = new Appearance();
   Material groundMat = new Material();
   groundMat.setAmbientColor(0.6f, 0.6f, 0.6f);
   groundMat.setDiffuseColor(1.0f, 1.0f, 1.0f);
   groundMat.setSpecularColor(0.0f, 0.0f, 0.0f);
   groundApp.setMaterial(groundMat);
   tr = new Transform3D();
   tr.setScale(new Vector3d(4.0, 4.0, 1.0));
   TextureAttributes groundTexAtt = new TextureAttributes();
   groundTexAtt.setTextureMode(TextureAttributes.MODULATE);
   groundTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
   groundTexAtt.setTextureTransform(tr);
   groundApp.setTextureAttributes(groundTexAtt);
   if (groundTex != null)
     groundApp.setTexture(groundTex);
   ElevationGrid ground = new ElevationGrid(11, // X dimension
       11, // Z dimension
       2.0f, // X spacing
       2.0f, // Z spacing
       // Automatically use zero heights
       groundApp); // Appearance
   trans.set(0.0f, -1.0f, 0.0f);
   tr.set(trans);
   tg = new TransformGroup(tr);
   tg.addChild(ground);
   scene.addChild(tg);
   // Add a light
   BoundingSphere worldBounds = new BoundingSphere(new Point3d(0.0, 0.0,
       0.0), // Center
       1000.0); // Extent
   DirectionalLight light = new DirectionalLight();
   light.setEnable(true);
   light.setColor(new Color3f(1.0f, 1.0f, 1.0f));
   light.setDirection(new Vector3f(0.5f, -1.0f, -0.5f));
   light.setInfluencingBounds(worldBounds);
   scene.addChild(light);
   return scene;
 }
 //--------------------------------------------------------------
 //  USER INTERFACE
 //--------------------------------------------------------------
 //
 //  Main
 //
 public static void main(String[] args) {
   ExSwitch ex = new ExSwitch();
   ex.initialize(args);
   ex.buildUniverse();
   ex.showFrame();
 }
 //
 //  Private class for holding switch options
 //
 private class NameChildMask {
   public String name;
   public int child;
   public BitSet mask;
   public NameChildMask(String n, int c, int m) {
     name = n;
     child = c;
     mask = new BitSet(3);
     if ((m & 1) != 0)
       mask.set(0);
     if ((m & 2) != 0)
       mask.set(1);
     if ((m & 4) != 0)
       mask.set(2);
   }
 }
 //  Switch menu choices
 private NameChildMask[] options = {
     new NameChildMask("CHILD_ALL", Switch.CHILD_ALL, 0),
     new NameChildMask("CHILD_NONE", Switch.CHILD_NONE, 0),
     new NameChildMask("Child 0", 0, 0),
     new NameChildMask("Child 1", 1, 0),
     new NameChildMask("Child 2", 2, 0),
     new NameChildMask("Children 0 & 1", Switch.CHILD_MASK, 3),
     new NameChildMask("Children 0 & 2", Switch.CHILD_MASK, 5),
     new NameChildMask("Children 1 & 2", Switch.CHILD_MASK, 6), };
 private CheckboxMenuItem[] switchMenu;
 //
 //  Initialize the GUI (application and applet)
 //
 public void initialize(String[] args) {
   // Initialize the window, menubar, etc.
   super.initialize(args);
   exampleFrame.setTitle("Java 3D Switch Example");
   // Add a menu to select among switch options
   Menu mt = new Menu("Switch");
   switchMenu = new CheckboxMenuItem[options.length];
   for (int i = 0; i < options.length; i++) {
     switchMenu[i] = new CheckboxMenuItem(options[i].name);
     switchMenu[i].addItemListener(this);
     switchMenu[i].setState(false);
     mt.add(switchMenu[i]);
   }
   exampleMenuBar.add(mt);
   currentSwitch = 0;
   switchMenu[currentSwitch].setState(true);
 }
 //
 //  Handle checkboxes
 //
 public void itemStateChanged(ItemEvent event) {
   Object src = event.getSource();
   // Check if it is switch choice
   for (int i = 0; i < switchMenu.length; i++) {
     if (src == switchMenu[i]) {
       // Update the checkboxes
       switchMenu[currentSwitch].setState(false);
       currentSwitch = i;
       switchMenu[currentSwitch].setState(true);
       // Set the switch
       swtch.setWhichChild(options[currentSwitch].child);
       swtch.setChildMask(options[currentSwitch].mask);
       return;
     }
   }
   // Handle all other checkboxes
   super.itemStateChanged(event);
 }

} // //CLASS //ElevationGrid - a 3D terrain grid built from a list of heights // //DESCRIPTION //This class creates a 3D terrain on a grid whose X and Z dimensions, //and row/column spacing are parameters, along with a list of heights //(elevations), one per grid row/column pair. // class ElevationGrid extends Primitive {

 // Parameters
 protected int xDimension = 0, zDimension = 0;
 protected double xSpacing = 0.0, zSpacing = 0.0;
 protected double[] heights = null;
 // 3D nodes
 private Appearance mainAppearance = null;
 private Shape3D shape = null;
 private IndexedTriangleStripArray tristrip = null;
 //
 //  Construct an elevation grid
 //
 public ElevationGrid() {
   xDimension = 2;
   zDimension = 2;
   xSpacing = 1.0;
   zSpacing = 1.0;
   mainAppearance = null;
   zeroHeights();
   rebuild();
 }
 public ElevationGrid(int xDim, int zDim) {
   xDimension = xDim;
   zDimension = zDim;
   xSpacing = 1.0;
   zSpacing = 1.0;
   mainAppearance = null;
   zeroHeights();
   rebuild();
 }
 public ElevationGrid(int xDim, int zDim, Appearance app) {
   xDimension = xDim;
   zDimension = zDim;
   xSpacing = 1.0;
   zSpacing = 1.0;
   mainAppearance = app;
   zeroHeights();
   rebuild();
 }
 public ElevationGrid(int xDim, int zDim, double xSpace, double zSpace) {
   xDimension = xDim;
   zDimension = zDim;
   xSpacing = xSpace;
   zSpacing = zSpace;
   mainAppearance = null;
   zeroHeights();
   rebuild();
 }
 public ElevationGrid(int xDim, int zDim, double xSpace, double zSpace,
     Appearance app) {
   xDimension = xDim;
   zDimension = zDim;
   xSpacing = xSpace;
   zSpacing = zSpace;
   mainAppearance = app;
   zeroHeights();
   rebuild();
 }
 public ElevationGrid(int xDim, int zDim, double[] h) {
   this(xDim, zDim, 1.0, 1.0, h, null);
 }
 public ElevationGrid(int xDim, int zDim, double[] h, Appearance app) {
   this(xDim, zDim, 1.0, 1.0, h, app);
 }
 public ElevationGrid(int xDim, int zDim, double xSpace, double zSpace,
     double[] h) {
   this(xDim, zDim, xSpace, zSpace, h, null);
 }
 public ElevationGrid(int xDim, int zDim, double xSpace, double zSpace,
     double[] h, Appearance app) {
   xDimension = xDim;
   zDimension = zDim;
   xSpacing = xSpace;
   zSpacing = zSpace;
   mainAppearance = app;
   if (h == null)
     zeroHeights();
   else {
     heights = new double[h.length];
     for (int i = 0; i < h.length; i++)
       heights[i] = h[i];
   }
   rebuild();
 }
 private void zeroHeights() {
   int n = xDimension * zDimension;
   heights = new double[n];
   for (int i = 0; i < n; i++)
     heights[i] = 0.0;
 }
 private void rebuild() {
   // Build a shape
   if (shape == null) {
     shape = new Shape3D();
     shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
     shape.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
     shape.setAppearance(mainAppearance);
     addChild(shape);
   } else {
     shape.setAppearance(mainAppearance);
   }
   if (xDimension < 2 || zDimension < 2 || heights == null
       || heights.length < 4) {
     tristrip = null;
     shape.setGeometry(null);
     return;
   }
   // Create a list of coordinates, one per grid row/column
   double[] coordinates = new double[xDimension * zDimension * 3];
   double x, z;
   int n = 0, k = 0;
   z = ((double) (zDimension - 1)) * zSpacing / 2.0; // start at front edge
   for (int i = 0; i < zDimension; i++) {
     x = -((double) (xDimension - 1)) * xSpacing / 2.0;// start at left
                               // edge
     for (int j = 0; j < xDimension; j++) {
       coordinates[n++] = x;
       coordinates[n++] = heights[k++];
       coordinates[n++] = z;
       x += xSpacing;
     }
     z -= zSpacing;
   }
   // Create a list of normals, one per grid row/column
   float[] normals = new float[xDimension * zDimension * 3];
   Vector3f one = new Vector3f(0.0f, 0.0f, 0.0f);
   Vector3f two = new Vector3f(0.0f, 0.0f, 0.0f);
   Vector3f norm = new Vector3f(0.0f, 0.0f, 0.0f);
   n = 0;
   k = 0;
   for (int i = 0; i < zDimension - 1; i++) {
     for (int j = 0; j < xDimension - 1; j++) {
       // Vector to right in X
       one.set((float) xSpacing,
           (float) (heights[k + 1] - heights[k]), 0.0f);
       // Vector back in Z
       two.set(0.0f, (float) (heights[k + xDimension] - heights[k]),
           (float) -zSpacing);
       // Cross them to get the normal
       norm.cross(one, two);
       normals[n++] = norm.x;
       normals[n++] = norm.y;
       normals[n++] = norm.z;
       k++;
     }
     // Last normal in row is a copy of the previous one
     normals[n] = normals[n - 3]; // X
     normals[n + 1] = normals[n - 2]; // Y
     normals[n + 2] = normals[n - 1]; // Z
     n += 3;
     k++;
   }
   // Last row of normals is a copy of the previous row
   for (int j = 0; j < xDimension; j++) {
     normals[n] = normals[n - xDimension * 3]; // X
     normals[n + 1] = normals[n - xDimension * 3 + 1]; // Y
     normals[n + 2] = normals[n - xDimension * 3 + 2]; // Z
     n += 3;
   }
   // Create a list of texture coordinates, one per grid row/column
   float[] texcoordinates = new float[xDimension * zDimension * 2];
   float deltaS = 1.0f / (float) (xDimension - 1);
   float deltaT = 1.0f / (float) (zDimension - 1);
   float s = 0.0f;
   float t = 0.0f;
   n = 0;
   for (int i = 0; i < zDimension; i++) {
     s = 0.0f;
     for (int j = 0; j < xDimension; j++) {
       texcoordinates[n++] = s;
       texcoordinates[n++] = t;
       s += deltaS;
     }
     t += deltaT;
   }
   // Create a list of triangle strip indexes. Each strip goes
   // down one row (X direction) of the elevation grid.
   int[] indexes = new int[xDimension * (zDimension - 1) * 2];
   int[] stripCounts = new int[zDimension - 1];
   n = 0;
   k = 0;
   for (int i = 0; i < zDimension - 1; i++) {
     stripCounts[i] = xDimension * 2;
     for (int j = 0; j < xDimension; j++) {
       indexes[n++] = k + xDimension;
       indexes[n++] = k;
       k++;
     }
   }
   // Create geometry for collection of triangle strips, one
   // strip per row of the elevation grid
   tristrip = new IndexedTriangleStripArray(coordinates.length,
       GeometryArray.COORDINATES | GeometryArray.NORMALS
           | GeometryArray.TEXTURE_COORDINATE_2, indexes.length,
       stripCounts);
   tristrip.setCoordinates(0, coordinates);
   tristrip.setNormals(0, normals);
   tristrip.setTextureCoordinates(0, texcoordinates);
   tristrip.setCoordinateIndices(0, indexes);
   tristrip.setNormalIndices(0, indexes);
   tristrip.setTextureCoordinateIndices(0, indexes);
   // Set the geometry for the shape
   shape.setGeometry(tristrip);
 }
 //
 //  Control the appearance
 //
 public void setAppearance(Appearance app) {
   mainAppearance = app;
   if (shape != null)
     shape.setAppearance(mainAppearance);
 }
 //
 //  Control grid parameters
 //
 public void setHeights(double[] h) {
   if (h == null)
     zeroHeights();
   else {
     heights = new double[h.length];
     for (int i = 0; i < h.length; i++)
       heights[i] = h[i];
   }
   rebuild();
 }
 public double[] getHeights() {
   return heights;
 }
 public void setXDimension(int xDim) {
   xDimension = xDim;
   rebuild();
 }
 public int getXDimension() {
   return xDimension;
 }
 public void setZDimension(int zDim) {
   zDimension = zDim;
   rebuild();
 }
 public int getZDimension() {
   return zDimension;
 }
 public void setXSpacing(double xSpace) {
   xSpacing = xSpace;
   rebuild();
 }
 public double getXSpacing() {
   return xSpacing;
 }
 public void setZSpacing(double zSpace) {
   zSpacing = zSpace;
   rebuild();
 }
 public double getZSpacing() {
   return zSpacing;
 }
 //
 //  Provide info on the shape and geometry
 //
 public Shape3D getShape(int partid) {
   return shape;
 }
 public int getNumTriangles() {
   return xDimension * zDimension * 2;
 }
 public int getNumVertices() {
   return xDimension * zDimension;
 }
 /* (non-Javadoc)
  * @see com.sun.j3d.utils.geometry.Primitive#getAppearance(int)
  */
 public Appearance getAppearance(int arg0) {
   // TODO Auto-generated method stub
   return null;
 }

} // //CLASS //GothicColumn - Gothic-style column used in example scenes // //DESCRIPTION //This class builds a Gothic-column architectural column. // //SEE ALSO //? // //AUTHOR //David R. Nadeau / San Diego Supercomputer Center // // class GothicColumn extends Primitive {

 //
 //  Construction Flags
 //
 public final static int BUILD_TAPERED_CROWN = 0x1;
 public final static int BUILD_TOP = 0x2;
 public final static int BUILD_BOTTOM = 0x4;
 //
 //  3D nodes
 //
 private Appearance mainAppearance = null;
 //
 //  Construct a column
 //
 public GothicColumn(float height, float radius, Appearance app) {
   this(height, radius, 0, app);
 }
 public GothicColumn(float height, float radius, int flags, Appearance app) {
   mainAppearance = app;
   // Compute sizes and positions based upon the
   // desired main column radius
   // Base box
   float baseWidth = 2.7f * radius;
   float baseDepth = baseWidth;
   float baseHeight = 0.75f * radius / 2.0f;
   // Base box #2
   float base2Width = 0.8f * baseWidth;
   float base2Depth = base2Width;
   float base2Height = baseHeight / 2.0f;
   // Tapered crown
   float crownWidth1 = 2.0f * 0.707f * radius;
   float crownDepth1 = crownWidth1;
   float crownWidth2 = 1.0f * base2Width;
   float crownDepth2 = 1.0f * base2Depth;
   float crownHeight = 2.0f * baseHeight;
   // Box above tapered crown
   float crown2Width = 1.1f * base2Width;
   float crown2Depth = 1.1f * base2Depth;
   float crown2Height = base2Height;
   // Final crown box
   float crown3Width = 1.1f * baseWidth;
   float crown3Depth = 1.1f * baseDepth;
   float crown3Height = baseHeight;
   // Cylindrical column
   //   Extend it up and into the tapered crown
   float columnHeight = height - baseHeight - base2Height - crown2Height
       - crown3Height;
   float columnRadius = radius;
   float baseY = baseHeight / 2.0f;
   float base2Y = baseHeight + base2Height / 2.0f;
   float columnY = baseHeight + base2Height + columnHeight / 2.0f;
   float crown2Y = baseHeight + base2Height + columnHeight + crown2Height
       / 2.0f;
   float crown3Y = baseHeight + base2Height + columnHeight + crown2Height
       + crown3Height / 2.0f;
   float crownY = crown2Y - crown2Height / 2.0f - crownHeight / 2.0f;
   // Column base box
   int fl = BUILD_TOP;
   if ((flags & BUILD_BOTTOM) != 0)
     fl |= BUILD_BOTTOM;
   addBox(baseWidth, baseHeight, baseDepth, baseY, fl);
   // Column base box #2 (no bottom)
   addBox(base2Width, base2Height, base2Depth, base2Y, BUILD_TOP);
   // Main column (no top or bottom)
   addCylinder(columnRadius, columnHeight, columnY);
   // Column crown tapered box (no top or bottom)
   if ((flags & BUILD_TAPERED_CROWN) != 0) {
     addBox(crownWidth1, crownHeight, crownDepth1, crownY, crownWidth2,
         crownDepth2, 0);
   }
   // Box above tapered crown (no top)
   addBox(crown2Width, crown2Height, crown2Depth, crown2Y, BUILD_BOTTOM);
   // Final crown box
   fl = BUILD_BOTTOM;
   if ((flags & BUILD_TOP) != 0)
     fl |= BUILD_TOP;
   addBox(crown3Width, crown3Height, crown3Depth, crown3Y, fl);
 }
 //
 //  Add an untapered box
 //
 private void addBox(float width, float height, float depth, float y) {
   addBox(width, height, depth, y, width, depth, 0);
 }
 private void addBox(float width, float height, float depth, float y,
     int flags) {
   addBox(width, height, depth, y, width, depth, flags);
 }
 private void addBox(float width, float height, float depth, float y,
     float width2, float depth2) {
   addBox(width, height, depth, y, width2, depth2, 0);
 }
 //
 //  Add a tapered box
 //
 private void addBox(float width, float height, float depth, float y,
     float width2, float depth2, int flags) {
   float[] coordinates = {
   // around the bottom
       -width / 2.0f, -height / 2.0f, depth / 2.0f, width / 2.0f,
       -height / 2.0f, depth / 2.0f, width / 2.0f, -height / 2.0f,
       -depth / 2.0f, -width / 2.0f, -height / 2.0f, -depth / 2.0f,
       // around the top
       -width2 / 2.0f, height / 2.0f, depth2 / 2.0f, width2 / 2.0f,
       height / 2.0f, depth2 / 2.0f, width2 / 2.0f, height / 2.0f,
       -depth2 / 2.0f, -width2 / 2.0f, height / 2.0f, -depth2 / 2.0f, };
   int[] fullCoordinateIndexes = { 0, 1, 5, 4, // front
       1, 2, 6, 5, // right
       2, 3, 7, 6, // back
       3, 0, 4, 7, // left
       4, 5, 6, 7, // top
       3, 2, 1, 0, // bottom
   };
   float v = -(width2 - width) / height;
   float[] normals = { 0.0f, v, 1.0f, // front
       1.0f, v, 0.0f, // right
       0.0f, v, -1.0f, // back
       -1.0f, v, 0.0f, // left
       0.0f, 1.0f, 0.0f, // top
       0.0f, -1.0f, 0.0f, // bottom
   };
   int[] fullNormalIndexes = { 0, 0, 0, 0, // front
       1, 1, 1, 1, // right
       2, 2, 2, 2, // back
       3, 3, 3, 3, // left
       4, 4, 4, 4, // top
       5, 5, 5, 5, // bottom
   };
   float[] textureCoordinates = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
       0.0f, 1.0f, };
   int[] fullTextureCoordinateIndexes = { 0, 1, 2, 3, // front
       0, 1, 2, 3, // right
       0, 1, 2, 3, // back
       0, 1, 2, 3, // left
       0, 1, 2, 3, // top
       0, 1, 2, 3, // bottom
   };
   // Select indexes needed
   int[] coordinateIndexes;
   int[] normalIndexes;
   int[] textureCoordinateIndexes;
   if (flags == 0) {
     // build neither top or bottom
     coordinateIndexes = new int[4 * 4];
     textureCoordinateIndexes = new int[4 * 4];
     normalIndexes = new int[4 * 4];
     for (int i = 0; i < 4 * 4; i++) {
       coordinateIndexes[i] = fullCoordinateIndexes[i];
       textureCoordinateIndexes[i] = fullTextureCoordinateIndexes[i];
       normalIndexes[i] = fullNormalIndexes[i];
     }
   } else if ((flags & (BUILD_TOP | BUILD_BOTTOM)) == (BUILD_TOP | BUILD_BOTTOM)) {
     // build top and bottom
     coordinateIndexes = fullCoordinateIndexes;
     textureCoordinateIndexes = fullTextureCoordinateIndexes;
     normalIndexes = fullNormalIndexes;
   } else if ((flags & BUILD_TOP) != 0) {
     // build top but not bottom
     coordinateIndexes = new int[5 * 4];
     textureCoordinateIndexes = new int[5 * 4];
     normalIndexes = new int[5 * 4];
     for (int i = 0; i < 5 * 4; i++) {
       coordinateIndexes[i] = fullCoordinateIndexes[i];
       textureCoordinateIndexes[i] = fullTextureCoordinateIndexes[i];
       normalIndexes[i] = fullNormalIndexes[i];
     }
   } else {
     // build bottom but not top
     coordinateIndexes = new int[5 * 4];
     textureCoordinateIndexes = new int[5 * 4];
     normalIndexes = new int[5 * 4];
     for (int i = 0; i < 4 * 4; i++) {
       coordinateIndexes[i] = fullCoordinateIndexes[i];
       textureCoordinateIndexes[i] = fullTextureCoordinateIndexes[i];
       normalIndexes[i] = fullNormalIndexes[i];
     }
     for (int i = 5 * 4; i < 6 * 4; i++) {
       coordinateIndexes[i - 4] = fullCoordinateIndexes[i];
       textureCoordinateIndexes[i - 4] = fullTextureCoordinateIndexes[i];
       normalIndexes[i - 4] = fullNormalIndexes[i];
     }
   }
   IndexedQuadArray quads = new IndexedQuadArray(coordinates.length, // number
       // of
       // vertexes
       GeometryArray.COORDINATES | // vertex coordinates given
           GeometryArray.NORMALS | // normals given
           GeometryArray.TEXTURE_COORDINATE_2, // texture
       // coordinates given
       coordinateIndexes.length); // number of coordinate indexes
   quads.setCoordinates(0, coordinates);
   quads.setCoordinateIndices(0, coordinateIndexes);
   quads.setNormals(0, normals);
   quads.setNormalIndices(0, normalIndexes);
   quads.setTextureCoordinates(0, textureCoordinates);
   quads.setTextureCoordinateIndices(0, textureCoordinateIndexes);
   Shape3D box = new Shape3D(quads, mainAppearance);
   Vector3f trans = new Vector3f(0.0f, y, 0.0f);
   Transform3D tr = new Transform3D();
   tr.set(trans); // translate
   TransformGroup tg = new TransformGroup(tr);
   tg.addChild(box);
   addChild(tg);
 }
 private final static int NSTEPS = 16;
 private void addCylinder(float radius, float height, float y) {
   //
   //  Compute coordinates, normals, and texture coordinates
   //  around the top and bottom of a cylinder
   //
   float[] coordinates = new float[NSTEPS * 2 * 3]; // xyz
   float[] normals = new float[NSTEPS * 2 * 3]; // xyz vector
   float[] textureCoordinates = new float[NSTEPS * 2 * 2]; // st
   float angle = 0.0f;
   float deltaAngle = 2.0f * (float) Math.PI / ((float) NSTEPS - 1);
   float s = 0.0f;
   float deltaS = 1.0f / ((float) NSTEPS - 1);
   int n = 0;
   int tn = 0;
   float h2 = height / 2.0f;
   for (int i = 0; i < NSTEPS; i++) {
     // bottom
     normals[n + 0] = (float) Math.cos(angle);
     normals[n + 1] = 0.0f;
     normals[n + 2] = -(float) Math.sin(angle);
     coordinates[n + 0] = radius * normals[n + 0];
     coordinates[n + 1] = -h2;
     coordinates[n + 2] = radius * normals[n + 2];
     textureCoordinates[tn + 0] = s;
     textureCoordinates[tn + 1] = 0.0f;
     n += 3;
     tn += 2;
     // top
     normals[n + 0] = normals[n - 3];
     normals[n + 1] = 0.0f;
     normals[n + 2] = normals[n - 1];
     coordinates[n + 0] = coordinates[n - 3];
     coordinates[n + 1] = h2;
     coordinates[n + 2] = coordinates[n - 1];
     textureCoordinates[tn + 0] = s;
     textureCoordinates[tn + 1] = 1.0f;
     n += 3;
     tn += 2;
     angle += deltaAngle;
     s += deltaS;
   }
   //
   //  Compute coordinate indexes, normal indexes, and texture
   //  coordinate indexes awround the sides of a cylinder.
   //  For this application, we don"t need top or bottom, so
   //  skip them.
   //
   int[] indexes = new int[NSTEPS * 4];
   n = 0;
   int p = 0; // panel count
   for (int i = 0; i < NSTEPS - 1; i++) {
     indexes[n + 0] = p; // bottom left
     indexes[n + 1] = p + 2; // bottom right (next panel)
     indexes[n + 2] = p + 3; // top right (next panel)
     indexes[n + 3] = p + 1; // top left
     n += 4;
     p += 2;
   }
   indexes[n + 0] = p; // bottom left
   indexes[n + 1] = 0; // bottom right (next panel)
   indexes[n + 2] = 1; // top right (next panel)
   indexes[n + 3] = p + 1; // top left
   IndexedQuadArray quads = new IndexedQuadArray(coordinates.length / 3, // number
       // of
       // vertexes
       GeometryArray.COORDINATES | // format
           GeometryArray.NORMALS
           | GeometryArray.TEXTURE_COORDINATE_2, indexes.length); // number
   // of
   // indexes
   quads.setCoordinates(0, coordinates);
   quads.setTextureCoordinates(0, textureCoordinates);
   quads.setNormals(0, normals);
   quads.setCoordinateIndices(0, indexes);
   quads.setTextureCoordinateIndices(0, indexes);
   quads.setNormalIndices(0, indexes);
   Shape3D shape = new Shape3D(quads, mainAppearance);
   Vector3f trans = new Vector3f(0.0f, y, 0.0f);
   Transform3D tr = new Transform3D();
   tr.set(trans); // translate
   TransformGroup tg = new TransformGroup(tr);
   tg.addChild(shape);
   addChild(tg);
 }
 //
 //  Control the appearance
 //
 public void setAppearance(Appearance app) {
   mainAppearance = app;
 }
 //
 //  Provide info on the shape and geometry
 //
 public Shape3D getShape(int partid) {
   return null;
 }
 public int getNumTriangles() {
   return 0;
 }
 public int getNumVertices() {
   return 2;
 }
 /* (non-Javadoc)
  * @see com.sun.j3d.utils.geometry.Primitive#getAppearance(int)
  */
 public Appearance getAppearance(int arg0) {
   // TODO Auto-generated method stub
   return null;
 }

} /**

* The Example class is a base class extended by example applications. The class
* provides basic features to create a top-level frame, add a menubar and
* Canvas3D, build the universe, set up "examine" and "walk" style navigation
* behaviors, and provide hooks so that subclasses can add 3D content to the
* example"s universe.
*

* Using this Example class simplifies the construction of example applications, * enabling the author to focus upon 3D content and not the busywork of creating * windows, menus, and universes. * * @version 1.0, 98/04/16 * @author David R. Nadeau, San Diego Supercomputer Center */ class Java3DFrame extends Applet implements WindowListener, ActionListener, ItemListener, CheckboxMenuListener { // Navigation types public final static int Walk = 0; public final static int Examine = 1; // Should the scene be compiled? private boolean shouldCompile = true; // GUI objects for our subclasses protected Java3DFrame example = null; protected Frame exampleFrame = null; protected MenuBar exampleMenuBar = null; protected Canvas3D exampleCanvas = null; protected TransformGroup exampleViewTransform = null; protected TransformGroup exampleSceneTransform = null; protected boolean debug = false; // Private GUI objects and state private boolean headlightOnOff = true; private int navigationType = Examine; private CheckboxMenuItem headlightMenuItem = null; private CheckboxMenuItem walkMenuItem = null; private CheckboxMenuItem examineMenuItem = null; private DirectionalLight headlight = null; private ExamineViewerBehavior examineBehavior = null; private WalkViewerBehavior walkBehavior = null; //-------------------------------------------------------------- // ADMINISTRATION //-------------------------------------------------------------- /** * The main program entry point when invoked as an application. Each example * application that extends this class must define their own main. * * @param args * a String array of command-line arguments */ public static void main(String[] args) { Java3DFrame ex = new Java3DFrame(); ex.initialize(args); ex.buildUniverse(); ex.showFrame(); } /** * Constructs a new Example object. * * @return a new Example that draws no 3D content */ public Java3DFrame() { // Do nothing } /** * Initializes the application when invoked as an applet. */ public void init() { // Collect properties into String array String[] args = new String[2]; // NOTE: to be done still... this.initialize(args); this.buildUniverse(); this.showFrame(); // NOTE: add something to the browser page? } /** * Initializes the Example by parsing command-line arguments, building an * AWT Frame, constructing a menubar, and creating the 3D canvas. * * @param args * a String array of command-line arguments */ protected void initialize(String[] args) { example = this; // Parse incoming arguments parseArgs(args); // Build the frame if (debug) System.err.println("Building GUI..."); exampleFrame = new Frame(); exampleFrame.setSize(640, 480); exampleFrame.setTitle("Java 3D Example"); exampleFrame.setLayout(new BorderLayout()); // Set up a close behavior exampleFrame.addWindowListener(this); // Create a canvas exampleCanvas = new Canvas3D(null); exampleCanvas.setSize(630, 460); exampleFrame.add("Center", exampleCanvas); // Build the menubar exampleMenuBar = this.buildMenuBar(); exampleFrame.setMenuBar(exampleMenuBar); // Pack exampleFrame.pack(); exampleFrame.validate(); // exampleFrame.setVisible( true ); } /** * Parses incoming command-line arguments. Applications that subclass this * class may override this method to support their own command-line * arguments. * * @param args * a String array of command-line arguments */ protected void parseArgs(String[] args) { for (int i = 0; i < args.length; i++) { if (args[i].equals("-d")) debug = true; } } //-------------------------------------------------------------- // SCENE CONTENT //-------------------------------------------------------------- /** * Builds the 3D universe by constructing a virtual universe (via * SimpleUniverse), a view platform (via SimpleUniverse), and a view (via * SimpleUniverse). A headlight is added and a set of behaviors initialized * to handle navigation types. */ protected void buildUniverse() { // // Create a SimpleUniverse object, which builds: // // - a Locale using the given hi-res coordinate origin // // - a ViewingPlatform which in turn builds: // - a MultiTransformGroup with which to move the // the ViewPlatform about // // - a ViewPlatform to hold the view // // - a BranchGroup to hold avatar geometry (if any) // // - a BranchGroup to hold view platform // geometry (if any) // // - a Viewer which in turn builds: // - a PhysicalBody which characterizes the user"s // viewing preferences and abilities // // - a PhysicalEnvironment which characterizes the // user"s rendering hardware and software // // - a JavaSoundMixer which initializes sound // support within the 3D environment // // - a View which renders the scene into a Canvas3D // // All of these actions could be done explicitly, but // using the SimpleUniverse utilities simplifies the code. // if (debug) System.err.println("Building scene graph..."); SimpleUniverse universe = new SimpleUniverse(null, // Hi-res coordinate // for the origin - // use default 1, // Number of transforms in MultiTransformGroup exampleCanvas, // Canvas3D into which to draw null); // URL for user configuration file - use defaults // // Get the viewer and create an audio device so that // sound will be enabled in this content. // Viewer viewer = universe.getViewer(); viewer.createAudioDevice(); // // Get the viewing platform created by SimpleUniverse. // From that platform, get the inner-most TransformGroup // in the MultiTransformGroup. That inner-most group // contains the ViewPlatform. It is this inner-most // TransformGroup we need in order to: // // - add a "headlight" that always aims forward from // the viewer // // - change the viewing direction in a "walk" style // // The inner-most TransformGroup"s transform will be // changed by the walk behavior (when enabled). // ViewingPlatform viewingPlatform = universe.getViewingPlatform(); exampleViewTransform = viewingPlatform.getViewPlatformTransform(); // // Create a "headlight" as a forward-facing directional light. // Set the light"s bounds to huge. Since we want the light // on the viewer"s "head", we need the light within the // TransformGroup containing the ViewPlatform. The // ViewingPlatform class creates a handy hook to do this // called "platform geometry". The PlatformGeometry class is // subclassed off of BranchGroup, and is intended to contain // a description of the 3D platform itself... PLUS a headlight! // So, to add the headlight, create a new PlatformGeometry group, // add the light to it, then add that platform geometry to the // ViewingPlatform. // BoundingSphere allBounds = new BoundingSphere( new Point3d(0.0, 0.0, 0.0), 100000.0); PlatformGeometry pg = new PlatformGeometry(); headlight = new DirectionalLight(); headlight.setColor(White); headlight.setDirection(new Vector3f(0.0f, 0.0f, -1.0f)); headlight.setInfluencingBounds(allBounds); headlight.setCapability(Light.ALLOW_STATE_WRITE); pg.addChild(headlight); viewingPlatform.setPlatformGeometry(pg); // // Create the 3D content BranchGroup, containing: // // - a TransformGroup who"s transform the examine behavior // will change (when enabled). // // - 3D geometry to view // // Build the scene root BranchGroup sceneRoot = new BranchGroup(); // Build a transform that we can modify exampleSceneTransform = new TransformGroup(); exampleSceneTransform .setCapability(TransformGroup.ALLOW_TRANSFORM_READ); exampleSceneTransform .setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); exampleSceneTransform.setCapability(Group.ALLOW_CHILDREN_EXTEND); // // Build the scene, add it to the transform, and add // the transform to the scene root // if (debug) System.err.println(" scene..."); Group scene = this.buildScene(); exampleSceneTransform.addChild(scene); sceneRoot.addChild(exampleSceneTransform); // // Create a pair of behaviors to implement two navigation // types: // // - "examine": a style where mouse drags rotate about // the scene"s origin as if it is an object under // examination. This is similar to the "Examine" // navigation type used by VRML browsers. // // - "walk": a style where mouse drags rotate about // the viewer"s center as if the viewer is turning // about to look at a scene they are in. This is // similar to the "Walk" navigation type used by // VRML browsers. // // Aim the examine behavior at the scene"s TransformGroup // and add the behavior to the scene root. // // Aim the walk behavior at the viewing platform"s // TransformGroup and add the behavior to the scene root. // // Enable one (and only one!) of the two behaviors // depending upon the current navigation type. // examineBehavior = new ExamineViewerBehavior(exampleSceneTransform, // Transform // gorup // to // modify exampleFrame); // Parent frame for cusor changes examineBehavior.setSchedulingBounds(allBounds); sceneRoot.addChild(examineBehavior); walkBehavior = new WalkViewerBehavior(exampleViewTransform, // Transform // group to // modify exampleFrame); // Parent frame for cusor changes walkBehavior.setSchedulingBounds(allBounds); sceneRoot.addChild(walkBehavior); if (navigationType == Walk) { examineBehavior.setEnable(false); walkBehavior.setEnable(true); } else { examineBehavior.setEnable(true); walkBehavior.setEnable(false); } // // Compile the scene branch group and add it to the // SimpleUniverse. // if (shouldCompile) sceneRoot.rupile(); universe.addBranchGraph(sceneRoot); reset(); } /** * Builds the scene. Example application subclasses should replace this * method with their own method to build 3D content. * * @return a Group containing 3D content to display */ public Group buildScene() { // Build the scene group containing nothing Group scene = new Group(); return scene; } //-------------------------------------------------------------- // SET/GET METHODS //-------------------------------------------------------------- /** * Sets the headlight on/off state. The headlight faces forward in the * direction the viewer is facing. Example applications that add their own * lights will typically turn the headlight off. A standard menu item * enables the headlight to be turned on and off via user control. * * @param onOff * a boolean turning the light on (true) or off (false) */ public void setHeadlightEnable(boolean onOff) { headlightOnOff = onOff; if (headlight != null) headlight.setEnable(headlightOnOff); if (headlightMenuItem != null) headlightMenuItem.setState(headlightOnOff); } /** * Gets the headlight on/off state. * * @return a boolean indicating if the headlight is on or off */ public boolean getHeadlightEnable() { return headlightOnOff; } /** * Sets the navigation type to be either Examine or Walk. The Examine * navigation type sets up behaviors that use mouse drags to rotate and * translate scene content as if it is an object held at arm"s length and * under examination. The Walk navigation type uses mouse drags to rotate * and translate the viewer as if they are walking through the content. The * Examine type is the default. * * @param nav * either Walk or Examine */ public void setNavigationType(int nav) { if (nav == Walk) { navigationType = Walk; if (walkMenuItem != null) walkMenuItem.setState(true); if (examineMenuItem != null) examineMenuItem.setState(false); if (walkBehavior != null) walkBehavior.setEnable(true); if (examineBehavior != null) examineBehavior.setEnable(false); } else { navigationType = Examine; if (walkMenuItem != null) walkMenuItem.setState(false); if (examineMenuItem != null) examineMenuItem.setState(true); if (walkBehavior != null) walkBehavior.setEnable(false); if (examineBehavior != null) examineBehavior.setEnable(true); } } /** * Gets the current navigation type, returning either Walk or Examine. * * @return either Walk or Examine */ public int getNavigationType() { return navigationType; } /** * Sets whether the scene graph should be compiled or not. Normally this is * always a good idea. For some example applications that use this Example * framework, it is useful to disable compilation - particularly when nodes * and node components will need to be made un-live in order to make * changes. Once compiled, such components can be made un-live, but they are * still unchangable unless appropriate capabilities have been set. * * @param onOff * a boolean turning compilation on (true) or off (false) */ public void setCompilable(boolean onOff) { shouldCompile = onOff; } /** * Gets whether the scene graph will be compiled or not. * * @return a boolean indicating if scene graph compilation is on or off */ public boolean getCompilable() { return shouldCompile; } //These methods will be replaced // Set the view position and direction public void setViewpoint(Point3f position, Vector3f direction) { Transform3D t = new Transform3D(); t.set(new Vector3f(position)); exampleViewTransform.setTransform(t); // how to set direction? } // Reset transforms public void reset() { Transform3D trans = new Transform3D(); exampleSceneTransform.setTransform(trans); trans.set(new Vector3f(0.0f, 0.0f, 10.0f)); exampleViewTransform.setTransform(trans); setNavigationType(navigationType); } // // Gets the URL (with file: prepended) for the current directory. // This is a terrible hack needed in the Alpha release of Java3D // in order to build a full path URL for loading sounds with // MediaContainer. When MediaContainer is fully implemented, // it should handle relative path names, but not yet. // public String getCurrentDirectory() { // Create a bogus file so that we can query it"s path File dummy = new File("dummy.tmp"); String dummyPath = dummy.getAbsolutePath(); // strip "/dummy.tmp" from end of dummyPath and put into "path" if (dummyPath.endsWith(File.separator + "dummy.tmp")) { int index = dummyPath.lastIndexOf(File.separator + "dummy.tmp"); if (index >= 0) { int pathLength = index + 5; // pre-pend "file:" char[] charPath = new char[pathLength]; dummyPath.getChars(0, index, charPath, 5); String path = new String(charPath, 0, pathLength); path = "file:" + path.substring(5, pathLength); return path + File.separator; } } return dummyPath + File.separator; } //-------------------------------------------------------------- // USER INTERFACE //-------------------------------------------------------------- /** * Builds the example AWT Frame menubar. Standard menus and their options * are added. Applications that subclass this class should build their * menubar additions within their initialize method. * * @return a MenuBar for the AWT Frame */ private MenuBar buildMenuBar() { // Build the menubar MenuBar menuBar = new MenuBar(); // File menu Menu m = new Menu("File"); m.addActionListener(this); m.add("Exit"); menuBar.add(m); // View menu m = new Menu("View"); m.addActionListener(this); m.add("Reset view"); m.addSeparator(); walkMenuItem = new CheckboxMenuItem("Walk"); walkMenuItem.addItemListener(this); m.add(walkMenuItem); examineMenuItem = new CheckboxMenuItem("Examine"); examineMenuItem.addItemListener(this); m.add(examineMenuItem); if (navigationType == Walk) { walkMenuItem.setState(true); examineMenuItem.setState(false); } else { walkMenuItem.setState(false); examineMenuItem.setState(true); } m.addSeparator(); headlightMenuItem = new CheckboxMenuItem("Headlight on/off"); headlightMenuItem.addItemListener(this); headlightMenuItem.setState(headlightOnOff); m.add(headlightMenuItem); menuBar.add(m); return menuBar; } /** * Shows the application"s frame, making it and its menubar, 3D canvas, and * 3D content visible. */ public void showFrame() { exampleFrame.show(); } /** * Quits the application. */ public void quit() { System.exit(0); } /** * Handles menu selections. * * @param event * an ActionEvent indicating what menu action requires handling */ public void actionPerformed(ActionEvent event) { String arg = event.getActionCommand(); if (arg.equals("Reset view")) reset(); else if (arg.equals("Exit")) quit(); } /** * Handles checkbox items on a CheckboxMenu. The Example class has none of * its own, but subclasses may have some. * * @param menu * which CheckboxMenu needs action * @param check * which CheckboxMenu item has changed */ public void checkboxChanged(CheckboxMenu menu, int check) { // None for us } /** * Handles on/off checkbox items on a standard menu. * * @param event * an ItemEvent indicating what requires handling */ public void itemStateChanged(ItemEvent event) { Object src = event.getSource(); boolean state; if (src == headlightMenuItem) { state = headlightMenuItem.getState(); headlight.setEnable(state); } else if (src == walkMenuItem) setNavigationType(Walk); else if (src == examineMenuItem) setNavigationType(Examine); } /** * Handles a window closing event notifying the application that the user * has chosen to close the application without selecting the "Exit" menu * item. * * @param event * a WindowEvent indicating the window is closing */ public void windowClosing(WindowEvent event) { quit(); } public void windowClosed(WindowEvent event) { } public void windowOpened(WindowEvent event) { } public void windowIconified(WindowEvent event) { } public void windowDeiconified(WindowEvent event) { } public void windowActivated(WindowEvent event) { } public void windowDeactivated(WindowEvent event) { } // Well known colors, positions, and directions public final static Color3f White = new Color3f(1.0f, 1.0f, 1.0f); public final static Color3f Gray = new Color3f(0.7f, 0.7f, 0.7f); public final static Color3f DarkGray = new Color3f(0.2f, 0.2f, 0.2f); public final static Color3f Black = new Color3f(0.0f, 0.0f, 0.0f); public final static Color3f Red = new Color3f(1.0f, 0.0f, 0.0f); public final static Color3f DarkRed = new Color3f(0.3f, 0.0f, 0.0f); public final static Color3f Yellow = new Color3f(1.0f, 1.0f, 0.0f); public final static Color3f DarkYellow = new Color3f(0.3f, 0.3f, 0.0f); public final static Color3f Green = new Color3f(0.0f, 1.0f, 0.0f); public final static Color3f DarkGreen = new Color3f(0.0f, 0.3f, 0.0f); public final static Color3f Cyan = new Color3f(0.0f, 1.0f, 1.0f); public final static Color3f Blue = new Color3f(0.0f, 0.0f, 1.0f); public final static Color3f DarkBlue = new Color3f(0.0f, 0.0f, 0.3f); public final static Color3f Magenta = new Color3f(1.0f, 0.0f, 1.0f); public final static Vector3f PosX = new Vector3f(1.0f, 0.0f, 0.0f); public final static Vector3f NegX = new Vector3f(-1.0f, 0.0f, 0.0f); public final static Vector3f PosY = new Vector3f(0.0f, 1.0f, 0.0f); public final static Vector3f NegY = new Vector3f(0.0f, -1.0f, 0.0f); public final static Vector3f PosZ = new Vector3f(0.0f, 0.0f, 1.0f); public final static Vector3f NegZ = new Vector3f(0.0f, 0.0f, -1.0f); public final static Point3f Origin = new Point3f(0.0f, 0.0f, 0.0f); public final static Point3f PlusX = new Point3f(0.75f, 0.0f, 0.0f); public final static Point3f MinusX = new Point3f(-0.75f, 0.0f, 0.0f); public final static Point3f PlusY = new Point3f(0.0f, 0.75f, 0.0f); public final static Point3f MinusY = new Point3f(0.0f, -0.75f, 0.0f); public final static Point3f PlusZ = new Point3f(0.0f, 0.0f, 0.75f); public final static Point3f MinusZ = new Point3f(0.0f, 0.0f, -0.75f); } // //INTERFACE //CheckboxMenuListener - listen for checkbox change events // //DESCRIPTION //The checkboxChanged method is called by users of this class //to notify the listener when a checkbox choice has changed on //a CheckboxMenu class menu. // interface CheckboxMenuListener extends EventListener { public void checkboxChanged(CheckboxMenu menu, int check); } /** * ExamineViewerBehavior * * @version 1.0, 98/04/16 */ /** * Wakeup on mouse button presses, releases, and mouse movements and generate * transforms in an "examination style" that enables the user to rotate, * translation, and zoom an object as if it is held at arm"s length. Such an * examination style is similar to the "Examine" navigation type used by VRML * browsers. * * The behavior maps mouse drags to different transforms depending upon the * mosue button held down: * * Button 1 (left) Horizontal movement --> Y-axis rotation Vertical movement --> * X-axis rotation * * Button 2 (middle) Horizontal movement --> nothing Vertical movement --> * Z-axis translation * * Button 3 (right) Horizontal movement --> X-axis translation Vertical movement * --> Y-axis translation * * To support systems with 2 or 1 mouse buttons, the following alternate * mappings are supported while dragging with any mouse button held down and * zero or more keyboard modifiers held down: * * No modifiers = Button 1 ALT = Button 2 Meta = Button 3 Control = Button 3 * * The behavior automatically modifies a TransformGroup provided to the * constructor. The TransformGroup"s transform can be set at any time by the * application or other behaviors to cause the examine rotation and translation * to be reset. */ // This class is inspired by the MouseBehavior, MouseRotate, // MouseTranslate, and MouseZoom utility behaviors provided with // Java 3D. This class differs from those utilities in that it: // // (a) encapsulates all three behaviors into one in order to // enforce a specific "Examine" symantic // // (b) supports set/get of the rotation and translation factors // that control the speed of movement. // // (c) supports the "Control" modifier as an alternative to the // "Meta" modifier not present on PC, Mac, and most non-Sun // keyboards. This makes button3 behavior usable on PCs, // Macs, and other systems with fewer than 3 mouse buttons. class ExamineViewerBehavior extends ViewerBehavior { // Previous cursor location protected int previousX = 0; protected int previousY = 0; // Saved standard cursor protected Cursor savedCursor = null; /** * Construct an examine behavior that listens to mouse movement and button * presses to generate rotation and translation transforms written into a * transform group given later with the setTransformGroup( ) method. */ public ExamineViewerBehavior() { super(); } /** * Construct an examine behavior that listens to mouse movement and button * presses to generate rotation and translation transforms written into a * transform group given later with the setTransformGroup( ) method. * * @param parent * The AWT Component that contains the area generating mouse * events. */ public ExamineViewerBehavior(Component parent) { super(parent); } /** * Construct an examine behavior that listens to mouse movement and button * presses to generate rotation and translation transforms written into the * given transform group. * * @param transformGroup * The transform group to be modified by the behavior. */ public ExamineViewerBehavior(TransformGroup transformGroup) { super(); subjectTransformGroup = transformGroup; } /** * Construct an examine behavior that listens to mouse movement and button * presses to generate rotation and translation transforms written into the * given transform group. * * @param transformGroup * The transform group to be modified by the behavior. * @param parent * The AWT Component that contains the area generating mouse * events. */ public ExamineViewerBehavior(TransformGroup transformGroup, Component parent) { super(parent); subjectTransformGroup = transformGroup; } /** * Respond to a button1 event (press, release, or drag). * * @param mouseEvent * A MouseEvent to respond to. */ public void onButton1(MouseEvent mev) { if (subjectTransformGroup == null) return; int x = mev.getX(); int y = mev.getY(); if (mev.getID() == MouseEvent.MOUSE_PRESSED) { // Mouse button pressed: record position previousX = x; previousY = y; // Change to a "move" cursor if (parentComponent != null) { savedCursor = parentComponent.getCursor(); parentComponent.setCursor(Cursor .getPredefinedCursor(Cursor.HAND_CURSOR)); } return; } if (mev.getID() == MouseEvent.MOUSE_RELEASED) { // Mouse button released: do nothing // Switch the cursor back if (parentComponent != null) parentComponent.setCursor(savedCursor); return; } // // Mouse moved while button down: create a rotation // // Compute the delta in X and Y from the previous // position. Use the delta to compute rotation // angles with the mapping: // // positive X mouse delta --> positive Y-axis rotation // positive Y mouse delta --> positive X-axis rotation // // where positive X mouse movement is to the right, and // positive Y mouse movement is **down** the screen. // int deltaX = x - previousX; int deltaY = y - previousY; if (deltaX > UNUSUAL_XDELTA || deltaX < -UNUSUAL_XDELTA || deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA) { // Deltas are too huge to be believable. Probably a glitch. // Don"t record the new XY location, or do anything. return; } double xRotationAngle = deltaY * XRotationFactor; double yRotationAngle = deltaX * YRotationFactor; // // Build transforms // transform1.rotX(xRotationAngle); transform2.rotY(yRotationAngle); // Get and save the current transform matrix subjectTransformGroup.getTransform(currentTransform); currentTransform.get(matrix); translate.set(matrix.m03, matrix.m13, matrix.m23); // Translate to the origin, rotate, then translate back currentTransform.setTranslation(origin); currentTransform.mul(transform1, currentTransform); currentTransform.mul(transform2, currentTransform); currentTransform.setTranslation(translate); // Update the transform group subjectTransformGroup.setTransform(currentTransform); previousX = x; previousY = y; } /** * Respond to a button2 event (press, release, or drag). * * @param mouseEvent * A MouseEvent to respond to. */ public void onButton2(MouseEvent mev) { if (subjectTransformGroup == null) return; int x = mev.getX(); int y = mev.getY(); if (mev.getID() == MouseEvent.MOUSE_PRESSED) { // Mouse button pressed: record position previousX = x; previousY = y; // Change to a "move" cursor if (parentComponent != null) { savedCursor = parentComponent.getCursor(); parentComponent.setCursor(Cursor .getPredefinedCursor(Cursor.MOVE_CURSOR)); } return; } if (mev.getID() == MouseEvent.MOUSE_RELEASED) { // Mouse button released: do nothing // Switch the cursor back if (parentComponent != null) parentComponent.setCursor(savedCursor); return; } // // Mouse moved while button down: create a translation // // Compute the delta in Y from the previous // position. Use the delta to compute translation // distances with the mapping: // // positive Y mouse delta --> positive Y-axis translation // // where positive X mouse movement is to the right, and // positive Y mouse movement is **down** the screen. // int deltaY = y - previousY; if (deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA) { // Deltas are too huge to be believable. Probably a glitch. // Don"t record the new XY location, or do anything. return; } double zTranslationDistance = deltaY * ZTranslationFactor; // // Build transforms // translate.set(0.0, 0.0, zTranslationDistance); transform1.set(translate); // Get and save the current transform subjectTransformGroup.getTransform(currentTransform); // Translate as needed currentTransform.mul(transform1, currentTransform); // Update the transform group subjectTransformGroup.setTransform(currentTransform); previousX = x; previousY = y; } /** * Respond to a button3 event (press, release, or drag). * * @param mouseEvent * A MouseEvent to respond to. */ public void onButton3(MouseEvent mev) { if (subjectTransformGroup == null) return; int x = mev.getX(); int y = mev.getY(); if (mev.getID() == MouseEvent.MOUSE_PRESSED) { // Mouse button pressed: record position previousX = x; previousY = y; // Change to a "move" cursor if (parentComponent != null) { savedCursor = parentComponent.getCursor(); parentComponent.setCursor(Cursor .getPredefinedCursor(Cursor.MOVE_CURSOR)); } return; } if (mev.getID() == MouseEvent.MOUSE_RELEASED) { // Mouse button released: do nothing // Switch the cursor back if (parentComponent != null) parentComponent.setCursor(savedCursor); return; } // // Mouse moved while button down: create a translation // // Compute the delta in X and Y from the previous // position. Use the delta to compute translation // distances with the mapping: // // positive X mouse delta --> positive X-axis translation // positive Y mouse delta --> negative Y-axis translation // // where positive X mouse movement is to the right, and // positive Y mouse movement is **down** the screen. // int deltaX = x - previousX; int deltaY = y - previousY; if (deltaX > UNUSUAL_XDELTA || deltaX < -UNUSUAL_XDELTA || deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA) { // Deltas are too huge to be believable. Probably a glitch. // Don"t record the new XY location, or do anything. return; } double xTranslationDistance = deltaX * XTranslationFactor; double yTranslationDistance = -deltaY * YTranslationFactor; // // Build transforms // translate.set(xTranslationDistance, yTranslationDistance, 0.0); transform1.set(translate); // Get and save the current transform subjectTransformGroup.getTransform(currentTransform); // Translate as needed currentTransform.mul(transform1, currentTransform); // Update the transform group subjectTransformGroup.setTransform(currentTransform); previousX = x; previousY = y; } /** * Respond to an elapsed frames event (assuming subclass has set up a wakeup * criterion for it). * * @param time * A WakeupOnElapsedFrames criterion to respond to. */ public void onElapsedFrames(WakeupOnElapsedFrames timeEvent) { // Can"t happen } } /* * * Copyright (c) 1998 David R. Nadeau * */ /** * WalkViewerBehavior is a utility class that creates a "walking style" * navigation symantic. * * The behavior wakes up on mouse button presses, releases, and mouse movements * and generates transforms in a "walk style" that enables the user to walk * through a scene, translating and turning about as if they are within the * scene. Such a walk style is similar to the "Walk" navigation type used by * VRML browsers. * <P> * The behavior maps mouse drags to different transforms depending upon the * mouse button held down: *

*
Button 1 (left) *
Horizontal movement --> Y-axis rotation *
Vertical movement --> Z-axis translation * *
Button 2 (middle) *
Horizontal movement --> Y-axis rotation *
Vertical movement --> X-axis rotation * *
Button 3 (right) *
Horizontal movement --> X-axis translation *
Vertical movement --> Y-axis translation *
* 
* To support systems with 2 or 1 mouse buttons, the following alternate
* mappings are supported while dragging with any mouse button held down and
* zero or more keyboard modifiers held down:
*
    *
  • No modifiers = Button 1 *
  • ALT = Button 2 *
  • Meta = Button 3 *
  • Control = Button 3 *
* The behavior automatically modifies a TransformGroup provided to the
* constructor. The TransformGroup"s transform can be set at any time by the
* application or other behaviors to cause the walk rotation and translation to
* be reset.
* <P>
* While a mouse button is down, the behavior automatically changes the cursor
* in a given parent AWT Component. If no parent Component is given, no cursor
* changes are attempted.
* 
* @version 1.0, 98/04/16
* @author David R. Nadeau, San Diego Supercomputer Center
*/

class WalkViewerBehavior extends ViewerBehavior {

 // This class is inspired by the MouseBehavior, MouseRotate,
 // MouseTranslate, and MouseZoom utility behaviors provided with
 // Java 3D. This class differs from those utilities in that it:
 //
 //    (a) encapsulates all three behaviors into one in order to
 //        enforce a specific "Walk" symantic
 //
 //    (b) supports set/get of the rotation and translation factors
 //        that control the speed of movement.
 //
 //    (c) supports the "Control" modifier as an alternative to the
 //        "Meta" modifier not present on PC, Mac, and most non-Sun
 //        keyboards. This makes button3 behavior usable on PCs,
 //        Macs, and other systems with fewer than 3 mouse buttons.
 // Previous and initial cursor locations
 protected int previousX = 0;
 protected int previousY = 0;
 protected int initialX = 0;
 protected int initialY = 0;
 // Deadzone size (delta from initial XY for which no
 // translate or rotate action is taken
 protected static final int DELTAX_DEADZONE = 10;
 protected static final int DELTAY_DEADZONE = 10;
 // Keep a set of wakeup criterion for animation-generated
 // event types.
 protected WakeupCriterion[] mouseAndAnimationEvents = null;
 protected WakeupOr mouseAndAnimationCriterion = null;
 protected WakeupOr savedMouseCriterion = null;
 // Saved standard cursor
 protected Cursor savedCursor = null;
 /**
  * Default Rotation and translation scaling factors for animated movements
  * (Button 1 press).
  */
 public static final double DEFAULT_YROTATION_ANIMATION_FACTOR = 0.0002;
 public static final double DEFAULT_ZTRANSLATION_ANIMATION_FACTOR = 0.01;
 protected double YRotationAnimationFactor = DEFAULT_YROTATION_ANIMATION_FACTOR;
 protected double ZTranslationAnimationFactor = DEFAULT_ZTRANSLATION_ANIMATION_FACTOR;
 /**
  * Constructs a new walk behavior that converts mouse actions into rotations
  * and translations. Rotations and translations are written into a
  * TransformGroup that must be set using the setTransformGroup method. The
  * cursor will be changed during mouse actions if the parent frame is set
  * using the setParentComponent method.
  * 
  * @return a new WalkViewerBehavior that needs its TransformGroup and parent
  *         Component set
  */
 public WalkViewerBehavior() {
   super();
 }
 /**
  * Constructs a new walk behavior that converts mouse actions into rotations
  * and translations. Rotations and translations are written into a
  * TransformGroup that must be set using the setTransformGroup method. The
  * cursor will be changed within the given AWT parent Component during mouse
  * drags.
  * 
  * @param parent
  *            a parent AWT Component within which the cursor will change
  *            during mouse drags
  * 
  * @return a new WalkViewerBehavior that needs its TransformGroup and parent
  *         Component set
  */
 public WalkViewerBehavior(Component parent) {
   super(parent);
 }
 /**
  * Constructs a new walk behavior that converts mouse actions into rotations
  * and translations. Rotations and translations are written into the given
  * TransformGroup. The cursor will be changed during mouse actions if the
  * parent frame is set using the setParentComponent method.
  * 
  * @param transformGroup
  *            a TransformGroup whos transform is read and written by the
  *            behavior
  * 
  * @return a new WalkViewerBehavior that needs its TransformGroup and parent
  *         Component set
  */
 public WalkViewerBehavior(TransformGroup transformGroup) {
   super();
   subjectTransformGroup = transformGroup;
 }
 /**
  * Constructs a new walk behavior that converts mouse actions into rotations
  * and translations. Rotations and translations are written into the given
  * TransformGroup. The cursor will be changed within the given AWT parent
  * Component during mouse drags.
  * 
  * @param transformGroup
  *            a TransformGroup whos transform is read and written by the
  *            behavior
  * 
  * @param parent
  *            a parent AWT Component within which the cursor will change
  *            during mouse drags
  * 
  * @return a new WalkViewerBehavior that needs its TransformGroup and parent
  *         Component set
  */
 public WalkViewerBehavior(TransformGroup transformGroup, Component parent) {
   super(parent);
   subjectTransformGroup = transformGroup;
 }
 /**
  * Initializes the behavior.
  */
 public void initialize() {
   super.initialize();
   savedMouseCriterion = mouseCriterion; // from parent class
   mouseAndAnimationEvents = new WakeupCriterion[4];
   mouseAndAnimationEvents[0] = new WakeupOnAWTEvent(
       MouseEvent.MOUSE_DRAGGED);
   mouseAndAnimationEvents[1] = new WakeupOnAWTEvent(
       MouseEvent.MOUSE_PRESSED);
   mouseAndAnimationEvents[2] = new WakeupOnAWTEvent(
       MouseEvent.MOUSE_RELEASED);
   mouseAndAnimationEvents[3] = new WakeupOnElapsedFrames(0);
   mouseAndAnimationCriterion = new WakeupOr(mouseAndAnimationEvents);
   // Don"t use the above criterion until a button 1 down event
 }
 /**
  * Sets the Y rotation animation scaling factor for Y-axis rotations. This
  * scaling factor is used to control the speed of Y rotation when button 1
  * is pressed and dragged.
  * 
  * @param factor
  *            the double Y rotation scaling factor
  */
 public void setYRotationAnimationFactor(double factor) {
   YRotationAnimationFactor = factor;
 }
 /**
  * Gets the current Y animation rotation scaling factor for Y-axis
  * rotations.
  * 
  * @return the double Y rotation scaling factor
  */
 public double getYRotationAnimationFactor() {
   return YRotationAnimationFactor;
 }
 /**
  * Sets the Z animation translation scaling factor for Z-axis translations.
  * This scaling factor is used to control the speed of Z translation when
  * button 1 is pressed and dragged.
  * 
  * @param factor
  *            the double Z translation scaling factor
  */
 public void setZTranslationAnimationFactor(double factor) {
   ZTranslationAnimationFactor = factor;
 }
 /**
  * Gets the current Z animation translation scaling factor for Z-axis
  * translations.
  * 
  * @return the double Z translation scaling factor
  */
 public double getZTranslationAnimationFactor() {
   return ZTranslationAnimationFactor;
 }
 /**
  * Responds to an elapsed frames event. Such an event is generated on every
  * frame while button 1 is held down. On each call, this method computes new
  * Y-axis rotation and Z-axis translation values and writes them to the
  * behavior"s TransformGroup. The translation and rotation amounts are
  * computed based upon the distance between the current cursor location and
  * the cursor location when button 1 was pressed. As this distance
  * increases, the translation or rotation amount increases.
  * 
  * @param time
  *            the WakeupOnElapsedFrames criterion to respond to
  */
 public void onElapsedFrames(WakeupOnElapsedFrames timeEvent) {
   //
   // Time elapsed while button down: create a rotation and
   // a translation.
   //
   // Compute the delta in X and Y from the initial position to
   // the previous position. Multiply the delta times a scaling
   // factor to compute an offset to add to the current translation
   // and rotation. Use the mapping:
   //
   //   positive X mouse delta --> negative Y-axis rotation
   //   positive Y mouse delta --> positive Z-axis translation
   //
   // where positive X mouse movement is to the right, and
   // positive Y mouse movement is **down** the screen.
   //
   if (buttonPressed != BUTTON1)
     return;
   int deltaX = previousX - initialX;
   int deltaY = previousY - initialY;
   double yRotationAngle = -deltaX * YRotationAnimationFactor;
   double zTranslationDistance = deltaY * ZTranslationAnimationFactor;
   //
   // Build transforms
   //
   transform1.rotY(yRotationAngle);
   translate.set(0.0, 0.0, zTranslationDistance);
   // Get and save the current transform matrix
   subjectTransformGroup.getTransform(currentTransform);
   currentTransform.get(matrix);
   // Translate to the origin, rotate, then translate back
   currentTransform.setTranslation(origin);
   currentTransform.mul(transform1, currentTransform);
   // Translate back from the origin by the original translation
   // distance, plus the new walk translation... but force walk
   // to travel on a plane by ignoring the Y component of a
   // transformed translation vector.
   currentTransform.transform(translate);
   translate.x += matrix.m03; // add in existing X translation
   translate.y = matrix.m13; // use Y translation
   translate.z += matrix.m23; // add in existing Z translation
   currentTransform.setTranslation(translate);
   // Update the transform group
   subjectTransformGroup.setTransform(currentTransform);
 }
 /**
  * Responds to a button1 event (press, release, or drag). On a press, the
  * method adds a wakeup criterion to the behavior"s set, callling for the
  * behavior to be awoken on each frame. On a button prelease, this criterion
  * is removed from the set.
  * 
  * @param mouseEvent
  *            the MouseEvent to respond to
  */
 public void onButton1(MouseEvent mev) {
   if (subjectTransformGroup == null)
     return;
   int x = mev.getX();
   int y = mev.getY();
   if (mev.getID() == MouseEvent.MOUSE_PRESSED) {
     // Mouse button pressed: record position and change
     // the wakeup criterion to include elapsed time wakeups
     // so we can animate.
     previousX = x;
     previousY = y;
     initialX = x;
     initialY = y;
     // Swap criterion... parent class will not reschedule us
     mouseCriterion = mouseAndAnimationCriterion;
     // Change to a "move" cursor
     if (parentComponent != null) {
       savedCursor = parentComponent.getCursor();
       parentComponent.setCursor(Cursor
           .getPredefinedCursor(Cursor.HAND_CURSOR));
     }
     return;
   }
   if (mev.getID() == MouseEvent.MOUSE_RELEASED) {
     // Mouse button released: restore original wakeup
     // criterion which only includes mouse activity, not
     // elapsed time
     mouseCriterion = savedMouseCriterion;
     // Switch the cursor back
     if (parentComponent != null)
       parentComponent.setCursor(savedCursor);
     return;
   }
   previousX = x;
   previousY = y;
 }
 /**
  * Responds to a button2 event (press, release, or drag). On a press, the
  * method records the initial cursor location. On a drag, the difference
  * between the current and previous cursor location provides a delta that
  * controls the amount by which to rotate in X and Y.
  * 
  * @param mouseEvent
  *            the MouseEvent to respond to
  */
 public void onButton2(MouseEvent mev) {
   if (subjectTransformGroup == null)
     return;
   int x = mev.getX();
   int y = mev.getY();
   if (mev.getID() == MouseEvent.MOUSE_PRESSED) {
     // Mouse button pressed: record position
     previousX = x;
     previousY = y;
     initialX = x;
     initialY = y;
     // Change to a "rotate" cursor
     if (parentComponent != null) {
       savedCursor = parentComponent.getCursor();
       parentComponent.setCursor(Cursor
           .getPredefinedCursor(Cursor.MOVE_CURSOR));
     }
     return;
   }
   if (mev.getID() == MouseEvent.MOUSE_RELEASED) {
     // Mouse button released: do nothing
     // Switch the cursor back
     if (parentComponent != null)
       parentComponent.setCursor(savedCursor);
     return;
   }
   //
   // Mouse moved while button down: create a rotation
   //
   // Compute the delta in X and Y from the previous
   // position. Use the delta to compute rotation
   // angles with the mapping:
   //
   //   positive X mouse delta --> negative Y-axis rotation
   //   positive Y mouse delta --> negative X-axis rotation
   //
   // where positive X mouse movement is to the right, and
   // positive Y mouse movement is **down** the screen.
   //
   int deltaX = x - previousX;
   int deltaY = 0;
   if (Math.abs(y - initialY) > DELTAY_DEADZONE) {
     // Cursor has moved far enough vertically to consider
     // it intentional, so get it"s delta.
     deltaY = y - previousY;
   }
   if (deltaX > UNUSUAL_XDELTA || deltaX < -UNUSUAL_XDELTA
       || deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA) {
     // Deltas are too huge to be believable. Probably a glitch.
     // Don"t record the new XY location, or do anything.
     return;
   }
   double xRotationAngle = -deltaY * XRotationFactor;
   double yRotationAngle = -deltaX * YRotationFactor;
   //
   // Build transforms
   //
   transform1.rotX(xRotationAngle);
   transform2.rotY(yRotationAngle);
   // Get and save the current transform matrix
   subjectTransformGroup.getTransform(currentTransform);
   currentTransform.get(matrix);
   translate.set(matrix.m03, matrix.m13, matrix.m23);
   // Translate to the origin, rotate, then translate back
   currentTransform.setTranslation(origin);
   currentTransform.mul(transform2, currentTransform);
   currentTransform.mul(transform1);
   currentTransform.setTranslation(translate);
   // Update the transform group
   subjectTransformGroup.setTransform(currentTransform);
   previousX = x;
   previousY = y;
 }
 /**
  * Responds to a button3 event (press, release, or drag). On a drag, the
  * difference between the current and previous cursor location provides a
  * delta that controls the amount by which to translate in X and Y.
  * 
  * @param mouseEvent
  *            the MouseEvent to respond to
  */
 public void onButton3(MouseEvent mev) {
   if (subjectTransformGroup == null)
     return;
   int x = mev.getX();
   int y = mev.getY();
   if (mev.getID() == MouseEvent.MOUSE_PRESSED) {
     // Mouse button pressed: record position
     previousX = x;
     previousY = y;
     // Change to a "move" cursor
     if (parentComponent != null) {
       savedCursor = parentComponent.getCursor();
       parentComponent.setCursor(Cursor
           .getPredefinedCursor(Cursor.MOVE_CURSOR));
     }
     return;
   }
   if (mev.getID() == MouseEvent.MOUSE_RELEASED) {
     // Mouse button released: do nothing
     // Switch the cursor back
     if (parentComponent != null)
       parentComponent.setCursor(savedCursor);
     return;
   }
   //
   // Mouse moved while button down: create a translation
   //
   // Compute the delta in X and Y from the previous
   // position. Use the delta to compute translation
   // distances with the mapping:
   //
   //   positive X mouse delta --> positive X-axis translation
   //   positive Y mouse delta --> negative Y-axis translation
   //
   // where positive X mouse movement is to the right, and
   // positive Y mouse movement is **down** the screen.
   //
   int deltaX = x - previousX;
   int deltaY = y - previousY;
   if (deltaX > UNUSUAL_XDELTA || deltaX < -UNUSUAL_XDELTA
       || deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA) {
     // Deltas are too huge to be believable. Probably a glitch.
     // Don"t record the new XY location, or do anything.
     return;
   }
   double xTranslationDistance = deltaX * XTranslationFactor;
   double yTranslationDistance = -deltaY * YTranslationFactor;
   //
   // Build transforms
   //
   translate.set(xTranslationDistance, yTranslationDistance, 0.0);
   transform1.set(translate);
   // Get and save the current transform
   subjectTransformGroup.getTransform(currentTransform);
   // Translate as needed
   currentTransform.mul(transform1);
   // Update the transform group
   subjectTransformGroup.setTransform(currentTransform);
   previousX = x;
   previousY = y;
 }

} // //CLASS //CheckboxMenu - build a menu of grouped checkboxes // //DESCRIPTION //The class creates a menu with one or more CheckboxMenuItem"s //and monitors that menu. When a menu checkbox is picked, the //previous one is turned off (in radio-button style). Then, //a given listener"s checkboxChanged method is called, passing it //the menu and the item checked. // class CheckboxMenu extends Menu implements ItemListener {

 // State
 protected CheckboxMenuItem[] checks = null;
 protected int current = 0;
 protected CheckboxMenuListener listener = null;
 //  Construct
 public CheckboxMenu(String name, NameValue[] items,
     CheckboxMenuListener listen) {
   this(name, items, 0, listen);
 }
 public CheckboxMenu(String name, NameValue[] items, int cur,
     CheckboxMenuListener listen) {
   super(name);
   current = cur;
   listener = listen;
   if (items == null)
     return;
   checks = new CheckboxMenuItem[items.length];
   for (int i = 0; i < items.length; i++) {
     checks[i] = new CheckboxMenuItem(items[i].name, false);
     checks[i].addItemListener(this);
     add(checks[i]);
   }
   checks[cur].setState(true);
 }
 //  Handle checkbox changed events
 public void itemStateChanged(ItemEvent event) {
   Object src = event.getSource();
   for (int i = 0; i < checks.length; i++) {
     if (src == checks[i]) {
       // Update the checkboxes
       checks[current].setState(false);
       current = i;
       checks[current].setState(true);
       if (listener != null)
         listener.checkboxChanged(this, i);
       return;
     }
   }
 }
 // Methods to get and set state
 public int getCurrent() {
   return current;
 }
 public void setCurrent(int cur) {
   if (cur < 0 || cur >= checks.length)
     return; // ignore out of range choices
   if (checks == null)
     return;
   checks[current].setState(false);
   current = cur;
   checks[current].setState(true);
 }
 public CheckboxMenuItem getSelectedCheckbox() {
   if (checks == null)
     return null;
   return checks[current];
 }
 public void setSelectedCheckbox(CheckboxMenuItem item) {
   if (checks == null)
     return;
   for (int i = 0; i < checks.length; i++) {
     if (item == checks[i]) {
       checks[i].setState(false);
       current = i;
       checks[i].setState(true);
     }
   }
 }

} /**

* ViewerBehavior
* 
* @version 1.0, 98/04/16
*/

/**

* Wakeup on mouse button presses, releases, and mouse movements and generate
* transforms for a transform group. Classes that extend this class impose
* specific symantics, such as "Examine" or "Walk" viewing, similar to the
* navigation types used by VRML browsers.
* 
* To support systems with 2 or 1 mouse buttons, the following alternate
* mappings are supported while dragging with any mouse button held down and
* zero or more keyboard modifiers held down:
* 
* No modifiers = Button 1 ALT = Button 2 Meta = Button 3 Control = Button 3
* 
* The behavior automatically modifies a TransformGroup provided to the
* constructor. The TransformGroup"s transform can be set at any time by the
* application or other behaviors to cause the viewer"s rotation and translation
* to be reset.
*/

// This class is inspired by the MouseBehavior, MouseRotate, // MouseTranslate, and MouseZoom utility behaviors provided with // Java 3D. This class differs from those utilities in that it: // // (a) encapsulates all three behaviors into one in order to // enforce a specific viewing symantic // // (b) supports set/get of the rotation and translation factors // that control the speed of movement. // // (c) supports the "Control" modifier as an alternative to the // "Meta" modifier not present on PC, Mac, and most non-Sun // keyboards. This makes button3 behavior usable on PCs, // Macs, and other systems with fewer than 3 mouse buttons. abstract class ViewerBehavior extends Behavior {

 // Keep track of the transform group who"s transform we modify
 // during mouse motion.
 protected TransformGroup subjectTransformGroup = null;
 // Keep a set of wakeup criterion for different mouse-generated
 // event types.
 protected WakeupCriterion[] mouseEvents = null;
 protected WakeupOr mouseCriterion = null;
 // Track which button was last pressed
 protected static final int BUTTONNONE = -1;
 protected static final int BUTTON1 = 0;
 protected static final int BUTTON2 = 1;
 protected static final int BUTTON3 = 2;
 protected int buttonPressed = BUTTONNONE;
 // Keep a few Transform3Ds for use during event processing. This
 // avoids having to allocate new ones on each event.
 protected Transform3D currentTransform = new Transform3D();
 protected Transform3D transform1 = new Transform3D();
 protected Transform3D transform2 = new Transform3D();
 protected Matrix4d matrix = new Matrix4d();
 protected Vector3d origin = new Vector3d(0.0, 0.0, 0.0);
 protected Vector3d translate = new Vector3d(0.0, 0.0, 0.0);
 // Unusual X and Y delta limits.
 protected static final int UNUSUAL_XDELTA = 400;
 protected static final int UNUSUAL_YDELTA = 400;
 protected Component parentComponent = null;
 /**
  * Construct a viewer behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into a
  * transform group given later with the setTransformGroup( ) method.
  */
 public ViewerBehavior() {
   super();
 }
 /**
  * Construct a viewer behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into a
  * transform group given later with the setTransformGroup( ) method.
  * 
  * @param parent
  *            The AWT Component that contains the area generating mouse
  *            events.
  */
 public ViewerBehavior(Component parent) {
   super();
   parentComponent = parent;
 }
 /**
  * Construct a viewer behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into the
  * given transform group.
  * 
  * @param transformGroup
  *            The transform group to be modified by the behavior.
  */
 public ViewerBehavior(TransformGroup transformGroup) {
   super();
   subjectTransformGroup = transformGroup;
 }
 /**
  * Construct a viewer behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into the
  * given transform group.
  * 
  * @param transformGroup
  *            The transform group to be modified by the behavior.
  * @param parent
  *            The AWT Component that contains the area generating mouse
  *            events.
  */
 public ViewerBehavior(TransformGroup transformGroup, Component parent) {
   super();
   subjectTransformGroup = transformGroup;
   parentComponent = parent;
 }
 /**
  * Set the transform group modified by the viewer behavior. Setting the
  * transform group to null disables the behavior until the transform group
  * is again set to an existing group.
  * 
  * @param transformGroup
  *            The new transform group to be modified by the behavior.
  */
 public void setTransformGroup(TransformGroup transformGroup) {
   subjectTransformGroup = transformGroup;
 }
 /**
  * Get the transform group modified by the viewer behavior.
  */
 public TransformGroup getTransformGroup() {
   return subjectTransformGroup;
 }
 /**
  * Sets the parent component who"s cursor will be changed during mouse
  * drags. If no component is given is given to the constructor, or set via
  * this method, no cursor changes will be done.
  * 
  * @param parent
  *            the AWT Component, such as a Frame, within which cursor
  *            changes should take place during mouse drags
  */
 public void setParentComponent(Component parent) {
   parentComponent = parent;
 }
 /*
  * Gets the parent frame within which the cursor changes during mouse drags.
  * 
  * @return the AWT Component, such as a Frame, within which cursor changes
  * should take place during mouse drags. Returns null if no parent is set.
  */
 public Component getParentComponent() {
   return parentComponent;
 }
 /**
  * Initialize the behavior.
  */
 public void initialize() {
   // Wakeup when the mouse is dragged or when a mouse button
   // is pressed or released.
   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);
   mouseCriterion = new WakeupOr(mouseEvents);
   wakeupOn(mouseCriterion);
 }
 /**
  * Process a new wakeup. Interpret mouse button presses, releases, and mouse
  * drags.
  * 
  * @param criteria
  *            The wakeup criteria causing the behavior wakeup.
  */
 public void processStimulus(Enumeration criteria) {
   WakeupCriterion wakeup = null;
   AWTEvent[] event = null;
   int whichButton = BUTTONNONE;
   // Process all pending wakeups
   while (criteria.hasMoreElements()) {
     wakeup = (WakeupCriterion) criteria.nextElement();
     if (wakeup instanceof WakeupOnAWTEvent) {
       event = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
       // Process all pending events
       for (int i = 0; i < event.length; i++) {
         if (event[i].getID() != MouseEvent.MOUSE_PRESSED
             && event[i].getID() != MouseEvent.MOUSE_RELEASED
             && event[i].getID() != MouseEvent.MOUSE_DRAGGED)
           // Ignore uninteresting mouse events
           continue;
         //
         // Regretably, Java event handling (or perhaps
         // underlying OS event handling) doesn"t always
         // catch button bounces (redundant presses and
         // releases), or order events so that the last
         // drag event is delivered before a release.
         // This means we can get stray events that we
         // filter out here.
         //
         if (event[i].getID() == MouseEvent.MOUSE_PRESSED
             && buttonPressed != BUTTONNONE)
           // Ignore additional button presses until a release
           continue;
         if (event[i].getID() == MouseEvent.MOUSE_RELEASED
             && buttonPressed == BUTTONNONE)
           // Ignore additional button releases until a press
           continue;
         if (event[i].getID() == MouseEvent.MOUSE_DRAGGED
             && buttonPressed == BUTTONNONE)
           // Ignore drags until a press
           continue;
         MouseEvent mev = (MouseEvent) event[i];
         int modifiers = mev.getModifiers();
         //
         // Unfortunately, the underlying event handling
         // doesn"t do a "grab" operation when a mouse button
         // is pressed. This means that once a button is
         // pressed, if another mouse button or a keyboard
         // modifier key is pressed, the delivered mouse event
         // will show that a different button is being held
         // down. For instance:
         //
         // Action Event
         //  Button 1 press Button 1 press
         //  Drag with button 1 down Button 1 drag
         //  ALT press -
         //  Drag with ALT & button 1 down Button 2 drag
         //  Button 1 release Button 2 release
         //
         // The upshot is that we can get a button press
         // without a matching release, and the button
         // associated with a drag can change mid-drag.
         //
         // To fix this, we watch for an initial button
         // press, and thenceforth consider that button
         // to be the one held down, even if additional
         // buttons get pressed, and despite what is
         // reported in the event. Only when a button is
         // released, do we end such a grab.
         //
         if (buttonPressed == BUTTONNONE) {
           // No button is pressed yet, figure out which
           // button is down now and how to direct events
           if (((modifiers & InputEvent.BUTTON3_MASK) != 0)
               || (((modifiers & InputEvent.BUTTON1_MASK) != 0) && ((modifiers & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK))) {
             // Button 3 activity (META or CTRL down)
             whichButton = BUTTON3;
           } else if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
             // Button 2 activity (ALT down)
             whichButton = BUTTON2;
           } else {
             // Button 1 activity (no modifiers down)
             whichButton = BUTTON1;
           }
           // If the event is to press a button, then
           // record that that button is now down
           if (event[i].getID() == MouseEvent.MOUSE_PRESSED)
             buttonPressed = whichButton;
         } else {
           // Otherwise a button was pressed earlier and
           // hasn"t been released yet. Assign all further
           // events to it, even if ALT, META, CTRL, or
           // another button has been pressed as well.
           whichButton = buttonPressed;
         }
         // Distribute the event
         switch (whichButton) {
         case BUTTON1:
           onButton1(mev);
           break;
         case BUTTON2:
           onButton2(mev);
           break;
         case BUTTON3:
           onButton3(mev);
           break;
         default:
           break;
         }
         // If the event is to release a button, then
         // record that that button is now up
         if (event[i].getID() == MouseEvent.MOUSE_RELEASED)
           buttonPressed = BUTTONNONE;
       }
       continue;
     }
     if (wakeup instanceof WakeupOnElapsedFrames) {
       onElapsedFrames((WakeupOnElapsedFrames) wakeup);
       continue;
     }
   }
   // Reschedule us for another wakeup
   wakeupOn(mouseCriterion);
 }
 /**
  * Default X and Y rotation factors, and XYZ translation factors.
  */
 public static final double DEFAULT_XROTATION_FACTOR = 0.02;
 public static final double DEFAULT_YROTATION_FACTOR = 0.005;
 public static final double DEFAULT_XTRANSLATION_FACTOR = 0.02;
 public static final double DEFAULT_YTRANSLATION_FACTOR = 0.02;
 public static final double DEFAULT_ZTRANSLATION_FACTOR = 0.04;
 protected double XRotationFactor = DEFAULT_XROTATION_FACTOR;
 protected double YRotationFactor = DEFAULT_YROTATION_FACTOR;
 protected double XTranslationFactor = DEFAULT_XTRANSLATION_FACTOR;
 protected double YTranslationFactor = DEFAULT_YTRANSLATION_FACTOR;
 protected double ZTranslationFactor = DEFAULT_ZTRANSLATION_FACTOR;
 /**
  * Set the X rotation scaling factor for X-axis rotations.
  * 
  * @param factor
  *            The new scaling factor.
  */
 public void setXRotationFactor(double factor) {
   XRotationFactor = factor;
 }
 /**
  * Get the current X rotation scaling factor for X-axis rotations.
  */
 public double getXRotationFactor() {
   return XRotationFactor;
 }
 /**
  * Set the Y rotation scaling factor for Y-axis rotations.
  * 
  * @param factor
  *            The new scaling factor.
  */
 public void setYRotationFactor(double factor) {
   YRotationFactor = factor;
 }
 /**
  * Get the current Y rotation scaling factor for Y-axis rotations.
  */
 public double getYRotationFactor() {
   return YRotationFactor;
 }
 /**
  * Set the X translation scaling factor for X-axis translations.
  * 
  * @param factor
  *            The new scaling factor.
  */
 public void setXTranslationFactor(double factor) {
   XTranslationFactor = factor;
 }
 /**
  * Get the current X translation scaling factor for X-axis translations.
  */
 public double getXTranslationFactor() {
   return XTranslationFactor;
 }
 /**
  * Set the Y translation scaling factor for Y-axis translations.
  * 
  * @param factor
  *            The new scaling factor.
  */
 public void setYTranslationFactor(double factor) {
   YTranslationFactor = factor;
 }
 /**
  * Get the current Y translation scaling factor for Y-axis translations.
  */
 public double getYTranslationFactor() {
   return YTranslationFactor;
 }
 /**
  * Set the Z translation scaling factor for Z-axis translations.
  * 
  * @param factor
  *            The new scaling factor.
  */
 public void setZTranslationFactor(double factor) {
   ZTranslationFactor = factor;
 }
 /**
  * Get the current Z translation scaling factor for Z-axis translations.
  */
 public double getZTranslationFactor() {
   return ZTranslationFactor;
 }
 /**
  * Respond to a button1 event (press, release, or drag).
  * 
  * @param mouseEvent
  *            A MouseEvent to respond to.
  */
 public abstract void onButton1(MouseEvent mouseEvent);
 /**
  * Respond to a button2 event (press, release, or drag).
  * 
  * @param mouseEvent
  *            A MouseEvent to respond to.
  */
 public abstract void onButton2(MouseEvent mouseEvent);
 /**
  * Responed to a button3 event (press, release, or drag).
  * 
  * @param mouseEvent
  *            A MouseEvent to respond to.
  */
 public abstract void onButton3(MouseEvent mouseEvent);
 /**
  * Respond to an elapsed frames event (assuming subclass has set up a wakeup
  * criterion for it).
  * 
  * @param time
  *            A WakeupOnElapsedFrames criterion to respond to.
  */
 public abstract void onElapsedFrames(WakeupOnElapsedFrames timeEvent);

} // //CLASS //NameValue - create a handy name-value pair // //DESCRIPTION //It is frequently handy to have one or more name-value pairs //with which to store named colors, named positions, named textures, //and so forth. Several of the examples use this class. // //AUTHOR //David R. Nadeau / San Diego Supercomputer Center // class NameValue {

 public String name;
 public Object value;
 public NameValue(String n, Object v) {
   name = n;
   value = v;
 }

}


      </source>
   
  
 
  



ExHenge - create a stone-henge like (vaguely) mysterious temple thing

   <source lang="java">

// //CLASS //ExHenge - create a stone-henge like (vaguely) mysterious temple thing // //DESCRIPTION //This example illustrates the use of a few of Java 3D"s lighting //types to create atmospheric lighting to make a structure look //like it is glowing. In particular, we build a central emissive //dome, unaffected by any lighting. Surrounding that dome are a //series of arches that are lit by a one or more of a point //light in the center, directional lights at front-left and //back-right, and two ambient lights. Each of these lights can be //turned on and off via menu items. // //SEE ALSO //Arch //ExAmbientLight //ExDirectionalLight //ExPointLight // //AUTHOR //David R. Nadeau / San Diego Supercomputer Center // // import java.applet.Applet; import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.CheckboxMenuItem; import java.awt.ruponent; import java.awt.Cursor; import java.awt.Frame; import java.awt.Menu; import java.awt.MenuBar; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.io.File; import java.util.Enumeration; import java.util.EventListener; import javax.media.j3d.AmbientLight; 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.DirectionalLight; import javax.media.j3d.GeometryArray; import javax.media.j3d.Group; import javax.media.j3d.ImageComponent; import javax.media.j3d.IndexedQuadArray; import javax.media.j3d.IndexedTriangleStripArray; import javax.media.j3d.Light; import javax.media.j3d.Link; import javax.media.j3d.Material; import javax.media.j3d.PointLight; import javax.media.j3d.Shape3D; import javax.media.j3d.SharedGroup; import javax.media.j3d.Texture; 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.media.j3d.WakeupOnElapsedFrames; import javax.media.j3d.WakeupOr; 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.geometry.Primitive; import com.sun.j3d.utils.image.TextureLoader; import com.sun.j3d.utils.universe.PlatformGeometry; import com.sun.j3d.utils.universe.SimpleUniverse; import com.sun.j3d.utils.universe.Viewer; import com.sun.j3d.utils.universe.ViewingPlatform; public class ExHenge extends Java3DFrame {

 //--------------------------------------------------------------
 //  SCENE CONTENT
 //--------------------------------------------------------------
 //
 //  Nodes (updated via menu)
 //
 private AmbientLight ambient = null;
 private AmbientLight brightAmbient = null;
 private DirectionalLight redDirectional = null;
 private DirectionalLight yellowDirectional = null;
 private PointLight orangePoint = null;
 //
 //  Build scene
 //
 public Group buildScene() {
   // Turn off the example headlight
   setHeadlightEnable(false);
   // Default to walk navigation
   setNavigationType(Walk);
   //
   // Preload the texture images
   //
   if (debug)
     System.err.println("  textures...");
   Texture groundTex = null;
   Texture spurTex = null;
   Texture domeTex = null;
   TextureLoader texLoader = null;
   ImageComponent image = null;
   texLoader = new TextureLoader("mud01.jpg", this);
   image = texLoader.getImage();
   if (image == null)
     System.err.println("Cannot load mud01.jpg texture");
   else {
     groundTex = texLoader.getTexture();
     groundTex.setBoundaryModeS(Texture.WRAP);
     groundTex.setBoundaryModeT(Texture.WRAP);
     groundTex.setMinFilter(Texture.NICEST);
     groundTex.setMagFilter(Texture.NICEST);
     groundTex.setMipMapMode(Texture.BASE_LEVEL);
     groundTex.setEnable(true);
   }
   texLoader = new TextureLoader("stonebrk2.jpg", this);
   image = texLoader.getImage();
   if (image == null)
     System.err.println("Cannot load stonebrk2.jpg texture");
   else {
     spurTex = texLoader.getTexture();
     spurTex.setBoundaryModeS(Texture.WRAP);
     spurTex.setBoundaryModeT(Texture.WRAP);
     spurTex.setMinFilter(Texture.NICEST);
     spurTex.setMagFilter(Texture.NICEST);
     spurTex.setMipMapMode(Texture.BASE_LEVEL);
     spurTex.setEnable(true);
   }
   texLoader = new TextureLoader("fire.jpg", this);
   image = texLoader.getImage();
   if (image == null)
     System.err.println("Cannot load fire.jpg texture");
   else {
     domeTex = texLoader.getTexture();
     domeTex.setBoundaryModeS(Texture.WRAP);
     domeTex.setBoundaryModeT(Texture.WRAP);
     domeTex.setMinFilter(Texture.NICEST);
     domeTex.setMagFilter(Texture.NICEST);
     domeTex.setMipMapMode(Texture.BASE_LEVEL);
     domeTex.setEnable(true);
   }
   //
   // Build some shapes we"ll need
   //
   if (debug)
     System.err.println("  flying buttresses...");
   // Build three types of spurs (flying buttresses)
   Appearance spurApp = new Appearance();
   Material spurMat = new Material();
   spurMat.setAmbientColor(0.6f, 0.6f, 0.6f);
   spurMat.setDiffuseColor(1.0f, 1.0f, 1.0f);
   spurMat.setSpecularColor(0.0f, 0.0f, 0.0f);
   spurApp.setMaterial(spurMat);
   Transform3D tr = new Transform3D();
   tr.setIdentity();
   tr.setScale(new Vector3d(1.0, 4.0, 1.0));
   TextureAttributes spurTexAtt = new TextureAttributes();
   spurTexAtt.setTextureMode(TextureAttributes.MODULATE);
   spurTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
   spurTexAtt.setTextureTransform(tr);
   spurApp.setTextureAttributes(spurTexAtt);
   if (spurTex != null)
     spurApp.setTexture(spurTex);
   Arch spur1 = new Arch(0.0, // start Phi
       1.571, // end Phi
       9, // nPhi
       -0.0982, // start Theta
       0.0982, // end Theta (11.25 degrees)
       2, // nTheta
       2.5, // start radius
       1.0, // end radius
       0.05, // start phi thickness
       0.025, // end phi thickness
       spurApp); // appearance
   Arch spur2 = new Arch(0.0, // start Phi
       1.571, // end Phi
       9, // nPhi
       -0.0982, // start Theta
       0.0982, // end Theta (11.25 degrees)
       2, // nTheta
       1.5, // start radius
       2.0, // end radius
       0.05, // start phi thickness
       0.025, // end phi thickness
       spurApp); // appearance
   Arch spur3 = new Arch(0.0, // start Phi
       1.571, // end Phi
       9, // nPhi
       -0.0982, // start Theta
       0.0982, // end Theta (11.25 degrees)
       2, // nTheta
       1.5, // start radius
       1.0, // end radius
       0.05, // start phi thickness
       0.025, // end phi thickness
       spurApp); // appearance
   Arch spur4 = new Arch(0.0, // start Phi
       1.178, // end Phi
       9, // nPhi
       -0.0982, // start Theta
       0.0982, // end Theta (11.25 degrees)
       2, // nTheta
       4.0, // start radius
       4.0, // end radius
       0.05, // start phi thickness
       0.025, // end phi thickness
       spurApp); // appearance
   // Put each spur into a shared group so we can instance
   // the spurs multiple times
   SharedGroup spur1Group = new SharedGroup();
   spur1Group.addChild(spur1);
   spur1Group.rupile();
   SharedGroup spur2Group = new SharedGroup();
   spur2Group.addChild(spur2);
   spur2Group.rupile();
   SharedGroup spur3Group = new SharedGroup();
   spur3Group.addChild(spur3);
   spur3Group.rupile();
   SharedGroup spur4Group = new SharedGroup();
   spur4Group.addChild(spur4);
   spur4Group.rupile();
   // Build a central dome
   if (debug)
     System.err.println("  central dome...");
   Appearance domeApp = new Appearance();
   // No material needed - we want the dome to glow,
   // so use a REPLACE mode texture only
   TextureAttributes domeTexAtt = new TextureAttributes();
   domeTexAtt.setTextureMode(TextureAttributes.REPLACE);
   domeTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
   domeApp.setTextureAttributes(domeTexAtt);
   if (domeTex != null)
     domeApp.setTexture(domeTex);
   Arch dome = new Arch(0.0, // start Phi
       1.571, // end Phi
       5, // nPhi
       0.0, // start Theta
       2.0 * Math.PI, // end Theta (360 degrees)
       17, // nTheta
       1.0, // start radius
       1.0, // end radius
       0.0, // start phi thickness
       0.0, // end phi thickness
       domeApp); // appearance
   // Build the ground. Use a trick to get better lighting
   // effects by using an elevation grid. The idea is this:
   // for interactive graphics systems, such as those
   // controlled by Java3D, lighting effects are computed only
   // at triangle vertexes. Imagine a big rectangular ground
   // underneath a PointLight (added below). If the
   // PointLight is above the center of the square, in the real
   // world we"d expect a bright spot below it, fading to
   // darkness at the edges of the square. Not so in
   // interactive graphics. Since lighting is only computed
   // at vertexes, and the square"s vertexes are each
   // equidistant from a centered PointLight, all four square
   // coordinates get the same brightness. That brightness
   // is interpolated across the square, giving a *constant*
   // brightness for the entire square! There is no bright
   // spot under the PointLight. So, here"s the trick: use
   // more triangles. Pretty simple. Split the ground under
   // the PointLight into a grid of smaller squares. Each
   // smaller square is shaded using light brightness computed
   // at the square"s vertexes. Squares directly under the
   // PointLight get brighter lighting at their vertexes, and
   // thus they are bright. This gives the desired bright
   // spot under the PointLight. The more squares we use
   // (a denser grid), the more accurate the bright spot and
   // the smoother the lighting gradation from bright directly
   // under the PointLight, to dark at the distant edges. Of
   // course, with more squares, we also get more polygons to
   // draw and a performance slow-down. So there is a
   // tradeoff between lighting quality and drawing speed.
   // For this example, we"ll use a coarse mesh of triangles
   // created using an ElevationGrid shape.
   if (debug)
     System.err.println("  ground...");
   Appearance groundApp = new Appearance();
   Material groundMat = new Material();
   groundMat.setAmbientColor(0.3f, 0.3f, 0.3f);
   groundMat.setDiffuseColor(0.7f, 0.7f, 0.7f);
   groundMat.setSpecularColor(0.0f, 0.0f, 0.0f);
   groundApp.setMaterial(groundMat);
   tr = new Transform3D();
   tr.setScale(new Vector3d(8.0, 8.0, 1.0));
   TextureAttributes groundTexAtt = new TextureAttributes();
   groundTexAtt.setTextureMode(TextureAttributes.MODULATE);
   groundTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
   groundTexAtt.setTextureTransform(tr);
   groundApp.setTextureAttributes(groundTexAtt);
   if (groundTex != null)
     groundApp.setTexture(groundTex);
   ElevationGrid ground = new ElevationGrid(11, // X dimension
       11, // Z dimension
       2.0f, // X spacing
       2.0f, // Z spacing
       // Automatically use zero heights
       groundApp); // Appearance
   //
   // Build the scene using the shapes above. Place everything
   // withing a TransformGroup.
   //
   // Build the scene root
   TransformGroup scene = new TransformGroup();
   tr = new Transform3D();
   tr.setTranslation(new Vector3f(0.0f, -1.6f, 0.0f));
   scene.setTransform(tr);
   // Create influencing bounds
   BoundingSphere worldBounds = new BoundingSphere(new Point3d(0.0, 0.0,
       0.0), // Center
       1000.0); // Extent
   // General Ambient light
   ambient = new AmbientLight();
   ambient.setEnable(ambientOnOff);
   ambient.setColor(new Color3f(0.3f, 0.3f, 0.3f));
   ambient.setCapability(AmbientLight.ALLOW_STATE_WRITE);
   ambient.setInfluencingBounds(worldBounds);
   scene.addChild(ambient);
   // Bright Ambient light
   brightAmbient = new AmbientLight();
   brightAmbient.setEnable(brightAmbientOnOff);
   brightAmbient.setColor(new Color3f(1.0f, 1.0f, 1.0f));
   brightAmbient.setCapability(AmbientLight.ALLOW_STATE_WRITE);
   brightAmbient.setInfluencingBounds(worldBounds);
   scene.addChild(brightAmbient);
   // Red directional light
   redDirectional = new DirectionalLight();
   redDirectional.setEnable(redDirectionalOnOff);
   redDirectional.setColor(new Color3f(1.0f, 0.0f, 0.0f));
   redDirectional.setDirection(new Vector3f(1.0f, -0.5f, -0.5f));
   redDirectional.setCapability(AmbientLight.ALLOW_STATE_WRITE);
   redDirectional.setInfluencingBounds(worldBounds);
   scene.addChild(redDirectional);
   // Yellow directional light
   yellowDirectional = new DirectionalLight();
   yellowDirectional.setEnable(yellowDirectionalOnOff);
   yellowDirectional.setColor(new Color3f(1.0f, 0.8f, 0.0f));
   yellowDirectional.setDirection(new Vector3f(-1.0f, 0.5f, 1.0f));
   yellowDirectional.setCapability(AmbientLight.ALLOW_STATE_WRITE);
   yellowDirectional.setInfluencingBounds(worldBounds);
   scene.addChild(yellowDirectional);
   // Orange point light
   orangePoint = new PointLight();
   orangePoint.setEnable(orangePointOnOff);
   orangePoint.setColor(new Color3f(1.0f, 0.5f, 0.0f));
   orangePoint.setPosition(new Point3f(0.0f, 0.5f, 0.0f));
   orangePoint.setCapability(AmbientLight.ALLOW_STATE_WRITE);
   orangePoint.setInfluencingBounds(worldBounds);
   scene.addChild(orangePoint);
   // Ground
   scene.addChild(ground);
   // Dome
   scene.addChild(dome);
   // Spur 1"s
   Group g = buildRing(spur1Group);
   scene.addChild(g);
   // Spur 2"s
   TransformGroup tg = new TransformGroup();
   tr = new Transform3D();
   tr.rotY(0.3927);
   tg.setTransform(tr);
   g = buildRing(spur2Group);
   tg.addChild(g);
   scene.addChild(tg);
   // Spur 3"s
   g = buildRing(spur3Group);
   scene.addChild(g);
   // Spur 4"s
   tg = new TransformGroup();
   tg.setTransform(tr);
   g = buildRing(spur4Group);
   tg.addChild(g);
   scene.addChild(tg);
   return scene;
 }
 //
 //  Build a ring of shapes, each shape contained in a given
 //  shared group
 //
 public Group buildRing(SharedGroup sg) {
   Group g = new Group();
   g.addChild(new Link(sg)); // 0 degrees
   TransformGroup tg = new TransformGroup();
   Transform3D tr = new Transform3D();
   tr.rotY(0.785); // 45 degrees
   tg.setTransform(tr);
   tg.addChild(new Link(sg));
   g.addChild(tg);
   tg = new TransformGroup();
   tr = new Transform3D();
   tr.rotY(-0.785); // -45 degrees
   tg.setTransform(tr);
   tg.addChild(new Link(sg));
   g.addChild(tg);
   tg = new TransformGroup();
   tr = new Transform3D();
   tr.rotY(1.571); // 90 degrees
   tg.setTransform(tr);
   tg.addChild(new Link(sg));
   g.addChild(tg);
   tg = new TransformGroup();
   tr = new Transform3D();
   tr.rotY(-1.571); // -90 degrees
   tg.setTransform(tr);
   tg.addChild(new Link(sg));
   g.addChild(tg);
   tg = new TransformGroup();
   tr = new Transform3D();
   tr.rotY(2.356); // 135 degrees
   tg.setTransform(tr);
   tg.addChild(new Link(sg));
   g.addChild(tg);
   tg = new TransformGroup();
   tr = new Transform3D();
   tr.rotY(-2.356); // -135 degrees
   tg.setTransform(tr);
   tg.addChild(new Link(sg));
   g.addChild(tg);
   tg = new TransformGroup();
   tr = new Transform3D();
   tr.rotY(Math.PI); // 180 degrees
   tg.setTransform(tr);
   tg.addChild(new Link(sg));
   g.addChild(tg);
   return g;
 }
 //--------------------------------------------------------------
 //  USER INTERFACE
 //--------------------------------------------------------------
 //
 //  Main
 //
 public static void main(String[] args) {
   ExHenge ex = new ExHenge();
   ex.initialize(args);
   ex.buildUniverse();
   ex.showFrame();
 }
 //  On/off choices
 private boolean ambientOnOff = true;
 private boolean brightAmbientOnOff = false;
 private boolean redDirectionalOnOff = false;
 private boolean yellowDirectionalOnOff = false;
 private boolean orangePointOnOff = true;
 private CheckboxMenuItem ambientOnOffMenu;
 private CheckboxMenuItem brightAmbientOnOffMenu;
 private CheckboxMenuItem redDirectionalOnOffMenu;
 private CheckboxMenuItem yellowDirectionalOnOffMenu;
 private CheckboxMenuItem orangePointOnOffMenu;
 //
 //  Initialize the GUI (application and applet)
 //
 public void initialize(String[] args) {
   // Initialize the window, menubar, etc.
   super.initialize(args);
   exampleFrame.setTitle("Java 3D ExHenge Example");
   //
   //  Add a menubar menu to change parameters
   //    Dim ambient light
   //    Bright ambient light
   //    Red directional light
   //    Yellow directional light
   //    Orange point light
   //
   Menu m = new Menu("Lights");
   ambientOnOffMenu = new CheckboxMenuItem("Dim ambient light",
       ambientOnOff);
   ambientOnOffMenu.addItemListener(this);
   m.add(ambientOnOffMenu);
   brightAmbientOnOffMenu = new CheckboxMenuItem("Bright ambient light",
       brightAmbientOnOff);
   brightAmbientOnOffMenu.addItemListener(this);
   m.add(brightAmbientOnOffMenu);
   redDirectionalOnOffMenu = new CheckboxMenuItem("Red directional light",
       redDirectionalOnOff);
   redDirectionalOnOffMenu.addItemListener(this);
   m.add(redDirectionalOnOffMenu);
   yellowDirectionalOnOffMenu = new CheckboxMenuItem(
       "Yellow directional light", yellowDirectionalOnOff);
   yellowDirectionalOnOffMenu.addItemListener(this);
   m.add(yellowDirectionalOnOffMenu);
   orangePointOnOffMenu = new CheckboxMenuItem("Orange point light",
       orangePointOnOff);
   orangePointOnOffMenu.addItemListener(this);
   m.add(orangePointOnOffMenu);
   exampleMenuBar.add(m);
 }
 //
 //  Handle checkboxes
 //
 public void itemStateChanged(ItemEvent event) {
   Object src = event.getSource();
   if (src == ambientOnOffMenu) {
     ambientOnOff = ambientOnOffMenu.getState();
     ambient.setEnable(ambientOnOff);
     return;
   }
   if (src == brightAmbientOnOffMenu) {
     brightAmbientOnOff = brightAmbientOnOffMenu.getState();
     brightAmbient.setEnable(brightAmbientOnOff);
     return;
   }
   if (src == redDirectionalOnOffMenu) {
     redDirectionalOnOff = redDirectionalOnOffMenu.getState();
     redDirectional.setEnable(redDirectionalOnOff);
     return;
   }
   if (src == yellowDirectionalOnOffMenu) {
     yellowDirectionalOnOff = yellowDirectionalOnOffMenu.getState();
     yellowDirectional.setEnable(yellowDirectionalOnOff);
     return;
   }
   if (src == orangePointOnOffMenu) {
     orangePointOnOff = orangePointOnOffMenu.getState();
     orangePoint.setEnable(orangePointOnOff);
     return;
   }
   // Handle all other checkboxes
   super.itemStateChanged(event);
 }

} // //CLASS //ElevationGrid - a 3D terrain grid built from a list of heights // //DESCRIPTION //This class creates a 3D terrain on a grid whose X and Z dimensions, //and row/column spacing are parameters, along with a list of heights //(elevations), one per grid row/column pair. // class ElevationGrid extends Primitive {

 // Parameters
 protected int xDimension = 0, zDimension = 0;
 protected double xSpacing = 0.0, zSpacing = 0.0;
 protected double[] heights = null;
 // 3D nodes
 private Appearance mainAppearance = null;
 private Shape3D shape = null;
 private IndexedTriangleStripArray tristrip = null;
 //
 //  Construct an elevation grid
 //
 public ElevationGrid() {
   xDimension = 2;
   zDimension = 2;
   xSpacing = 1.0;
   zSpacing = 1.0;
   mainAppearance = null;
   zeroHeights();
   rebuild();
 }
 public ElevationGrid(int xDim, int zDim) {
   xDimension = xDim;
   zDimension = zDim;
   xSpacing = 1.0;
   zSpacing = 1.0;
   mainAppearance = null;
   zeroHeights();
   rebuild();
 }
 public ElevationGrid(int xDim, int zDim, Appearance app) {
   xDimension = xDim;
   zDimension = zDim;
   xSpacing = 1.0;
   zSpacing = 1.0;
   mainAppearance = app;
   zeroHeights();
   rebuild();
 }
 public ElevationGrid(int xDim, int zDim, double xSpace, double zSpace) {
   xDimension = xDim;
   zDimension = zDim;
   xSpacing = xSpace;
   zSpacing = zSpace;
   mainAppearance = null;
   zeroHeights();
   rebuild();
 }
 public ElevationGrid(int xDim, int zDim, double xSpace, double zSpace,
     Appearance app) {
   xDimension = xDim;
   zDimension = zDim;
   xSpacing = xSpace;
   zSpacing = zSpace;
   mainAppearance = app;
   zeroHeights();
   rebuild();
 }
 public ElevationGrid(int xDim, int zDim, double[] h) {
   this(xDim, zDim, 1.0, 1.0, h, null);
 }
 public ElevationGrid(int xDim, int zDim, double[] h, Appearance app) {
   this(xDim, zDim, 1.0, 1.0, h, app);
 }
 public ElevationGrid(int xDim, int zDim, double xSpace, double zSpace,
     double[] h) {
   this(xDim, zDim, xSpace, zSpace, h, null);
 }
 public ElevationGrid(int xDim, int zDim, double xSpace, double zSpace,
     double[] h, Appearance app) {
   xDimension = xDim;
   zDimension = zDim;
   xSpacing = xSpace;
   zSpacing = zSpace;
   mainAppearance = app;
   if (h == null)
     zeroHeights();
   else {
     heights = new double[h.length];
     for (int i = 0; i < h.length; i++)
       heights[i] = h[i];
   }
   rebuild();
 }
 private void zeroHeights() {
   int n = xDimension * zDimension;
   heights = new double[n];
   for (int i = 0; i < n; i++)
     heights[i] = 0.0;
 }
 private void rebuild() {
   // Build a shape
   if (shape == null) {
     shape = new Shape3D();
     shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
     shape.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
     shape.setAppearance(mainAppearance);
     addChild(shape);
   } else {
     shape.setAppearance(mainAppearance);
   }
   if (xDimension < 2 || zDimension < 2 || heights == null
       || heights.length < 4) {
     tristrip = null;
     shape.setGeometry(null);
     return;
   }
   // Create a list of coordinates, one per grid row/column
   double[] coordinates = new double[xDimension * zDimension * 3];
   double x, z;
   int n = 0, k = 0;
   z = ((double) (zDimension - 1)) * zSpacing / 2.0; // start at front edge
   for (int i = 0; i < zDimension; i++) {
     x = -((double) (xDimension - 1)) * xSpacing / 2.0;// start at left
     // edge
     for (int j = 0; j < xDimension; j++) {
       coordinates[n++] = x;
       coordinates[n++] = heights[k++];
       coordinates[n++] = z;
       x += xSpacing;
     }
     z -= zSpacing;
   }
   // Create a list of normals, one per grid row/column
   float[] normals = new float[xDimension * zDimension * 3];
   Vector3f one = new Vector3f(0.0f, 0.0f, 0.0f);
   Vector3f two = new Vector3f(0.0f, 0.0f, 0.0f);
   Vector3f norm = new Vector3f(0.0f, 0.0f, 0.0f);
   n = 0;
   k = 0;
   for (int i = 0; i < zDimension - 1; i++) {
     for (int j = 0; j < xDimension - 1; j++) {
       // Vector to right in X
       one.set((float) xSpacing,
           (float) (heights[k + 1] - heights[k]), 0.0f);
       // Vector back in Z
       two.set(0.0f, (float) (heights[k + xDimension] - heights[k]),
           (float) -zSpacing);
       // Cross them to get the normal
       norm.cross(one, two);
       normals[n++] = norm.x;
       normals[n++] = norm.y;
       normals[n++] = norm.z;
       k++;
     }
     // Last normal in row is a copy of the previous one
     normals[n] = normals[n - 3]; // X
     normals[n + 1] = normals[n - 2]; // Y
     normals[n + 2] = normals[n - 1]; // Z
     n += 3;
     k++;
   }
   // Last row of normals is a copy of the previous row
   for (int j = 0; j < xDimension; j++) {
     normals[n] = normals[n - xDimension * 3]; // X
     normals[n + 1] = normals[n - xDimension * 3 + 1]; // Y
     normals[n + 2] = normals[n - xDimension * 3 + 2]; // Z
     n += 3;
   }
   // Create a list of texture coordinates, one per grid row/column
   float[] texcoordinates = new float[xDimension * zDimension * 2];
   float deltaS = 1.0f / (float) (xDimension - 1);
   float deltaT = 1.0f / (float) (zDimension - 1);
   float s = 0.0f;
   float t = 0.0f;
   n = 0;
   for (int i = 0; i < zDimension; i++) {
     s = 0.0f;
     for (int j = 0; j < xDimension; j++) {
       texcoordinates[n++] = s;
       texcoordinates[n++] = t;
       s += deltaS;
     }
     t += deltaT;
   }
   // Create a list of triangle strip indexes. Each strip goes
   // down one row (X direction) of the elevation grid.
   int[] indexes = new int[xDimension * (zDimension - 1) * 2];
   int[] stripCounts = new int[zDimension - 1];
   n = 0;
   k = 0;
   for (int i = 0; i < zDimension - 1; i++) {
     stripCounts[i] = xDimension * 2;
     for (int j = 0; j < xDimension; j++) {
       indexes[n++] = k + xDimension;
       indexes[n++] = k;
       k++;
     }
   }
   // Create geometry for collection of triangle strips, one
   // strip per row of the elevation grid
   tristrip = new IndexedTriangleStripArray(coordinates.length,
       GeometryArray.COORDINATES | GeometryArray.NORMALS
           | GeometryArray.TEXTURE_COORDINATE_2, indexes.length,
       stripCounts);
   tristrip.setCoordinates(0, coordinates);
   tristrip.setNormals(0, normals);
   tristrip.setTextureCoordinates(0, texcoordinates);
   tristrip.setCoordinateIndices(0, indexes);
   tristrip.setNormalIndices(0, indexes);
   tristrip.setTextureCoordinateIndices(0, indexes);
   // Set the geometry for the shape
   shape.setGeometry(tristrip);
 }
 //
 //  Control the appearance
 //
 public void setAppearance(Appearance app) {
   mainAppearance = app;
   if (shape != null)
     shape.setAppearance(mainAppearance);
 }
 //
 //  Control grid parameters
 //
 public void setHeights(double[] h) {
   if (h == null)
     zeroHeights();
   else {
     heights = new double[h.length];
     for (int i = 0; i < h.length; i++)
       heights[i] = h[i];
   }
   rebuild();
 }
 public double[] getHeights() {
   return heights;
 }
 public void setXDimension(int xDim) {
   xDimension = xDim;
   rebuild();
 }
 public int getXDimension() {
   return xDimension;
 }
 public void setZDimension(int zDim) {
   zDimension = zDim;
   rebuild();
 }
 public int getZDimension() {
   return zDimension;
 }
 public void setXSpacing(double xSpace) {
   xSpacing = xSpace;
   rebuild();
 }
 public double getXSpacing() {
   return xSpacing;
 }
 public void setZSpacing(double zSpace) {
   zSpacing = zSpace;
   rebuild();
 }
 public double getZSpacing() {
   return zSpacing;
 }
 //
 //  Provide info on the shape and geometry
 //
 public Shape3D getShape(int partid) {
   return shape;
 }
 public int getNumTriangles() {
   return xDimension * zDimension * 2;
 }
 public int getNumVertices() {
   return xDimension * zDimension;
 }
 /*
  * (non-Javadoc)
  * 
  * @see com.sun.j3d.utils.geometry.Primitive#getAppearance(int)
  */
 public Appearance getAppearance(int arg0) {
   // TODO Auto-generated method stub
   return null;
 }

} // //CLASS //Arch - generalized arch // //DESCRIPTION //This class builds a generalized arch where incoming parameters //specify the angle range in theta (around the equator of a sphere), //the angle range in phi (north-south), the number of subdivisions //in theta and phi, and optionally radii and outer-to-inner wall //thickness variations as phi varies from its starting value to //its ending value. If the thicknesses are 0.0, then only an outer //surface is created. // //Using this class, you can create spheres with or without inner //surfaces, hemisphers, quarter spheres, and arches stretched or //compressed vertically. // //This is probably not as general as it could be, but it was enough //for the purposes at hand. // //SEE ALSO //ModernFire // //AUTHOR //David R. Nadeau / San Diego Supercomputer Center // // class Arch extends Group {

 // The shape
 private Shape3D arch = null;
 // Construct an arch
 public Arch() {
   // Default to a sphere
   this(0.0, Math.PI / 2.0, 9, 0.0, Math.PI, 17, 1.0, 1.0, 0.0, 0.0,
       new Appearance());
 }
 public Arch(Appearance app) {
   // Default to a sphere
   this(0.0, Math.PI / 2.0, 9, 0.0, Math.PI, 17, 1.0, 1.0, 0.0, 0.0, app);
 }
 public Arch(double startPhi, double endPhi, int nPhi, double startTheta,
     double endTheta, int nTheta, Appearance app) {
   // Default to constant radius, no thickness
   this(startPhi, endPhi, nPhi, startTheta, endTheta, nTheta, 1.0, 1.0,
       0.0, 0.0, app);
 }
 public Arch(double startPhi, double endPhi, int nPhi, double startTheta,
     double endTheta, int nTheta, double startPhiRadius,
     double endPhiRadius, double startPhiThickness,
     double endPhiThickness, Appearance app) {
   double theta, phi, radius, radius2, thickness;
   double x, y, z;
   double[] xyz = new double[3];
   float[] norm = new float[3];
   float[] tex = new float[3];
   // Compute some values for our looping
   double deltaTheta = (endTheta - startTheta) / (double) (nTheta - 1);
   double deltaPhi = (endPhi - startPhi) / (double) (nPhi - 1);
   double deltaTexX = 1.0 / (double) (nTheta - 1);
   double deltaTexY = 1.0 / (double) (nPhi - 1);
   double deltaPhiRadius = (endPhiRadius - startPhiRadius)
       / (double) (nPhi - 1);
   double deltaPhiThickness = (endPhiThickness - startPhiThickness)
       / (double) (nPhi - 1);
   boolean doThickness = true;
   if (startPhiThickness == 0.0 && endPhiThickness == 0.0)
     doThickness = false;
   //  Create geometry
   int vertexCount = nTheta * nPhi;
   if (doThickness)
     vertexCount *= 2;
   int indexCount = (nTheta - 1) * (nPhi - 1) * 4; // Outer surface
   if (doThickness) {
     indexCount *= 2; // plus inner surface
     indexCount += (nPhi - 1) * 4 * 2; // plus left & right edges
   }
   IndexedQuadArray polys = new IndexedQuadArray(vertexCount,
       GeometryArray.COORDINATES | GeometryArray.NORMALS
           | GeometryArray.TEXTURE_COORDINATE_2, indexCount);
   //
   //  Compute coordinates, normals, and texture coordinates
   //
   theta = startTheta;
   tex[0] = 0.0f;
   int index = 0;
   for (int i = 0; i < nTheta; i++) {
     phi = startPhi;
     radius = startPhiRadius;
     thickness = startPhiThickness;
     tex[1] = 0.0f;
     for (int j = 0; j < nPhi; j++) {
       norm[0] = (float) (Math.cos(phi) * Math.cos(theta));
       norm[1] = (float) (Math.sin(phi));
       norm[2] = (float) (-Math.cos(phi) * Math.sin(theta));
       xyz[0] = radius * norm[0];
       xyz[1] = radius * norm[1];
       xyz[2] = radius * norm[2];
       polys.setCoordinate(index, xyz);
       polys.setNormal(index, norm);
       polys.setTextureCoordinate(index, tex);
       index++;
       if (doThickness) {
         radius2 = radius - thickness;
         xyz[0] = radius2 * norm[0];
         xyz[1] = radius2 * norm[1];
         xyz[2] = radius2 * norm[2];
         norm[0] *= -1.0f;
         norm[1] *= -1.0f;
         norm[2] *= -1.0f;
         polys.setCoordinate(index, xyz);
         polys.setNormal(index, norm);
         polys.setTextureCoordinate(index, tex);
         index++;
       }
       phi += deltaPhi;
       radius += deltaPhiRadius;
       thickness += deltaPhiThickness;
       tex[1] += deltaTexY;
     }
     theta += deltaTheta;
     tex[0] += deltaTexX;
   }
   //
   //  Compute coordinate indexes
   //  (also used as normal and texture indexes)
   //
   index = 0;
   int phiRow = nPhi;
   int phiCol = 1;
   if (doThickness) {
     phiRow += nPhi;
     phiCol += 1;
   }
   int[] indices = new int[indexCount];
   // Outer surface
   int n;
   for (int i = 0; i < nTheta - 1; i++) {
     for (int j = 0; j < nPhi - 1; j++) {
       n = i * phiRow + j * phiCol;
       indices[index + 0] = n;
       indices[index + 1] = n + phiRow;
       indices[index + 2] = n + phiRow + phiCol;
       indices[index + 3] = n + phiCol;
       index += 4;
     }
   }
   // Inner surface
   if (doThickness) {
     for (int i = 0; i < nTheta - 1; i++) {
       for (int j = 0; j < nPhi - 1; j++) {
         n = i * phiRow + j * phiCol;
         indices[index + 0] = n + 1;
         indices[index + 1] = n + phiCol + 1;
         indices[index + 2] = n + phiRow + phiCol + 1;
         indices[index + 3] = n + phiRow + 1;
         index += 4;
       }
     }
   }
   // Edges
   if (doThickness) {
     for (int j = 0; j < nPhi - 1; j++) {
       n = j * phiCol;
       indices[index + 0] = n;
       indices[index + 1] = n + phiCol;
       indices[index + 2] = n + phiCol + 1;
       indices[index + 3] = n + 1;
       index += 4;
     }
     for (int j = 0; j < nPhi - 1; j++) {
       n = (nTheta - 1) * phiRow + j * phiCol;
       indices[index + 0] = n;
       indices[index + 1] = n + 1;
       indices[index + 2] = n + phiCol + 1;
       indices[index + 3] = n + phiCol;
       index += 4;
     }
   }
   polys.setCoordinateIndices(0, indices);
   polys.setNormalIndices(0, indices);
   polys.setTextureCoordinateIndices(0, indices);
   //
   //  Build a shape
   //
   arch = new Shape3D();
   arch.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
   arch.setGeometry(polys);
   arch.setAppearance(app);
   addChild(arch);
 }
 public void setAppearance(Appearance app) {
   if (arch != null)
     arch.setAppearance(app);
 }

} /**

* The Example class is a base class extended by example applications. The class
* provides basic features to create a top-level frame, add a menubar and
* Canvas3D, build the universe, set up "examine" and "walk" style navigation
* behaviors, and provide hooks so that subclasses can add 3D content to the
* example"s universe.
* <P>
* Using this Example class simplifies the construction of example applications,
* enabling the author to focus upon 3D content and not the busywork of creating
* windows, menus, and universes.
* 
* @version 1.0, 98/04/16
* @author David R. Nadeau, San Diego Supercomputer Center
*/

class Java3DFrame extends Applet implements WindowListener, ActionListener,

   ItemListener, CheckboxMenuListener {
 //  Navigation types
 public final static int Walk = 0;
 public final static int Examine = 1;
 //  Should the scene be compiled?
 private boolean shouldCompile = true;
 //  GUI objects for our subclasses
 protected Java3DFrame example = null;
 protected Frame exampleFrame = null;
 protected MenuBar exampleMenuBar = null;
 protected Canvas3D exampleCanvas = null;
 protected TransformGroup exampleViewTransform = null;
 protected TransformGroup exampleSceneTransform = null;
 protected boolean debug = false;
 //  Private GUI objects and state
 private boolean headlightOnOff = true;
 private int navigationType = Examine;
 private CheckboxMenuItem headlightMenuItem = null;
 private CheckboxMenuItem walkMenuItem = null;
 private CheckboxMenuItem examineMenuItem = null;
 private DirectionalLight headlight = null;
 private ExamineViewerBehavior examineBehavior = null;
 private WalkViewerBehavior walkBehavior = null;
 //--------------------------------------------------------------
 //  ADMINISTRATION
 //--------------------------------------------------------------
 /**
  * The main program entry point when invoked as an application. Each example
  * application that extends this class must define their own main.
  * 
  * @param args
  *            a String array of command-line arguments
  */
 public static void main(String[] args) {
   Java3DFrame ex = new Java3DFrame();
   ex.initialize(args);
   ex.buildUniverse();
   ex.showFrame();
 }
 /**
  * Constructs a new Example object.
  * 
  * @return a new Example that draws no 3D content
  */
 public Java3DFrame() {
   // Do nothing
 }
 /**
  * Initializes the application when invoked as an applet.
  */
 public void init() {
   // Collect properties into String array
   String[] args = new String[2];
   // NOTE: to be done still...
   this.initialize(args);
   this.buildUniverse();
   this.showFrame();
   // NOTE: add something to the browser page?
 }
 /**
  * Initializes the Example by parsing command-line arguments, building an
  * AWT Frame, constructing a menubar, and creating the 3D canvas.
  * 
  * @param args
  *            a String array of command-line arguments
  */
 protected void initialize(String[] args) {
   example = this;
   // Parse incoming arguments
   parseArgs(args);
   // Build the frame
   if (debug)
     System.err.println("Building GUI...");
   exampleFrame = new Frame();
   exampleFrame.setSize(640, 480);
   exampleFrame.setTitle("Java 3D Example");
   exampleFrame.setLayout(new BorderLayout());
   // Set up a close behavior
   exampleFrame.addWindowListener(this);
   // Create a canvas
   exampleCanvas = new Canvas3D(null);
   exampleCanvas.setSize(630, 460);
   exampleFrame.add("Center", exampleCanvas);
   // Build the menubar
   exampleMenuBar = this.buildMenuBar();
   exampleFrame.setMenuBar(exampleMenuBar);
   // Pack
   exampleFrame.pack();
   exampleFrame.validate();
   //    exampleFrame.setVisible( true );
 }
 /**
  * Parses incoming command-line arguments. Applications that subclass this
  * class may override this method to support their own command-line
  * arguments.
  * 
  * @param args
  *            a String array of command-line arguments
  */
 protected void parseArgs(String[] args) {
   for (int i = 0; i < args.length; i++) {
     if (args[i].equals("-d"))
       debug = true;
   }
 }
 //--------------------------------------------------------------
 //  SCENE CONTENT
 //--------------------------------------------------------------
 /**
  * Builds the 3D universe by constructing a virtual universe (via
  * SimpleUniverse), a view platform (via SimpleUniverse), and a view (via
  * SimpleUniverse). A headlight is added and a set of behaviors initialized
  * to handle navigation types.
  */
 protected void buildUniverse() {
   //
   //  Create a SimpleUniverse object, which builds:
   //
   //    - a Locale using the given hi-res coordinate origin
   //
   //    - a ViewingPlatform which in turn builds:
   //          - a MultiTransformGroup with which to move the
   //            the ViewPlatform about
   //
   //          - a ViewPlatform to hold the view
   //
   //          - a BranchGroup to hold avatar geometry (if any)
   //
   //          - a BranchGroup to hold view platform
   //            geometry (if any)
   //
   //    - a Viewer which in turn builds:
   //          - a PhysicalBody which characterizes the user"s
   //            viewing preferences and abilities
   //
   //          - a PhysicalEnvironment which characterizes the
   //            user"s rendering hardware and software
   //
   //          - a JavaSoundMixer which initializes sound
   //            support within the 3D environment
   //
   //          - a View which renders the scene into a Canvas3D
   //
   //  All of these actions could be done explicitly, but
   //  using the SimpleUniverse utilities simplifies the code.
   //
   if (debug)
     System.err.println("Building scene graph...");
   SimpleUniverse universe = new SimpleUniverse(null, // Hi-res coordinate
       // for the origin -
       // use default
       1, // Number of transforms in MultiTransformGroup
       exampleCanvas, // Canvas3D into which to draw
       null); // URL for user configuration file - use defaults
   //
   //  Get the viewer and create an audio device so that
   //  sound will be enabled in this content.
   //
   Viewer viewer = universe.getViewer();
   viewer.createAudioDevice();
   //
   //  Get the viewing platform created by SimpleUniverse.
   //  From that platform, get the inner-most TransformGroup
   //  in the MultiTransformGroup. That inner-most group
   //  contains the ViewPlatform. It is this inner-most
   //  TransformGroup we need in order to:
   //
   //    - add a "headlight" that always aims forward from
   //       the viewer
   //
   //    - change the viewing direction in a "walk" style
   //
   //  The inner-most TransformGroup"s transform will be
   //  changed by the walk behavior (when enabled).
   //
   ViewingPlatform viewingPlatform = universe.getViewingPlatform();
   exampleViewTransform = viewingPlatform.getViewPlatformTransform();
   //
   //  Create a "headlight" as a forward-facing directional light.
   //  Set the light"s bounds to huge. Since we want the light
   //  on the viewer"s "head", we need the light within the
   //  TransformGroup containing the ViewPlatform. The
   //  ViewingPlatform class creates a handy hook to do this
   //  called "platform geometry". The PlatformGeometry class is
   //  subclassed off of BranchGroup, and is intended to contain
   //  a description of the 3D platform itself... PLUS a headlight!
   //  So, to add the headlight, create a new PlatformGeometry group,
   //  add the light to it, then add that platform geometry to the
   //  ViewingPlatform.
   //
   BoundingSphere allBounds = new BoundingSphere(
       new Point3d(0.0, 0.0, 0.0), 100000.0);
   PlatformGeometry pg = new PlatformGeometry();
   headlight = new DirectionalLight();
   headlight.setColor(White);
   headlight.setDirection(new Vector3f(0.0f, 0.0f, -1.0f));
   headlight.setInfluencingBounds(allBounds);
   headlight.setCapability(Light.ALLOW_STATE_WRITE);
   pg.addChild(headlight);
   viewingPlatform.setPlatformGeometry(pg);
   //
   //  Create the 3D content BranchGroup, containing:
   //
   //    - a TransformGroup who"s transform the examine behavior
   //      will change (when enabled).
   //
   //    - 3D geometry to view
   //
   // Build the scene root
   BranchGroup sceneRoot = new BranchGroup();
   // Build a transform that we can modify
   exampleSceneTransform = new TransformGroup();
   exampleSceneTransform
       .setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   exampleSceneTransform
       .setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   exampleSceneTransform.setCapability(Group.ALLOW_CHILDREN_EXTEND);
   //
   //  Build the scene, add it to the transform, and add
   //  the transform to the scene root
   //
   if (debug)
     System.err.println("  scene...");
   Group scene = this.buildScene();
   exampleSceneTransform.addChild(scene);
   sceneRoot.addChild(exampleSceneTransform);
   //
   //  Create a pair of behaviors to implement two navigation
   //  types:
   //
   //    - "examine": a style where mouse drags rotate about
   //      the scene"s origin as if it is an object under
   //      examination. This is similar to the "Examine"
   //      navigation type used by VRML browsers.
   //
   //    - "walk": a style where mouse drags rotate about
   //      the viewer"s center as if the viewer is turning
   //      about to look at a scene they are in. This is
   //      similar to the "Walk" navigation type used by
   //      VRML browsers.
   //
   //  Aim the examine behavior at the scene"s TransformGroup
   //  and add the behavior to the scene root.
   //
   //  Aim the walk behavior at the viewing platform"s
   //  TransformGroup and add the behavior to the scene root.
   //
   //  Enable one (and only one!) of the two behaviors
   //  depending upon the current navigation type.
   //
   examineBehavior = new ExamineViewerBehavior(exampleSceneTransform, // Transform
       // gorup
       // to
       // modify
       exampleFrame); // Parent frame for cusor changes
   examineBehavior.setSchedulingBounds(allBounds);
   sceneRoot.addChild(examineBehavior);
   walkBehavior = new WalkViewerBehavior(exampleViewTransform, // Transform
       // group to
       // modify
       exampleFrame); // Parent frame for cusor changes
   walkBehavior.setSchedulingBounds(allBounds);
   sceneRoot.addChild(walkBehavior);
   if (navigationType == Walk) {
     examineBehavior.setEnable(false);
     walkBehavior.setEnable(true);
   } else {
     examineBehavior.setEnable(true);
     walkBehavior.setEnable(false);
   }
   //
   //  Compile the scene branch group and add it to the
   //  SimpleUniverse.
   //
   if (shouldCompile)
     sceneRoot.rupile();
   universe.addBranchGraph(sceneRoot);
   reset();
 }
 /**
  * Builds the scene. Example application subclasses should replace this
  * method with their own method to build 3D content.
  * 
  * @return a Group containing 3D content to display
  */
 public Group buildScene() {
   // Build the scene group containing nothing
   Group scene = new Group();
   return scene;
 }
 //--------------------------------------------------------------
 //  SET/GET METHODS
 //--------------------------------------------------------------
 /**
  * Sets the headlight on/off state. The headlight faces forward in the
  * direction the viewer is facing. Example applications that add their own
  * lights will typically turn the headlight off. A standard menu item
  * enables the headlight to be turned on and off via user control.
  * 
  * @param onOff
  *            a boolean turning the light on (true) or off (false)
  */
 public void setHeadlightEnable(boolean onOff) {
   headlightOnOff = onOff;
   if (headlight != null)
     headlight.setEnable(headlightOnOff);
   if (headlightMenuItem != null)
     headlightMenuItem.setState(headlightOnOff);
 }
 /**
  * Gets the headlight on/off state.
  * 
  * @return a boolean indicating if the headlight is on or off
  */
 public boolean getHeadlightEnable() {
   return headlightOnOff;
 }
 /**
  * Sets the navigation type to be either Examine or Walk. The Examine
  * navigation type sets up behaviors that use mouse drags to rotate and
  * translate scene content as if it is an object held at arm"s length and
  * under examination. The Walk navigation type uses mouse drags to rotate
  * and translate the viewer as if they are walking through the content. The
  * Examine type is the default.
  * 
  * @param nav
  *            either Walk or Examine
  */
 public void setNavigationType(int nav) {
   if (nav == Walk) {
     navigationType = Walk;
     if (walkMenuItem != null)
       walkMenuItem.setState(true);
     if (examineMenuItem != null)
       examineMenuItem.setState(false);
     if (walkBehavior != null)
       walkBehavior.setEnable(true);
     if (examineBehavior != null)
       examineBehavior.setEnable(false);
   } else {
     navigationType = Examine;
     if (walkMenuItem != null)
       walkMenuItem.setState(false);
     if (examineMenuItem != null)
       examineMenuItem.setState(true);
     if (walkBehavior != null)
       walkBehavior.setEnable(false);
     if (examineBehavior != null)
       examineBehavior.setEnable(true);
   }
 }
 /**
  * Gets the current navigation type, returning either Walk or Examine.
  * 
  * @return either Walk or Examine
  */
 public int getNavigationType() {
   return navigationType;
 }
 /**
  * Sets whether the scene graph should be compiled or not. Normally this is
  * always a good idea. For some example applications that use this Example
  * framework, it is useful to disable compilation - particularly when nodes
  * and node components will need to be made un-live in order to make
  * changes. Once compiled, such components can be made un-live, but they are
  * still unchangable unless appropriate capabilities have been set.
  * 
  * @param onOff
  *            a boolean turning compilation on (true) or off (false)
  */
 public void setCompilable(boolean onOff) {
   shouldCompile = onOff;
 }
 /**
  * Gets whether the scene graph will be compiled or not.
  * 
  * @return a boolean indicating if scene graph compilation is on or off
  */
 public boolean getCompilable() {
   return shouldCompile;
 }
 //These methods will be replaced
 //  Set the view position and direction
 public void setViewpoint(Point3f position, Vector3f direction) {
   Transform3D t = new Transform3D();
   t.set(new Vector3f(position));
   exampleViewTransform.setTransform(t);
   // how to set direction?
 }
 //  Reset transforms
 public void reset() {
   Transform3D trans = new Transform3D();
   exampleSceneTransform.setTransform(trans);
   trans.set(new Vector3f(0.0f, 0.0f, 10.0f));
   exampleViewTransform.setTransform(trans);
   setNavigationType(navigationType);
 }
 //
 //  Gets the URL (with file: prepended) for the current directory.
 //  This is a terrible hack needed in the Alpha release of Java3D
 //  in order to build a full path URL for loading sounds with
 //  MediaContainer. When MediaContainer is fully implemented,
 //  it should handle relative path names, but not yet.
 //
 public String getCurrentDirectory() {
   // Create a bogus file so that we can query it"s path
   File dummy = new File("dummy.tmp");
   String dummyPath = dummy.getAbsolutePath();
   // strip "/dummy.tmp" from end of dummyPath and put into "path"
   if (dummyPath.endsWith(File.separator + "dummy.tmp")) {
     int index = dummyPath.lastIndexOf(File.separator + "dummy.tmp");
     if (index >= 0) {
       int pathLength = index + 5; // pre-pend "file:"
       char[] charPath = new char[pathLength];
       dummyPath.getChars(0, index, charPath, 5);
       String path = new String(charPath, 0, pathLength);
       path = "file:" + path.substring(5, pathLength);
       return path + File.separator;
     }
   }
   return dummyPath + File.separator;
 }
 //--------------------------------------------------------------
 //  USER INTERFACE
 //--------------------------------------------------------------
 /**
  * Builds the example AWT Frame menubar. Standard menus and their options
  * are added. Applications that subclass this class should build their
  * menubar additions within their initialize method.
  * 
  * @return a MenuBar for the AWT Frame
  */
 private MenuBar buildMenuBar() {
   // Build the menubar
   MenuBar menuBar = new MenuBar();
   // File menu
   Menu m = new Menu("File");
   m.addActionListener(this);
   m.add("Exit");
   menuBar.add(m);
   // View menu
   m = new Menu("View");
   m.addActionListener(this);
   m.add("Reset view");
   m.addSeparator();
   walkMenuItem = new CheckboxMenuItem("Walk");
   walkMenuItem.addItemListener(this);
   m.add(walkMenuItem);
   examineMenuItem = new CheckboxMenuItem("Examine");
   examineMenuItem.addItemListener(this);
   m.add(examineMenuItem);
   if (navigationType == Walk) {
     walkMenuItem.setState(true);
     examineMenuItem.setState(false);
   } else {
     walkMenuItem.setState(false);
     examineMenuItem.setState(true);
   }
   m.addSeparator();
   headlightMenuItem = new CheckboxMenuItem("Headlight on/off");
   headlightMenuItem.addItemListener(this);
   headlightMenuItem.setState(headlightOnOff);
   m.add(headlightMenuItem);
   menuBar.add(m);
   return menuBar;
 }
 /**
  * Shows the application"s frame, making it and its menubar, 3D canvas, and
  * 3D content visible.
  */
 public void showFrame() {
   exampleFrame.show();
 }
 /**
  * Quits the application.
  */
 public void quit() {
   System.exit(0);
 }
 /**
  * Handles menu selections.
  * 
  * @param event
  *            an ActionEvent indicating what menu action requires handling
  */
 public void actionPerformed(ActionEvent event) {
   String arg = event.getActionCommand();
   if (arg.equals("Reset view"))
     reset();
   else if (arg.equals("Exit"))
     quit();
 }
 /**
  * Handles checkbox items on a CheckboxMenu. The Example class has none of
  * its own, but subclasses may have some.
  * 
  * @param menu
  *            which CheckboxMenu needs action
  * @param check
  *            which CheckboxMenu item has changed
  */
 public void checkboxChanged(CheckboxMenu menu, int check) {
   // None for us
 }
 /**
  * Handles on/off checkbox items on a standard menu.
  * 
  * @param event
  *            an ItemEvent indicating what requires handling
  */
 public void itemStateChanged(ItemEvent event) {
   Object src = event.getSource();
   boolean state;
   if (src == headlightMenuItem) {
     state = headlightMenuItem.getState();
     headlight.setEnable(state);
   } else if (src == walkMenuItem)
     setNavigationType(Walk);
   else if (src == examineMenuItem)
     setNavigationType(Examine);
 }
 /**
  * Handles a window closing event notifying the application that the user
  * has chosen to close the application without selecting the "Exit" menu
  * item.
  * 
  * @param event
  *            a WindowEvent indicating the window is closing
  */
 public void windowClosing(WindowEvent event) {
   quit();
 }
 public void windowClosed(WindowEvent event) {
 }
 public void windowOpened(WindowEvent event) {
 }
 public void windowIconified(WindowEvent event) {
 }
 public void windowDeiconified(WindowEvent event) {
 }
 public void windowActivated(WindowEvent event) {
 }
 public void windowDeactivated(WindowEvent event) {
 }
 //  Well known colors, positions, and directions
 public final static Color3f White = new Color3f(1.0f, 1.0f, 1.0f);
 public final static Color3f Gray = new Color3f(0.7f, 0.7f, 0.7f);
 public final static Color3f DarkGray = new Color3f(0.2f, 0.2f, 0.2f);
 public final static Color3f Black = new Color3f(0.0f, 0.0f, 0.0f);
 public final static Color3f Red = new Color3f(1.0f, 0.0f, 0.0f);
 public final static Color3f DarkRed = new Color3f(0.3f, 0.0f, 0.0f);
 public final static Color3f Yellow = new Color3f(1.0f, 1.0f, 0.0f);
 public final static Color3f DarkYellow = new Color3f(0.3f, 0.3f, 0.0f);
 public final static Color3f Green = new Color3f(0.0f, 1.0f, 0.0f);
 public final static Color3f DarkGreen = new Color3f(0.0f, 0.3f, 0.0f);
 public final static Color3f Cyan = new Color3f(0.0f, 1.0f, 1.0f);
 public final static Color3f Blue = new Color3f(0.0f, 0.0f, 1.0f);
 public final static Color3f DarkBlue = new Color3f(0.0f, 0.0f, 0.3f);
 public final static Color3f Magenta = new Color3f(1.0f, 0.0f, 1.0f);
 public final static Vector3f PosX = new Vector3f(1.0f, 0.0f, 0.0f);
 public final static Vector3f NegX = new Vector3f(-1.0f, 0.0f, 0.0f);
 public final static Vector3f PosY = new Vector3f(0.0f, 1.0f, 0.0f);
 public final static Vector3f NegY = new Vector3f(0.0f, -1.0f, 0.0f);
 public final static Vector3f PosZ = new Vector3f(0.0f, 0.0f, 1.0f);
 public final static Vector3f NegZ = new Vector3f(0.0f, 0.0f, -1.0f);
 public final static Point3f Origin = new Point3f(0.0f, 0.0f, 0.0f);
 public final static Point3f PlusX = new Point3f(0.75f, 0.0f, 0.0f);
 public final static Point3f MinusX = new Point3f(-0.75f, 0.0f, 0.0f);
 public final static Point3f PlusY = new Point3f(0.0f, 0.75f, 0.0f);
 public final static Point3f MinusY = new Point3f(0.0f, -0.75f, 0.0f);
 public final static Point3f PlusZ = new Point3f(0.0f, 0.0f, 0.75f);
 public final static Point3f MinusZ = new Point3f(0.0f, 0.0f, -0.75f);

} // //INTERFACE //CheckboxMenuListener - listen for checkbox change events // //DESCRIPTION //The checkboxChanged method is called by users of this class //to notify the listener when a checkbox choice has changed on //a CheckboxMenu class menu. // interface CheckboxMenuListener extends EventListener {

 public void checkboxChanged(CheckboxMenu menu, int check);

} /**

* ExamineViewerBehavior
* 
* @version 1.0, 98/04/16
*/

/**

* Wakeup on mouse button presses, releases, and mouse movements and generate
* transforms in an "examination style" that enables the user to rotate,
* translation, and zoom an object as if it is held at arm"s length. Such an
* examination style is similar to the "Examine" navigation type used by VRML
* browsers.
* 
* The behavior maps mouse drags to different transforms depending upon the
* mosue button held down:
* 
* Button 1 (left) Horizontal movement --> Y-axis rotation Vertical movement -->
* X-axis rotation
* 
* Button 2 (middle) Horizontal movement --> nothing Vertical movement -->
* Z-axis translation
* 
* Button 3 (right) Horizontal movement --> X-axis translation Vertical movement
* --> Y-axis translation
* 
* To support systems with 2 or 1 mouse buttons, the following alternate
* mappings are supported while dragging with any mouse button held down and
* zero or more keyboard modifiers held down:
* 
* No modifiers = Button 1 ALT = Button 2 Meta = Button 3 Control = Button 3
* 
* The behavior automatically modifies a TransformGroup provided to the
* constructor. The TransformGroup"s transform can be set at any time by the
* application or other behaviors to cause the examine rotation and translation
* to be reset.
*/

// This class is inspired by the MouseBehavior, MouseRotate, // MouseTranslate, and MouseZoom utility behaviors provided with // Java 3D. This class differs from those utilities in that it: // // (a) encapsulates all three behaviors into one in order to // enforce a specific "Examine" symantic // // (b) supports set/get of the rotation and translation factors // that control the speed of movement. // // (c) supports the "Control" modifier as an alternative to the // "Meta" modifier not present on PC, Mac, and most non-Sun // keyboards. This makes button3 behavior usable on PCs, // Macs, and other systems with fewer than 3 mouse buttons. class ExamineViewerBehavior extends ViewerBehavior {

 // Previous cursor location
 protected int previousX = 0;
 protected int previousY = 0;
 // Saved standard cursor
 protected Cursor savedCursor = null;
 /**
  * Construct an examine behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into a
  * transform group given later with the setTransformGroup( ) method.
  */
 public ExamineViewerBehavior() {
   super();
 }
 /**
  * Construct an examine behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into a
  * transform group given later with the setTransformGroup( ) method.
  * 
  * @param parent
  *            The AWT Component that contains the area generating mouse
  *            events.
  */
 public ExamineViewerBehavior(Component parent) {
   super(parent);
 }
 /**
  * Construct an examine behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into the
  * given transform group.
  * 
  * @param transformGroup
  *            The transform group to be modified by the behavior.
  */
 public ExamineViewerBehavior(TransformGroup transformGroup) {
   super();
   subjectTransformGroup = transformGroup;
 }
 /**
  * Construct an examine behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into the
  * given transform group.
  * 
  * @param transformGroup
  *            The transform group to be modified by the behavior.
  * @param parent
  *            The AWT Component that contains the area generating mouse
  *            events.
  */
 public ExamineViewerBehavior(TransformGroup transformGroup, Component parent) {
   super(parent);
   subjectTransformGroup = transformGroup;
 }
 /**
  * Respond to a button1 event (press, release, or drag).
  * 
  * @param mouseEvent
  *            A MouseEvent to respond to.
  */
 public void onButton1(MouseEvent mev) {
   if (subjectTransformGroup == null)
     return;
   int x = mev.getX();
   int y = mev.getY();
   if (mev.getID() == MouseEvent.MOUSE_PRESSED) {
     // Mouse button pressed: record position
     previousX = x;
     previousY = y;
     // Change to a "move" cursor
     if (parentComponent != null) {
       savedCursor = parentComponent.getCursor();
       parentComponent.setCursor(Cursor
           .getPredefinedCursor(Cursor.HAND_CURSOR));
     }
     return;
   }
   if (mev.getID() == MouseEvent.MOUSE_RELEASED) {
     // Mouse button released: do nothing
     // Switch the cursor back
     if (parentComponent != null)
       parentComponent.setCursor(savedCursor);
     return;
   }
   //
   // Mouse moved while button down: create a rotation
   //
   // Compute the delta in X and Y from the previous
   // position. Use the delta to compute rotation
   // angles with the mapping:
   //
   //   positive X mouse delta --> positive Y-axis rotation
   //   positive Y mouse delta --> positive X-axis rotation
   //
   // where positive X mouse movement is to the right, and
   // positive Y mouse movement is **down** the screen.
   //
   int deltaX = x - previousX;
   int deltaY = y - previousY;
   if (deltaX > UNUSUAL_XDELTA || deltaX < -UNUSUAL_XDELTA
       || deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA) {
     // Deltas are too huge to be believable. Probably a glitch.
     // Don"t record the new XY location, or do anything.
     return;
   }
   double xRotationAngle = deltaY * XRotationFactor;
   double yRotationAngle = deltaX * YRotationFactor;
   //
   // Build transforms
   //
   transform1.rotX(xRotationAngle);
   transform2.rotY(yRotationAngle);
   // Get and save the current transform matrix
   subjectTransformGroup.getTransform(currentTransform);
   currentTransform.get(matrix);
   translate.set(matrix.m03, matrix.m13, matrix.m23);
   // Translate to the origin, rotate, then translate back
   currentTransform.setTranslation(origin);
   currentTransform.mul(transform1, currentTransform);
   currentTransform.mul(transform2, currentTransform);
   currentTransform.setTranslation(translate);
   // Update the transform group
   subjectTransformGroup.setTransform(currentTransform);
   previousX = x;
   previousY = y;
 }
 /**
  * Respond to a button2 event (press, release, or drag).
  * 
  * @param mouseEvent
  *            A MouseEvent to respond to.
  */
 public void onButton2(MouseEvent mev) {
   if (subjectTransformGroup == null)
     return;
   int x = mev.getX();
   int y = mev.getY();
   if (mev.getID() == MouseEvent.MOUSE_PRESSED) {
     // Mouse button pressed: record position
     previousX = x;
     previousY = y;
     // Change to a "move" cursor
     if (parentComponent != null) {
       savedCursor = parentComponent.getCursor();
       parentComponent.setCursor(Cursor
           .getPredefinedCursor(Cursor.MOVE_CURSOR));
     }
     return;
   }
   if (mev.getID() == MouseEvent.MOUSE_RELEASED) {
     // Mouse button released: do nothing
     // Switch the cursor back
     if (parentComponent != null)
       parentComponent.setCursor(savedCursor);
     return;
   }
   //
   // Mouse moved while button down: create a translation
   //
   // Compute the delta in Y from the previous
   // position. Use the delta to compute translation
   // distances with the mapping:
   //
   //   positive Y mouse delta --> positive Y-axis translation
   //
   // where positive X mouse movement is to the right, and
   // positive Y mouse movement is **down** the screen.
   //
   int deltaY = y - previousY;
   if (deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA) {
     // Deltas are too huge to be believable. Probably a glitch.
     // Don"t record the new XY location, or do anything.
     return;
   }
   double zTranslationDistance = deltaY * ZTranslationFactor;
   //
   // Build transforms
   //
   translate.set(0.0, 0.0, zTranslationDistance);
   transform1.set(translate);
   // Get and save the current transform
   subjectTransformGroup.getTransform(currentTransform);
   // Translate as needed
   currentTransform.mul(transform1, currentTransform);
   // Update the transform group
   subjectTransformGroup.setTransform(currentTransform);
   previousX = x;
   previousY = y;
 }
 /**
  * Respond to a button3 event (press, release, or drag).
  * 
  * @param mouseEvent
  *            A MouseEvent to respond to.
  */
 public void onButton3(MouseEvent mev) {
   if (subjectTransformGroup == null)
     return;
   int x = mev.getX();
   int y = mev.getY();
   if (mev.getID() == MouseEvent.MOUSE_PRESSED) {
     // Mouse button pressed: record position
     previousX = x;
     previousY = y;
     // Change to a "move" cursor
     if (parentComponent != null) {
       savedCursor = parentComponent.getCursor();
       parentComponent.setCursor(Cursor
           .getPredefinedCursor(Cursor.MOVE_CURSOR));
     }
     return;
   }
   if (mev.getID() == MouseEvent.MOUSE_RELEASED) {
     // Mouse button released: do nothing
     // Switch the cursor back
     if (parentComponent != null)
       parentComponent.setCursor(savedCursor);
     return;
   }
   //
   // Mouse moved while button down: create a translation
   //
   // Compute the delta in X and Y from the previous
   // position. Use the delta to compute translation
   // distances with the mapping:
   //
   //   positive X mouse delta --> positive X-axis translation
   //   positive Y mouse delta --> negative Y-axis translation
   //
   // where positive X mouse movement is to the right, and
   // positive Y mouse movement is **down** the screen.
   //
   int deltaX = x - previousX;
   int deltaY = y - previousY;
   if (deltaX > UNUSUAL_XDELTA || deltaX < -UNUSUAL_XDELTA
       || deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA) {
     // Deltas are too huge to be believable. Probably a glitch.
     // Don"t record the new XY location, or do anything.
     return;
   }
   double xTranslationDistance = deltaX * XTranslationFactor;
   double yTranslationDistance = -deltaY * YTranslationFactor;
   //
   // Build transforms
   //
   translate.set(xTranslationDistance, yTranslationDistance, 0.0);
   transform1.set(translate);
   // Get and save the current transform
   subjectTransformGroup.getTransform(currentTransform);
   // Translate as needed
   currentTransform.mul(transform1, currentTransform);
   // Update the transform group
   subjectTransformGroup.setTransform(currentTransform);
   previousX = x;
   previousY = y;
 }
 /**
  * Respond to an elapsed frames event (assuming subclass has set up a wakeup
  * criterion for it).
  * 
  * @param time
  *            A WakeupOnElapsedFrames criterion to respond to.
  */
 public void onElapsedFrames(WakeupOnElapsedFrames timeEvent) {
   // Can"t happen
 }

} /*

* 
* Copyright (c) 1998 David R. Nadeau
*  
*/

/**

* WalkViewerBehavior is a utility class that creates a "walking style"
* navigation symantic.
* 
* The behavior wakes up on mouse button presses, releases, and mouse movements
* and generates transforms in a "walk style" that enables the user to walk
* through a scene, translating and turning about as if they are within the
* scene. Such a walk style is similar to the "Walk" navigation type used by
* VRML browsers.
* <P>
* The behavior maps mouse drags to different transforms depending upon the
* mouse button held down:
*
*
Button 1 (left) *
Horizontal movement --> Y-axis rotation *
Vertical movement --> Z-axis translation * *
Button 2 (middle) *
Horizontal movement --> Y-axis rotation *
Vertical movement --> X-axis rotation * *
Button 3 (right) *
Horizontal movement --> X-axis translation *
Vertical movement --> Y-axis translation *
* 
* To support systems with 2 or 1 mouse buttons, the following alternate
* mappings are supported while dragging with any mouse button held down and
* zero or more keyboard modifiers held down:
*
    *
  • No modifiers = Button 1 *
  • ALT = Button 2 *
  • Meta = Button 3 *
  • Control = Button 3 *
* The behavior automatically modifies a TransformGroup provided to the
* constructor. The TransformGroup"s transform can be set at any time by the
* application or other behaviors to cause the walk rotation and translation to
* be reset.
* <P>
* While a mouse button is down, the behavior automatically changes the cursor
* in a given parent AWT Component. If no parent Component is given, no cursor
* changes are attempted.
* 
* @version 1.0, 98/04/16
* @author David R. Nadeau, San Diego Supercomputer Center
*/

class WalkViewerBehavior extends ViewerBehavior {

 // This class is inspired by the MouseBehavior, MouseRotate,
 // MouseTranslate, and MouseZoom utility behaviors provided with
 // Java 3D. This class differs from those utilities in that it:
 //
 //    (a) encapsulates all three behaviors into one in order to
 //        enforce a specific "Walk" symantic
 //
 //    (b) supports set/get of the rotation and translation factors
 //        that control the speed of movement.
 //
 //    (c) supports the "Control" modifier as an alternative to the
 //        "Meta" modifier not present on PC, Mac, and most non-Sun
 //        keyboards. This makes button3 behavior usable on PCs,
 //        Macs, and other systems with fewer than 3 mouse buttons.
 // Previous and initial cursor locations
 protected int previousX = 0;
 protected int previousY = 0;
 protected int initialX = 0;
 protected int initialY = 0;
 // Deadzone size (delta from initial XY for which no
 // translate or rotate action is taken
 protected static final int DELTAX_DEADZONE = 10;
 protected static final int DELTAY_DEADZONE = 10;
 // Keep a set of wakeup criterion for animation-generated
 // event types.
 protected WakeupCriterion[] mouseAndAnimationEvents = null;
 protected WakeupOr mouseAndAnimationCriterion = null;
 protected WakeupOr savedMouseCriterion = null;
 // Saved standard cursor
 protected Cursor savedCursor = null;
 /**
  * Default Rotation and translation scaling factors for animated movements
  * (Button 1 press).
  */
 public static final double DEFAULT_YROTATION_ANIMATION_FACTOR = 0.0002;
 public static final double DEFAULT_ZTRANSLATION_ANIMATION_FACTOR = 0.01;
 protected double YRotationAnimationFactor = DEFAULT_YROTATION_ANIMATION_FACTOR;
 protected double ZTranslationAnimationFactor = DEFAULT_ZTRANSLATION_ANIMATION_FACTOR;
 /**
  * Constructs a new walk behavior that converts mouse actions into rotations
  * and translations. Rotations and translations are written into a
  * TransformGroup that must be set using the setTransformGroup method. The
  * cursor will be changed during mouse actions if the parent frame is set
  * using the setParentComponent method.
  * 
  * @return a new WalkViewerBehavior that needs its TransformGroup and parent
  *         Component set
  */
 public WalkViewerBehavior() {
   super();
 }
 /**
  * Constructs a new walk behavior that converts mouse actions into rotations
  * and translations. Rotations and translations are written into a
  * TransformGroup that must be set using the setTransformGroup method. The
  * cursor will be changed within the given AWT parent Component during mouse
  * drags.
  * 
  * @param parent
  *            a parent AWT Component within which the cursor will change
  *            during mouse drags
  * 
  * @return a new WalkViewerBehavior that needs its TransformGroup and parent
  *         Component set
  */
 public WalkViewerBehavior(Component parent) {
   super(parent);
 }
 /**
  * Constructs a new walk behavior that converts mouse actions into rotations
  * and translations. Rotations and translations are written into the given
  * TransformGroup. The cursor will be changed during mouse actions if the
  * parent frame is set using the setParentComponent method.
  * 
  * @param transformGroup
  *            a TransformGroup whos transform is read and written by the
  *            behavior
  * 
  * @return a new WalkViewerBehavior that needs its TransformGroup and parent
  *         Component set
  */
 public WalkViewerBehavior(TransformGroup transformGroup) {
   super();
   subjectTransformGroup = transformGroup;
 }
 /**
  * Constructs a new walk behavior that converts mouse actions into rotations
  * and translations. Rotations and translations are written into the given
  * TransformGroup. The cursor will be changed within the given AWT parent
  * Component during mouse drags.
  * 
  * @param transformGroup
  *            a TransformGroup whos transform is read and written by the
  *            behavior
  * 
  * @param parent
  *            a parent AWT Component within which the cursor will change
  *            during mouse drags
  * 
  * @return a new WalkViewerBehavior that needs its TransformGroup and parent
  *         Component set
  */
 public WalkViewerBehavior(TransformGroup transformGroup, Component parent) {
   super(parent);
   subjectTransformGroup = transformGroup;
 }
 /**
  * Initializes the behavior.
  */
 public void initialize() {
   super.initialize();
   savedMouseCriterion = mouseCriterion; // from parent class
   mouseAndAnimationEvents = new WakeupCriterion[4];
   mouseAndAnimationEvents[0] = new WakeupOnAWTEvent(
       MouseEvent.MOUSE_DRAGGED);
   mouseAndAnimationEvents[1] = new WakeupOnAWTEvent(
       MouseEvent.MOUSE_PRESSED);
   mouseAndAnimationEvents[2] = new WakeupOnAWTEvent(
       MouseEvent.MOUSE_RELEASED);
   mouseAndAnimationEvents[3] = new WakeupOnElapsedFrames(0);
   mouseAndAnimationCriterion = new WakeupOr(mouseAndAnimationEvents);
   // Don"t use the above criterion until a button 1 down event
 }
 /**
  * Sets the Y rotation animation scaling factor for Y-axis rotations. This
  * scaling factor is used to control the speed of Y rotation when button 1
  * is pressed and dragged.
  * 
  * @param factor
  *            the double Y rotation scaling factor
  */
 public void setYRotationAnimationFactor(double factor) {
   YRotationAnimationFactor = factor;
 }
 /**
  * Gets the current Y animation rotation scaling factor for Y-axis
  * rotations.
  * 
  * @return the double Y rotation scaling factor
  */
 public double getYRotationAnimationFactor() {
   return YRotationAnimationFactor;
 }
 /**
  * Sets the Z animation translation scaling factor for Z-axis translations.
  * This scaling factor is used to control the speed of Z translation when
  * button 1 is pressed and dragged.
  * 
  * @param factor
  *            the double Z translation scaling factor
  */
 public void setZTranslationAnimationFactor(double factor) {
   ZTranslationAnimationFactor = factor;
 }
 /**
  * Gets the current Z animation translation scaling factor for Z-axis
  * translations.
  * 
  * @return the double Z translation scaling factor
  */
 public double getZTranslationAnimationFactor() {
   return ZTranslationAnimationFactor;
 }
 /**
  * Responds to an elapsed frames event. Such an event is generated on every
  * frame while button 1 is held down. On each call, this method computes new
  * Y-axis rotation and Z-axis translation values and writes them to the
  * behavior"s TransformGroup. The translation and rotation amounts are
  * computed based upon the distance between the current cursor location and
  * the cursor location when button 1 was pressed. As this distance
  * increases, the translation or rotation amount increases.
  * 
  * @param time
  *            the WakeupOnElapsedFrames criterion to respond to
  */
 public void onElapsedFrames(WakeupOnElapsedFrames timeEvent) {
   //
   // Time elapsed while button down: create a rotation and
   // a translation.
   //
   // Compute the delta in X and Y from the initial position to
   // the previous position. Multiply the delta times a scaling
   // factor to compute an offset to add to the current translation
   // and rotation. Use the mapping:
   //
   //   positive X mouse delta --> negative Y-axis rotation
   //   positive Y mouse delta --> positive Z-axis translation
   //
   // where positive X mouse movement is to the right, and
   // positive Y mouse movement is **down** the screen.
   //
   if (buttonPressed != BUTTON1)
     return;
   int deltaX = previousX - initialX;
   int deltaY = previousY - initialY;
   double yRotationAngle = -deltaX * YRotationAnimationFactor;
   double zTranslationDistance = deltaY * ZTranslationAnimationFactor;
   //
   // Build transforms
   //
   transform1.rotY(yRotationAngle);
   translate.set(0.0, 0.0, zTranslationDistance);
   // Get and save the current transform matrix
   subjectTransformGroup.getTransform(currentTransform);
   currentTransform.get(matrix);
   // Translate to the origin, rotate, then translate back
   currentTransform.setTranslation(origin);
   currentTransform.mul(transform1, currentTransform);
   // Translate back from the origin by the original translation
   // distance, plus the new walk translation... but force walk
   // to travel on a plane by ignoring the Y component of a
   // transformed translation vector.
   currentTransform.transform(translate);
   translate.x += matrix.m03; // add in existing X translation
   translate.y = matrix.m13; // use Y translation
   translate.z += matrix.m23; // add in existing Z translation
   currentTransform.setTranslation(translate);
   // Update the transform group
   subjectTransformGroup.setTransform(currentTransform);
 }
 /**
  * Responds to a button1 event (press, release, or drag). On a press, the
  * method adds a wakeup criterion to the behavior"s set, callling for the
  * behavior to be awoken on each frame. On a button prelease, this criterion
  * is removed from the set.
  * 
  * @param mouseEvent
  *            the MouseEvent to respond to
  */
 public void onButton1(MouseEvent mev) {
   if (subjectTransformGroup == null)
     return;
   int x = mev.getX();
   int y = mev.getY();
   if (mev.getID() == MouseEvent.MOUSE_PRESSED) {
     // Mouse button pressed: record position and change
     // the wakeup criterion to include elapsed time wakeups
     // so we can animate.
     previousX = x;
     previousY = y;
     initialX = x;
     initialY = y;
     // Swap criterion... parent class will not reschedule us
     mouseCriterion = mouseAndAnimationCriterion;
     // Change to a "move" cursor
     if (parentComponent != null) {
       savedCursor = parentComponent.getCursor();
       parentComponent.setCursor(Cursor
           .getPredefinedCursor(Cursor.HAND_CURSOR));
     }
     return;
   }
   if (mev.getID() == MouseEvent.MOUSE_RELEASED) {
     // Mouse button released: restore original wakeup
     // criterion which only includes mouse activity, not
     // elapsed time
     mouseCriterion = savedMouseCriterion;
     // Switch the cursor back
     if (parentComponent != null)
       parentComponent.setCursor(savedCursor);
     return;
   }
   previousX = x;
   previousY = y;
 }
 /**
  * Responds to a button2 event (press, release, or drag). On a press, the
  * method records the initial cursor location. On a drag, the difference
  * between the current and previous cursor location provides a delta that
  * controls the amount by which to rotate in X and Y.
  * 
  * @param mouseEvent
  *            the MouseEvent to respond to
  */
 public void onButton2(MouseEvent mev) {
   if (subjectTransformGroup == null)
     return;
   int x = mev.getX();
   int y = mev.getY();
   if (mev.getID() == MouseEvent.MOUSE_PRESSED) {
     // Mouse button pressed: record position
     previousX = x;
     previousY = y;
     initialX = x;
     initialY = y;
     // Change to a "rotate" cursor
     if (parentComponent != null) {
       savedCursor = parentComponent.getCursor();
       parentComponent.setCursor(Cursor
           .getPredefinedCursor(Cursor.MOVE_CURSOR));
     }
     return;
   }
   if (mev.getID() == MouseEvent.MOUSE_RELEASED) {
     // Mouse button released: do nothing
     // Switch the cursor back
     if (parentComponent != null)
       parentComponent.setCursor(savedCursor);
     return;
   }
   //
   // Mouse moved while button down: create a rotation
   //
   // Compute the delta in X and Y from the previous
   // position. Use the delta to compute rotation
   // angles with the mapping:
   //
   //   positive X mouse delta --> negative Y-axis rotation
   //   positive Y mouse delta --> negative X-axis rotation
   //
   // where positive X mouse movement is to the right, and
   // positive Y mouse movement is **down** the screen.
   //
   int deltaX = x - previousX;
   int deltaY = 0;
   if (Math.abs(y - initialY) > DELTAY_DEADZONE) {
     // Cursor has moved far enough vertically to consider
     // it intentional, so get it"s delta.
     deltaY = y - previousY;
   }
   if (deltaX > UNUSUAL_XDELTA || deltaX < -UNUSUAL_XDELTA
       || deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA) {
     // Deltas are too huge to be believable. Probably a glitch.
     // Don"t record the new XY location, or do anything.
     return;
   }
   double xRotationAngle = -deltaY * XRotationFactor;
   double yRotationAngle = -deltaX * YRotationFactor;
   //
   // Build transforms
   //
   transform1.rotX(xRotationAngle);
   transform2.rotY(yRotationAngle);
   // Get and save the current transform matrix
   subjectTransformGroup.getTransform(currentTransform);
   currentTransform.get(matrix);
   translate.set(matrix.m03, matrix.m13, matrix.m23);
   // Translate to the origin, rotate, then translate back
   currentTransform.setTranslation(origin);
   currentTransform.mul(transform2, currentTransform);
   currentTransform.mul(transform1);
   currentTransform.setTranslation(translate);
   // Update the transform group
   subjectTransformGroup.setTransform(currentTransform);
   previousX = x;
   previousY = y;
 }
 /**
  * Responds to a button3 event (press, release, or drag). On a drag, the
  * difference between the current and previous cursor location provides a
  * delta that controls the amount by which to translate in X and Y.
  * 
  * @param mouseEvent
  *            the MouseEvent to respond to
  */
 public void onButton3(MouseEvent mev) {
   if (subjectTransformGroup == null)
     return;
   int x = mev.getX();
   int y = mev.getY();
   if (mev.getID() == MouseEvent.MOUSE_PRESSED) {
     // Mouse button pressed: record position
     previousX = x;
     previousY = y;
     // Change to a "move" cursor
     if (parentComponent != null) {
       savedCursor = parentComponent.getCursor();
       parentComponent.setCursor(Cursor
           .getPredefinedCursor(Cursor.MOVE_CURSOR));
     }
     return;
   }
   if (mev.getID() == MouseEvent.MOUSE_RELEASED) {
     // Mouse button released: do nothing
     // Switch the cursor back
     if (parentComponent != null)
       parentComponent.setCursor(savedCursor);
     return;
   }
   //
   // Mouse moved while button down: create a translation
   //
   // Compute the delta in X and Y from the previous
   // position. Use the delta to compute translation
   // distances with the mapping:
   //
   //   positive X mouse delta --> positive X-axis translation
   //   positive Y mouse delta --> negative Y-axis translation
   //
   // where positive X mouse movement is to the right, and
   // positive Y mouse movement is **down** the screen.
   //
   int deltaX = x - previousX;
   int deltaY = y - previousY;
   if (deltaX > UNUSUAL_XDELTA || deltaX < -UNUSUAL_XDELTA
       || deltaY > UNUSUAL_YDELTA || deltaY < -UNUSUAL_YDELTA) {
     // Deltas are too huge to be believable. Probably a glitch.
     // Don"t record the new XY location, or do anything.
     return;
   }
   double xTranslationDistance = deltaX * XTranslationFactor;
   double yTranslationDistance = -deltaY * YTranslationFactor;
   //
   // Build transforms
   //
   translate.set(xTranslationDistance, yTranslationDistance, 0.0);
   transform1.set(translate);
   // Get and save the current transform
   subjectTransformGroup.getTransform(currentTransform);
   // Translate as needed
   currentTransform.mul(transform1);
   // Update the transform group
   subjectTransformGroup.setTransform(currentTransform);
   previousX = x;
   previousY = y;
 }

} // //CLASS //CheckboxMenu - build a menu of grouped checkboxes // //DESCRIPTION //The class creates a menu with one or more CheckboxMenuItem"s //and monitors that menu. When a menu checkbox is picked, the //previous one is turned off (in radio-button style). Then, //a given listener"s checkboxChanged method is called, passing it //the menu and the item checked. // class CheckboxMenu extends Menu implements ItemListener {

 // State
 protected CheckboxMenuItem[] checks = null;
 protected int current = 0;
 protected CheckboxMenuListener listener = null;
 //  Construct
 public CheckboxMenu(String name, NameValue[] items,
     CheckboxMenuListener listen) {
   this(name, items, 0, listen);
 }
 public CheckboxMenu(String name, NameValue[] items, int cur,
     CheckboxMenuListener listen) {
   super(name);
   current = cur;
   listener = listen;
   if (items == null)
     return;
   checks = new CheckboxMenuItem[items.length];
   for (int i = 0; i < items.length; i++) {
     checks[i] = new CheckboxMenuItem(items[i].name, false);
     checks[i].addItemListener(this);
     add(checks[i]);
   }
   checks[cur].setState(true);
 }
 //  Handle checkbox changed events
 public void itemStateChanged(ItemEvent event) {
   Object src = event.getSource();
   for (int i = 0; i < checks.length; i++) {
     if (src == checks[i]) {
       // Update the checkboxes
       checks[current].setState(false);
       current = i;
       checks[current].setState(true);
       if (listener != null)
         listener.checkboxChanged(this, i);
       return;
     }
   }
 }
 // Methods to get and set state
 public int getCurrent() {
   return current;
 }
 public void setCurrent(int cur) {
   if (cur < 0 || cur >= checks.length)
     return; // ignore out of range choices
   if (checks == null)
     return;
   checks[current].setState(false);
   current = cur;
   checks[current].setState(true);
 }
 public CheckboxMenuItem getSelectedCheckbox() {
   if (checks == null)
     return null;
   return checks[current];
 }
 public void setSelectedCheckbox(CheckboxMenuItem item) {
   if (checks == null)
     return;
   for (int i = 0; i < checks.length; i++) {
     if (item == checks[i]) {
       checks[i].setState(false);
       current = i;
       checks[i].setState(true);
     }
   }
 }

} /**

* ViewerBehavior
* 
* @version 1.0, 98/04/16
*/

/**

* Wakeup on mouse button presses, releases, and mouse movements and generate
* transforms for a transform group. Classes that extend this class impose
* specific symantics, such as "Examine" or "Walk" viewing, similar to the
* navigation types used by VRML browsers.
* 
* To support systems with 2 or 1 mouse buttons, the following alternate
* mappings are supported while dragging with any mouse button held down and
* zero or more keyboard modifiers held down:
* 
* No modifiers = Button 1 ALT = Button 2 Meta = Button 3 Control = Button 3
* 
* The behavior automatically modifies a TransformGroup provided to the
* constructor. The TransformGroup"s transform can be set at any time by the
* application or other behaviors to cause the viewer"s rotation and translation
* to be reset.
*/

// This class is inspired by the MouseBehavior, MouseRotate, // MouseTranslate, and MouseZoom utility behaviors provided with // Java 3D. This class differs from those utilities in that it: // // (a) encapsulates all three behaviors into one in order to // enforce a specific viewing symantic // // (b) supports set/get of the rotation and translation factors // that control the speed of movement. // // (c) supports the "Control" modifier as an alternative to the // "Meta" modifier not present on PC, Mac, and most non-Sun // keyboards. This makes button3 behavior usable on PCs, // Macs, and other systems with fewer than 3 mouse buttons. abstract class ViewerBehavior extends Behavior {

 // Keep track of the transform group who"s transform we modify
 // during mouse motion.
 protected TransformGroup subjectTransformGroup = null;
 // Keep a set of wakeup criterion for different mouse-generated
 // event types.
 protected WakeupCriterion[] mouseEvents = null;
 protected WakeupOr mouseCriterion = null;
 // Track which button was last pressed
 protected static final int BUTTONNONE = -1;
 protected static final int BUTTON1 = 0;
 protected static final int BUTTON2 = 1;
 protected static final int BUTTON3 = 2;
 protected int buttonPressed = BUTTONNONE;
 // Keep a few Transform3Ds for use during event processing. This
 // avoids having to allocate new ones on each event.
 protected Transform3D currentTransform = new Transform3D();
 protected Transform3D transform1 = new Transform3D();
 protected Transform3D transform2 = new Transform3D();
 protected Matrix4d matrix = new Matrix4d();
 protected Vector3d origin = new Vector3d(0.0, 0.0, 0.0);
 protected Vector3d translate = new Vector3d(0.0, 0.0, 0.0);
 // Unusual X and Y delta limits.
 protected static final int UNUSUAL_XDELTA = 400;
 protected static final int UNUSUAL_YDELTA = 400;
 protected Component parentComponent = null;
 /**
  * Construct a viewer behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into a
  * transform group given later with the setTransformGroup( ) method.
  */
 public ViewerBehavior() {
   super();
 }
 /**
  * Construct a viewer behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into a
  * transform group given later with the setTransformGroup( ) method.
  * 
  * @param parent
  *            The AWT Component that contains the area generating mouse
  *            events.
  */
 public ViewerBehavior(Component parent) {
   super();
   parentComponent = parent;
 }
 /**
  * Construct a viewer behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into the
  * given transform group.
  * 
  * @param transformGroup
  *            The transform group to be modified by the behavior.
  */
 public ViewerBehavior(TransformGroup transformGroup) {
   super();
   subjectTransformGroup = transformGroup;
 }
 /**
  * Construct a viewer behavior that listens to mouse movement and button
  * presses to generate rotation and translation transforms written into the
  * given transform group.
  * 
  * @param transformGroup
  *            The transform group to be modified by the behavior.
  * @param parent
  *            The AWT Component that contains the area generating mouse
  *            events.
  */
 public ViewerBehavior(TransformGroup transformGroup, Component parent) {
   super();
   subjectTransformGroup = transformGroup;
   parentComponent = parent;
 }
 /**
  * Set the transform group modified by the viewer behavior. Setting the
  * transform group to null disables the behavior until the transform group
  * is again set to an existing group.
  * 
  * @param transformGroup
  *            The new transform group to be modified by the behavior.
  */
 public void setTransformGroup(TransformGroup transformGroup) {
   subjectTransformGroup = transformGroup;
 }
 /**
  * Get the transform group modified by the viewer behavior.
  */
 public TransformGroup getTransformGroup() {
   return subjectTransformGroup;
 }
 /**
  * Sets the parent component who"s cursor will be changed during mouse
  * drags. If no component is given is given to the constructor, or set via
  * this method, no cursor changes will be done.
  * 
  * @param parent
  *            the AWT Component, such as a Frame, within which cursor
  *            changes should take place during mouse drags
  */
 public void setParentComponent(Component parent) {
   parentComponent = parent;
 }
 /*
  * Gets the parent frame within which the cursor changes during mouse drags.
  * 
  * @return the AWT Component, such as a Frame, within which cursor changes
  * should take place during mouse drags. Returns null if no parent is set.
  */
 public Component getParentComponent() {
   return parentComponent;
 }
 /**
  * Initialize the behavior.
  */
 public void initialize() {
   // Wakeup when the mouse is dragged or when a mouse button
   // is pressed or released.
   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);
   mouseCriterion = new WakeupOr(mouseEvents);
   wakeupOn(mouseCriterion);
 }
 /**
  * Process a new wakeup. Interpret mouse button presses, releases, and mouse
  * drags.
  * 
  * @param criteria
  *            The wakeup criteria causing the behavior wakeup.
  */
 public void processStimulus(Enumeration criteria) {
   WakeupCriterion wakeup = null;
   AWTEvent[] event = null;
   int whichButton = BUTTONNONE;
   // Process all pending wakeups
   while (criteria.hasMoreElements()) {
     wakeup = (WakeupCriterion) criteria.nextElement();
     if (wakeup instanceof WakeupOnAWTEvent) {
       event = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
       // Process all pending events
       for (int i = 0; i < event.length; i++) {
         if (event[i].getID() != MouseEvent.MOUSE_PRESSED
             && event[i].getID() != MouseEvent.MOUSE_RELEASED
             && event[i].getID() != MouseEvent.MOUSE_DRAGGED)
           // Ignore uninteresting mouse events
           continue;
         //
         // Regretably, Java event handling (or perhaps
         // underlying OS event handling) doesn"t always
         // catch button bounces (redundant presses and
         // releases), or order events so that the last
         // drag event is delivered before a release.
         // This means we can get stray events that we
         // filter out here.
         //
         if (event[i].getID() == MouseEvent.MOUSE_PRESSED
             && buttonPressed != BUTTONNONE)
           // Ignore additional button presses until a release
           continue;
         if (event[i].getID() == MouseEvent.MOUSE_RELEASED
             && buttonPressed == BUTTONNONE)
           // Ignore additional button releases until a press
           continue;
         if (event[i].getID() == MouseEvent.MOUSE_DRAGGED
             && buttonPressed == BUTTONNONE)
           // Ignore drags until a press
           continue;
         MouseEvent mev = (MouseEvent) event[i];
         int modifiers = mev.getModifiers();
         //
         // Unfortunately, the underlying event handling
         // doesn"t do a "grab" operation when a mouse button
         // is pressed. This means that once a button is
         // pressed, if another mouse button or a keyboard
         // modifier key is pressed, the delivered mouse event
         // will show that a different button is being held
         // down. For instance:
         //
         // Action Event
         //  Button 1 press Button 1 press
         //  Drag with button 1 down Button 1 drag
         //  ALT press -
         //  Drag with ALT & button 1 down Button 2 drag
         //  Button 1 release Button 2 release
         //
         // The upshot is that we can get a button press
         // without a matching release, and the button
         // associated with a drag can change mid-drag.
         //
         // To fix this, we watch for an initial button
         // press, and thenceforth consider that button
         // to be the one held down, even if additional
         // buttons get pressed, and despite what is
         // reported in the event. Only when a button is
         // released, do we end such a grab.
         //
         if (buttonPressed == BUTTONNONE) {
           // No button is pressed yet, figure out which
           // button is down now and how to direct events
           if (((modifiers & InputEvent.BUTTON3_MASK) != 0)
               || (((modifiers & InputEvent.BUTTON1_MASK) != 0) && ((modifiers & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK))) {
             // Button 3 activity (META or CTRL down)
             whichButton = BUTTON3;
           } else if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
             // Button 2 activity (ALT down)
             whichButton = BUTTON2;
           } else {
             // Button 1 activity (no modifiers down)
             whichButton = BUTTON1;
           }
           // If the event is to press a button, then
           // record that that button is now down
           if (event[i].getID() == MouseEvent.MOUSE_PRESSED)
             buttonPressed = whichButton;
         } else {
           // Otherwise a button was pressed earlier and
           // hasn"t been released yet. Assign all further
           // events to it, even if ALT, META, CTRL, or
           // another button has been pressed as well.
           whichButton = buttonPressed;
         }
         // Distribute the event
         switch (whichButton) {
         case BUTTON1:
           onButton1(mev);
           break;
         case BUTTON2:
           onButton2(mev);
           break;
         case BUTTON3:
           onButton3(mev);
           break;
         default:
           break;
         }
         // If the event is to release a button, then
         // record that that button is now up
         if (event[i].getID() == MouseEvent.MOUSE_RELEASED)
           buttonPressed = BUTTONNONE;
       }
       continue;
     }
     if (wakeup instanceof WakeupOnElapsedFrames) {
       onElapsedFrames((WakeupOnElapsedFrames) wakeup);
       continue;
     }
   }
   // Reschedule us for another wakeup
   wakeupOn(mouseCriterion);
 }
 /**
  * Default X and Y rotation factors, and XYZ translation factors.
  */
 public static final double DEFAULT_XROTATION_FACTOR = 0.02;
 public static final double DEFAULT_YROTATION_FACTOR = 0.005;
 public static final double DEFAULT_XTRANSLATION_FACTOR = 0.02;
 public static final double DEFAULT_YTRANSLATION_FACTOR = 0.02;
 public static final double DEFAULT_ZTRANSLATION_FACTOR = 0.04;
 protected double XRotationFactor = DEFAULT_XROTATION_FACTOR;
 protected double YRotationFactor = DEFAULT_YROTATION_FACTOR;
 protected double XTranslationFactor = DEFAULT_XTRANSLATION_FACTOR;
 protected double YTranslationFactor = DEFAULT_YTRANSLATION_FACTOR;
 protected double ZTranslationFactor = DEFAULT_ZTRANSLATION_FACTOR;
 /**
  * Set the X rotation scaling factor for X-axis rotations.
  * 
  * @param factor
  *            The new scaling factor.
  */
 public void setXRotationFactor(double factor) {
   XRotationFactor = factor;
 }
 /**
  * Get the current X rotation scaling factor for X-axis rotations.
  */
 public double getXRotationFactor() {
   return XRotationFactor;
 }
 /**
  * Set the Y rotation scaling factor for Y-axis rotations.
  * 
  * @param factor
  *            The new scaling factor.
  */
 public void setYRotationFactor(double factor) {
   YRotationFactor = factor;
 }
 /**
  * Get the current Y rotation scaling factor for Y-axis rotations.
  */
 public double getYRotationFactor() {
   return YRotationFactor;
 }
 /**
  * Set the X translation scaling factor for X-axis translations.
  * 
  * @param factor
  *            The new scaling factor.
  */
 public void setXTranslationFactor(double factor) {
   XTranslationFactor = factor;
 }
 /**
  * Get the current X translation scaling factor for X-axis translations.
  */
 public double getXTranslationFactor() {
   return XTranslationFactor;
 }
 /**
  * Set the Y translation scaling factor for Y-axis translations.
  * 
  * @param factor
  *            The new scaling factor.
  */
 public void setYTranslationFactor(double factor) {
   YTranslationFactor = factor;
 }
 /**
  * Get the current Y translation scaling factor for Y-axis translations.
  */
 public double getYTranslationFactor() {
   return YTranslationFactor;
 }
 /**
  * Set the Z translation scaling factor for Z-axis translations.
  * 
  * @param factor
  *            The new scaling factor.
  */
 public void setZTranslationFactor(double factor) {
   ZTranslationFactor = factor;
 }
 /**
  * Get the current Z translation scaling factor for Z-axis translations.
  */
 public double getZTranslationFactor() {
   return ZTranslationFactor;
 }
 /**
  * Respond to a button1 event (press, release, or drag).
  * 
  * @param mouseEvent
  *            A MouseEvent to respond to.
  */
 public abstract void onButton1(MouseEvent mouseEvent);
 /**
  * Respond to a button2 event (press, release, or drag).
  * 
  * @param mouseEvent
  *            A MouseEvent to respond to.
  */
 public abstract void onButton2(MouseEvent mouseEvent);
 /**
  * Responed to a button3 event (press, release, or drag).
  * 
  * @param mouseEvent
  *            A MouseEvent to respond to.
  */
 public abstract void onButton3(MouseEvent mouseEvent);
 /**
  * Respond to an elapsed frames event (assuming subclass has set up a wakeup
  * criterion for it).
  * 
  * @param time
  *            A WakeupOnElapsedFrames criterion to respond to.
  */
 public abstract void onElapsedFrames(WakeupOnElapsedFrames timeEvent);

} // //CLASS //NameValue - create a handy name-value pair // //DESCRIPTION //It is frequently handy to have one or more name-value pairs //with which to store named colors, named positions, named textures, //and so forth. Several of the examples use this class. // //AUTHOR //David R. Nadeau / San Diego Supercomputer Center // class NameValue {

 public String name;
 public Object value;
 public NameValue(String n, Object v) {
   name = n;
   value = v;
 }

}


      </source>
   
  
 
  



Geometry By Reference

   <source lang="java">

/*

* @(#)GeometryByReferenceTest.java 1.12 02/10/21 13:41:27
* 
* 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.awt.Container; import java.awt.Frame; 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.ColoringAttributes; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Geometry; import javax.media.j3d.GeometryArray; import javax.media.j3d.GeometryUpdater; import javax.media.j3d.IndexedGeometryArray; import javax.media.j3d.IndexedTriangleArray; import javax.media.j3d.IndexedTriangleStripArray; import javax.media.j3d.Material; import javax.media.j3d.RenderingAttributes; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TransparencyAttributes; import javax.media.j3d.TriangleArray; import javax.media.j3d.TriangleStripArray; import javax.swing.BoxLayout; import javax.swing.JApplet; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.border.TitledBorder; 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.vp.OrbitBehavior; import com.sun.j3d.utils.universe.SimpleUniverse; import com.sun.j3d.utils.universe.ViewingPlatform; public class GeometryByReferenceTest extends JApplet implements ActionListener,

   GeometryUpdater {
 RenderingAttributes ra;
 ColoringAttributes ca;
 Material mat;
 Appearance app;
 JComboBox geomType;
 JComboBox vertexType;
 JComboBox colorType;
 JCheckBox transparency;
 JComboBox updates;
 Shape3D shape;
 TransparencyAttributes transp;
 int updateIndex = 0;
 int colorCount = 0, vertexCount = 0;
 int vertexIndex = 0, colorIndex = 0;
 GeometryArray tetraRegular, tetraStrip, tetraIndexed, tetraIndexedStrip;
 GeometryArray[] geoArrays = new GeometryArray[4];
 private static final float sqrt3 = (float) Math.sqrt(3.0);
 private static final float sqrt3_3 = sqrt3 / 3.0f;
 private static final float sqrt24_3 = (float) Math.sqrt(24.0) / 3.0f;
 private static final float ycenter = 0.5f * sqrt24_3;
 private static final float zcenter = -sqrt3_3;
 private static final Point3f p1 = new Point3f(-1.0f, -ycenter, -zcenter);
 private static final Point3f p2 = new Point3f(1.0f, -ycenter, -zcenter);
 private static final Point3f p3 = new Point3f(0.0f, -ycenter, -sqrt3
     - zcenter);
 private static final Point3f p4 = new Point3f(0.0f, sqrt24_3 - ycenter,
     0.0f);
 private static final float[] floatVerts = { p1.x, p1.y, p1.z, // front face
     p2.x, p2.y, p2.z, p4.x, p4.y, p4.z,
     p1.x, p1.y, p1.z,// left, back face
     p4.x, p4.y, p4.z, p3.x, p3.y, p3.z,
     p2.x, p2.y, p2.z,// right, back face
     p3.x, p3.y, p3.z, p4.x, p4.y, p4.z,
     p1.x, p1.y, p1.z,// bottom face
     p3.x, p3.y, p3.z, p2.x, p2.y, p2.z, };
 private static final Color3f c1 = new Color3f(0.6f, 0.0f, 0.0f);
 private static final Color3f c2 = new Color3f(0.0f, 0.6f, 0.0f);
 private static final Color3f c3 = new Color3f(0.0f, 0.6f, 0.6f);
 private static final Color3f c4 = new Color3f(0.6f, 0.6f, 0.0f);
 private static final float[] floatClrs = { c1.x, c1.y, c1.z, // front face
     c2.x, c2.y, c2.z, c4.x, c4.y, c4.z,
     c1.x, c1.y, c1.z,// left, back face
     c4.x, c4.y, c4.z, c3.x, c3.y, c3.z,
     c2.x, c2.y, c2.z,// right, back face
     c3.x, c3.y, c3.z, c4.x, c4.y, c4.z,
     c1.x, c1.y, c1.z,// bottom face
     c3.x, c3.y, c3.z, c2.x, c2.y, c2.z, };
 private static final float[] indexedFloatVerts = { p1.x, p1.y, p1.z, p2.x,
     p2.y, p2.z, p3.x, p3.y, p3.z, p4.x, p4.y, p4.z,
 };
 private static final float[] indexedFloatClrs = { c1.x, c1.y, c1.z, c2.x,
     c2.y, c2.z, c3.x, c3.y, c3.z, c4.x, c4.y, c4.z, };
 private static final Point3f[] p3fVerts = { p1, p2, p4, p1, p4, p3, p2, p3,
     p4, p1, p3, p2 };
 private static final Point3f[] indexedP3fVerts = { p1, p2, p3, p4 };
 private static final Color3f[] c3fClrs = { c1, c2, c4, c1, c4, c3, c2, c3,
     c4, c1, c3, c2 };
 private static final Color3f[] indexedC3fClrs = { c1, c2, c3, c4 };
 private static final int[] indices = { 0, 1, 3, 0, 3, 2, 1, 2, 3, 0, 2, 1 };
 private int[] stripVertexCounts = { 3, 3, 3, 3 };
 private SimpleUniverse u;
 BranchGroup createSceneGraph() {
   BranchGroup objRoot = new BranchGroup();
   // Set up attributes to render lines
   app = new Appearance();
   transp = new TransparencyAttributes();
   transp.setTransparency(0.5f);
   transp.setCapability(TransparencyAttributes.ALLOW_MODE_WRITE);
   transp.setTransparencyMode(TransparencyAttributes.NONE);
   app.setTransparencyAttributes(transp);
   tetraRegular = createGeometry(1);
   tetraStrip = createGeometry(2);
   tetraIndexed = createGeometry(3);
   tetraIndexedStrip = createGeometry(4);
   geoArrays[0] = tetraRegular;
   geoArrays[1] = tetraStrip;
   geoArrays[2] = tetraIndexed;
   geoArrays[3] = tetraIndexedStrip;
   shape = new Shape3D(tetraRegular, app);
   shape.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
   shape.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
   Transform3D t = new Transform3D();
   // move the object upwards
   t.set(new Vector3f(0.0f, 0.3f, 0.0f));
   // rotate the shape
   Transform3D temp = new Transform3D();
   temp.rotX(Math.PI / 4.0d);
   t.mul(temp);
   temp.rotY(Math.PI / 4.0d);
   t.mul(temp);
   // Shrink the object
   t.setScale(0.6);
   TransformGroup trans = new TransformGroup(t);
   trans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   trans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   objRoot.addChild(trans);
   trans.addChild(shape);
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   // Set up the global lights
   Color3f lColor1 = new Color3f(0.7f, 0.7f, 0.7f);
   Vector3f lDir1 = new Vector3f(-1.0f, -1.0f, -1.0f);
   Color3f alColor = new Color3f(0.2f, 0.2f, 0.2f);
   AmbientLight aLgt = new AmbientLight(alColor);
   aLgt.setInfluencingBounds(bounds);
   DirectionalLight lgt1 = new DirectionalLight(lColor1, lDir1);
   lgt1.setInfluencingBounds(bounds);
   objRoot.addChild(aLgt);
   objRoot.addChild(lgt1);
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 }
 JPanel createGeometryByReferencePanel() {
   JPanel panel = new JPanel();
   panel.setBorder(new TitledBorder("Geometry Type"));
   String values[] = { "Array", "Strip", "Indexed", "IndexedStrip" };
   geomType = new JComboBox(values);
   geomType.setLightWeightPopupEnabled(false);
   geomType.addActionListener(this);
   geomType.setSelectedIndex(0);
   panel.add(new JLabel("Geometry Type"));
   panel.add(geomType);
   String vertex_types[] = { "Float", "P3F" };
   vertexType = new JComboBox(vertex_types);
   vertexType.setLightWeightPopupEnabled(false);
   vertexType.addActionListener(this);
   vertexType.setSelectedIndex(0);
   panel.add(new JLabel("VertexType"));
   panel.add(vertexType);
   String color_types[] = { "Float", "C3F" };
   colorType = new JComboBox(color_types);
   colorType.setLightWeightPopupEnabled(false);
   colorType.addActionListener(this);
   colorType.setSelectedIndex(0);
   panel.add(new JLabel("ColorType"));
   panel.add(colorType);
   return panel;
 }
 JPanel createUpdatePanel() {
   JPanel panel = new JPanel();
   panel.setBorder(new TitledBorder("Other Attributes"));
   String updateComp[] = { "None", "Geometry", "Color" };
   transparency = new JCheckBox("EnableTransparency", false);
   transparency.addActionListener(this);
   panel.add(transparency);
   updates = new JComboBox(updateComp);
   updates.setLightWeightPopupEnabled(false);
   updates.addActionListener(this);
   updates.setSelectedIndex(0);
   panel.add(new JLabel("UpdateData"));
   panel.add(updates);
   return panel;
 }
 public GeometryByReferenceTest() {
 }
 public void init() {
   Container contentPane = getContentPane();
   Canvas3D c = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
   contentPane.add("Center", c);
   BranchGroup scene = createSceneGraph();
   // SimpleUniverse is a Convenience Utility class
   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.
   viewingPlatform.setNominalViewingTransform();
   u.addBranchGraph(scene);
   // add Orbit behavior to the ViewingPlatform
   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);
   // Create GUI
   JPanel p = new JPanel();
   BoxLayout boxlayout = new BoxLayout(p, BoxLayout.Y_AXIS);
   p.add(createGeometryByReferencePanel());
   p.add(createUpdatePanel());
   p.setLayout(boxlayout);
   contentPane.add("South", p);
 }
 public void destroy() {
   u.cleanup();
 }
 public void actionPerformed(ActionEvent e) {
   Object target = e.getSource();
   GeometryArray geo;
   boolean setColor = false, setVertex = false;
   if (target == geomType) {
     geo = geoArrays[geomType.getSelectedIndex()];
     // Set everything to null, and set it later ..
     geo.setColorRefFloat(null);
     geo.setColorRef3f(null);
     geo.setCoordRefFloat(null);
     geo.setCoordRef3f(null);
     shape.setGeometry(geoArrays[geomType.getSelectedIndex()]);
     setColor = true;
     setVertex = true;
   } else if (target == transparency) {
     if (transparency.isSelected()) {
       transp.setTransparencyMode(TransparencyAttributes.BLENDED);
     } else {
       transp.setTransparencyMode(TransparencyAttributes.NONE);
     }
   } else if (target == updates) {
     updateIndex = updates.getSelectedIndex();
     if (updateIndex == 1) {
       System.out.println("Doing coordinate update");
       ((GeometryArray) (shape.getGeometry())).updateData(this);
     } else if (updateIndex == 2) {
       System.out.println("Doing color update");
       ((GeometryArray) (shape.getGeometry())).updateData(this);
     }
   } else if (target == vertexType) {
     geo = ((GeometryArray) shape.getGeometry());
     if (vertexIndex == 0) {
       geo.setCoordRefFloat(null);
     } else if (vertexIndex == 1) {
       geo.setCoordRef3f(null);
     }
     vertexIndex = vertexType.getSelectedIndex();
     setVertex = true;
   } else if (target == colorType) {
     geo = (GeometryArray) shape.getGeometry();
     if (colorIndex == 0) {
       geo.setColorRefFloat(null);
     } else if (colorIndex == 1) {
       geo.setColorRef3f(null);
     }
     colorIndex = colorType.getSelectedIndex();
     setColor = true;
   }
   if (setVertex) {
     geo = (GeometryArray) shape.getGeometry();
     if (vertexIndex == 0) {
       if (geo instanceof IndexedGeometryArray)
         geo.setCoordRefFloat(indexedFloatVerts);
       else
         geo.setCoordRefFloat(floatVerts);
     } else if (vertexIndex == 1) {
       if (geo instanceof IndexedGeometryArray)
         geo.setCoordRef3f(indexedP3fVerts);
       else
         geo.setCoordRef3f(p3fVerts);
     }
   }
   if (setColor) {
     geo = (GeometryArray) shape.getGeometry();
     if (colorIndex == 0) {
       if (geo instanceof IndexedGeometryArray)
         geo.setColorRefFloat(indexedFloatClrs);
       else
         geo.setColorRefFloat(floatClrs);
     } else if (colorIndex == 1) {
       if (geo instanceof IndexedGeometryArray)
         geo.setColorRef3f(indexedC3fClrs);
       else
         geo.setColorRef3f(c3fClrs);
     }
   }
 }
 public static void main(String[] args) {
   Frame frame = new MainFrame(new GeometryByReferenceTest(), 800, 800);
 }
 public GeometryArray createGeometry(int type) {
   GeometryArray tetra = null;
   if (type == 1) {
     tetra = new TriangleArray(12, TriangleArray.COORDINATES
         | TriangleArray.COLOR_3 | TriangleArray.BY_REFERENCE);
     tetra.setCoordRefFloat(floatVerts);
     tetra.setColorRefFloat(floatClrs);
   } else if (type == 2) {
     tetra = new TriangleStripArray(12, TriangleStripArray.COORDINATES
         | TriangleStripArray.COLOR_3
         | TriangleStripArray.BY_REFERENCE, stripVertexCounts);
     tetra.setCoordRefFloat(floatVerts);
     tetra.setColorRefFloat(floatClrs);
   } else if (type == 3) { // Indexed Geometry
     tetra = new IndexedTriangleArray(4,
         IndexedTriangleArray.COORDINATES
             | IndexedTriangleArray.COLOR_3
             | IndexedTriangleArray.BY_REFERENCE, 12);
     tetra.setCoordRefFloat(indexedFloatVerts);
     tetra.setColorRefFloat(indexedFloatClrs);
     ((IndexedTriangleArray) tetra).setCoordinateIndices(0, indices);
     ((IndexedTriangleArray) tetra).setColorIndices(0, indices);
   } else if (type == 4) { // Indexed strip geometry
     tetra = new IndexedTriangleStripArray(4,
         IndexedTriangleStripArray.COORDINATES
             | IndexedTriangleStripArray.COLOR_3
             | IndexedTriangleStripArray.BY_REFERENCE, 12,
         stripVertexCounts);
     tetra.setCoordRefFloat(indexedFloatVerts);
     tetra.setColorRefFloat(indexedFloatClrs);
     ((IndexedTriangleStripArray) tetra)
         .setCoordinateIndices(0, indices);
     ((IndexedTriangleStripArray) tetra).setColorIndices(0, indices);
   }
   if (tetra != null)
     tetra.setCapability(GeometryArray.ALLOW_REF_DATA_WRITE);
   return tetra;
 }
 public void updateData(Geometry geometry) {
   int i;
   float val;
   if (updateIndex == 1) { // geometry
     // Translate the geometry by a small amount in x
     vertexCount++;
     if ((vertexCount & 1) == 1)
       val = 0.2f;
     else
       val = -0.2f;
     if (vertexIndex == 0) {
       // Do Indexed geometry
       for (i = 0; i < indexedFloatVerts.length; i += 3) {
         indexedFloatVerts[i] += val;
       }
       // Do non-indexed float geometry
       for (i = 0; i < floatVerts.length; i += 3) {
         floatVerts[i] += val;
       }
     } else {
       // If p3f do each point only once
       for (i = 0; i < indexedP3fVerts.length; i++) {
         indexedP3fVerts[i].x += val;
       }
     }
   } else if (updateIndex == 2) { // colors
     colorCount++;
     if ((colorCount & 1) == 1)
       val = 0.4f;
     else
       val = -0.4f;
     if (colorIndex == 0) {
       // Do Indexed geometry
       for (i = 0; i < indexedFloatClrs.length; i += 3) {
         indexedFloatClrs[i] += val;
       }
       // Do non-indexed float geometry
       for (i = 0; i < floatClrs.length; i += 3) {
         floatClrs[i] += val;
       }
     } else {
       // If c3f do each point only once
       for (i = 0; i < indexedC3fClrs.length; i++) {
         indexedC3fClrs[i].x += val;
       }
     }
   }
 }

}


      </source>
   
  
 
  



Gouraud

   <source lang="java">

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import java.awt.GraphicsConfiguration; import java.io.FileNotFoundException; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import com.sun.j3d.loaders.IncorrectFormatException; import com.sun.j3d.loaders.ParsingErrorException; import com.sun.j3d.loaders.Scene; import com.sun.j3d.loaders.objectfile.ObjectFile; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.universe.SimpleUniverse; /**

* !Diese Klasse wurde fur das Laden uber ein JAR-Archiv oder Applet welches ein
* JAR - Archiv nutzt angepasst Um das Programm als einfache Applikation uber
* einen class-File laufen zu lassen bitte auf den Code zum Einladen der OBJ
* Datei im Tutorial zuruckgreifen!
*/

public class Gouraud extends Applet {

 /**
  * init Methoden fur die Darstellung als Applet Es muss also kein extra
  * Konstruktor definert werden
  */
 public void init() {
   setLayout(new BorderLayout());
   GraphicsConfiguration config = SimpleUniverse
       .getPreferredConfiguration();
   canvas3D = new Canvas3D(config);
   add("Center", canvas3D);
   BranchGroup szene = macheSzene();
   szene.rupile();
   universe = new SimpleUniverse(canvas3D);
   universe.getViewingPlatform().setNominalViewingTransform();
   universe.addBranchGraph(szene);
 }
 /**
  * Erstellt den Szenegraphen
  * 
  * @return BranchGroup
  */
 public BranchGroup macheSzene() {
   BranchGroup objWurzel = new BranchGroup();
   // Transformation, 2 Rotationen:
   Transform3D drehung = new Transform3D();
   Transform3D drehung2 = new Transform3D();
   drehung.rotX(Math.PI / 4.0d);
   drehung2.rotY(Math.PI / 5.0d);
   drehung.mul(drehung2);
   TransformGroup objDreh = new TransformGroup(drehung);
   //Loader
   ObjectFile file = new ObjectFile(ObjectFile.RESIZE);
   Scene scene = null;
   try {
     // Laden der Obj Datei mittels jar
     scene = file.load(ClassLoader.getSystemResource("teapot.obj"));
   } catch (Exception e) {
     System.err.println(e);
     System.exit(1);
   }
   objDreh.addChild(scene.getSceneGroup());
   DirectionalLight d_Licht = new DirectionalLight(new Color3f(1.0f, 1.0f,
       1.0f), new Vector3f(-1.0f, -1.0f, -1.0f));
   d_Licht.setInfluencingBounds(new BoundingSphere(new Point3d(0.0d, 0.0d,
       0.0d), 100.0d));
   objDreh.addChild(d_Licht);
   objWurzel.addChild(objDreh);
   return objWurzel;
 }
 /**
  * gibt speicher frei
  */
 public void destroy() {
   universe.removeAllLocales();
 }
 public static void main(String[] args) {
   frame = new MainFrame(new Gouraud(), 500, 500);
   frame.setTitle("Gouraud");
 }
 //---- Attribute -----------------------
 private SimpleUniverse universe;
 private Canvas3D canvas3D;
 private static Frame frame;

}

//File: minimart3.mtl /* newmtl 0_4 Kd 0.8 0.1 0.1 illum 1

  • /

//File: teapot.obj /* mtllib minimart3.mtl usemtl 0_4 v 0.297884 1.715014 0.075692 v 0.018884 1.738014 0.075722 v 0.287884 1.714913 0.150691 v 0.259884 1.714823 0.217691 v 0.216884 1.714748 0.273691 v 0.160884 1.714690 0.316691 v 0.093884 1.714653 0.344691 v 0.018884 1.714639 0.354691 v -0.056116 1.714653 0.344691 v -0.123116 1.714690 0.316691 v -0.179116 1.714748 0.273691 v -0.222116 1.714823 0.217691 v -0.250116 1.714913 0.150691 v -0.260116 1.715014 0.075692 v -0.250116 1.715114 0.000692 v -0.222116 1.715204 -0.066308 v -0.179116 1.715279 -0.122308 v -0.123116 1.715337 -0.165308 v -0.056116 1.715374 -0.193308 v 0.018884 1.715388 -0.203308 v 0.093884 1.715374 -0.193308 v 0.160884 1.715337 -0.165308 v 0.216884 1.715279 -0.122308 v 0.259884 1.715204 -0.066308 v 0.287884 1.715114 0.000692 v 0.381884 1.655013 0.075611 v 0.368884 1.654882 0.173611 v 0.332884 1.654765 0.260611 v 0.276884 1.654667 0.333611 v 0.203884 1.654592 0.389611 v 0.116884 1.654544 0.425611 v 0.018884 1.654527 0.438611 v -0.079116 1.654544 0.425611 v -0.166116 1.654592 0.389611 v -0.239116 1.654667 0.333611 v -0.295116 1.654765 0.260611 v -0.331116 1.654882 0.173611 v -0.344116 1.655013 0.075611 v -0.331116 1.655145 -0.022389 v -0.295116 1.655262 -0.109389 v -0.239116 1.655360 -0.182389 v -0.166116 1.655435 -0.238389 v -0.079116 1.655483 -0.274389 v 0.018884 1.655500 -0.287389 v 0.116884 1.655483 -0.274389 v 0.203884 1.655435 -0.238389 v 0.276884 1.655360 -0.182389 v 0.332884 1.655262 -0.109389 v 0.368884 1.655145 -0.022389 v 0.343884 1.569014 0.075496 v 0.332884 1.568896 0.163496 v 0.299884 1.568792 0.240496 v 0.249884 1.568704 0.306495 v 0.183884 1.568637 0.356495 v 0.106884 1.568592 0.389495 v 0.018884 1.568578 0.400495 v -0.069116 1.568592 0.389495 v -0.146116 1.568637 0.356495 v -0.212116 1.568704 0.306495 v -0.262116 1.568792 0.240496 v -0.295116 1.568896 0.163496 v -0.306116 1.569014 0.075496 v -0.295116 1.569132 -0.012504 v -0.262116 1.569235 -0.089504 v -0.212116 1.569323 -0.155504 v -0.146116 1.569390 -0.205504 v -0.069116 1.569435 -0.238504 v 0.018884 1.569449 -0.249504 v 0.106884 1.569435 -0.238504 v 0.183884 1.569390 -0.205504 v 0.249884 1.569323 -0.155504 v 0.299884 1.569235 -0.089504 v 0.332884 1.569132 -0.012504 v 0.255884 1.471014 0.075364 v 0.247884 1.470928 0.139364 v 0.223884 1.470851 0.196364 v 0.186884 1.470788 0.243364 v 0.139884 1.470739 0.280364 v 0.082884 1.470706 0.304364 v 0.018884 1.470696 0.312364 v -0.045116 1.470706 0.304364 v -0.102116 1.470739 0.280364 v -0.149116 1.470788 0.243364 v -0.186116 1.470851 0.196364 v -0.210116 1.470928 0.139364 v -0.218116 1.471014 0.075364 v -0.210116 1.471099 0.011364 v -0.186116 1.471176 -0.045636 v -0.149116 1.471239 -0.092636 v -0.102116 1.471289 -0.129636 v -0.045116 1.471321 -0.153636 v 0.018884 1.471331 -0.161636 v 0.082884 1.471321 -0.153636 v 0.139884 1.471289 -0.129636 v 0.186884 1.471239 -0.092636 v 0.223884 1.471176 -0.045636 v 0.247884 1.471099 0.011364 v 0.189884 1.373014 0.075233 v 0.183884 1.372952 0.121233 v 0.166884 1.372897 0.162233 v 0.140884 1.372850 0.197233 v 0.105884 1.372815 0.223233 v 0.064884 1.372793 0.240233 v 0.018884 1.372784 0.246233 v -0.027116 1.372793 0.240233 v -0.068116 1.372815 0.223233 v -0.103116 1.372850 0.197233 v -0.129116 1.372897 0.162233 v -0.146116 1.372952 0.121233 v -0.152116 1.373014 0.075233 v -0.146116 1.373076 0.029233 v -0.129116 1.373131 -0.011767 v -0.103116 1.373178 -0.046767 v -0.068116 1.373212 -0.072767 v -0.027116 1.373235 -0.089767 v 0.018884 1.373243 -0.095767 v 0.064884 1.373235 -0.089767 v 0.105884 1.373212 -0.072767 v 0.140884 1.373178 -0.046767 v 0.166884 1.373131 -0.011767 v 0.183884 1.373076 0.029233 v 0.218884 1.288014 0.075119 v 0.211884 1.287941 0.129119 v 0.191884 1.287877 0.177119 v 0.160884 1.287823 0.217119 v 0.120884 1.287782 0.248119 v 0.072884 1.287755 0.268119 v 0.018884 1.287746 0.275119 v -0.035116 1.287755 0.268119 v -0.083116 1.287782 0.248119 v -0.123116 1.287823 0.217119 v -0.154116 1.287877 0.177119 v -0.174116 1.287941 0.129119 v -0.181116 1.288014 0.075119 v -0.174116 1.288086 0.021119 v -0.154116 1.288151 -0.026881 v -0.123116 1.288204 -0.066881 v -0.083116 1.288246 -0.097881 v -0.035116 1.288273 -0.117881 v 0.018884 1.288282 -0.124881 v 0.072884 1.288273 -0.117881 v 0.120884 1.288246 -0.097881 v 0.160884 1.288204 -0.066881 v 0.191884 1.288151 -0.026881 v 0.211884 1.288086 0.021119 v 0.369884 1.224014 0.075033 v 0.357884 1.223888 0.169033 v 0.322884 1.223775 0.253033 v 0.267884 1.223680 0.324033 v 0.196884 1.223606 0.379033 v 0.112884 1.223559 0.414033 v 0.018884 1.223543 0.426033 v -0.075116 1.223559 0.414033 v -0.159116 1.223606 0.379033 v -0.230116 1.223680 0.324033 v -0.285116 1.223775 0.253033 v -0.320116 1.223888 0.169033 v -0.332116 1.224014 0.075033 v -0.320116 1.224140 -0.018967 v -0.285116 1.224253 -0.102967 v -0.230116 1.224348 -0.173967 v -0.159116 1.224422 -0.228967 v -0.075116 1.224468 -0.263967 v 0.018884 1.224485 -0.275967 v 0.112884 1.224468 -0.263967 v 0.196884 1.224422 -0.228967 v 0.267884 1.224348 -0.173967 v 0.322884 1.224253 -0.102967 v 0.357884 1.224140 -0.018967 v 0.592884 1.177014 0.074970 v 0.572884 1.176807 0.228970 v 0.515884 1.176622 0.366970 v 0.426884 1.176467 0.482970 v 0.310884 1.176347 0.571970 v 0.172884 1.176271 0.628969 v 0.018884 1.176244 0.648969 v -0.135116 1.176271 0.628969 v -0.273116 1.176347 0.571970 v -0.389116 1.176467 0.482970 v -0.478116 1.176622 0.366970 v -0.535116 1.176807 0.228970 v -0.555116 1.177014 0.074970 v -0.535116 1.177220 -0.079030 v -0.478116 1.177406 -0.217030 v -0.389116 1.177561 -0.333030 v -0.273116 1.177680 -0.422030 v -0.135116 1.177757 -0.479030 v 0.018884 1.177784 -0.499030 v 0.172884 1.177757 -0.479030 v 0.310884 1.177680 -0.422030 v 0.426884 1.177561 -0.333030 v 0.515884 1.177406 -0.217030 v 0.572884 1.177220 -0.079030 v 0.843884 1.138014 0.074918 v 0.814884 1.137716 0.296917 v 0.732884 1.137452 0.493917 v 0.604884 1.137228 0.660917 v 0.437884 1.137056 0.788917 v 0.240884 1.136946 0.870917 v 0.018884 1.136907 0.899917 v -0.203116 1.136946 0.870917 v -0.400116 1.137056 0.788917 v -0.567116 1.137228 0.660917 v -0.695116 1.137452 0.493917 v -0.777116 1.137716 0.296917 v -0.806116 1.138014 0.074918 v -0.777116 1.138312 -0.147082 v -0.695116 1.138576 -0.344082 v -0.567116 1.138800 -0.511082 v -0.400116 1.138972 -0.639082 v -0.203116 1.139081 -0.721082 v 0.018884 1.139120 -0.750082 v 0.240884 1.139081 -0.721082 v 0.437884 1.138972 -0.639082 v 0.604884 1.138800 -0.511082 v 0.732884 1.138576 -0.344082 v 0.814884 1.138312 -0.147082 v 1.077884 1.099014 0.074865 v 1.040884 1.098633 0.358865 v 0.934884 1.098292 0.612865 v 0.770884 1.098005 0.826865 v 0.556884 1.097785 0.990865 v 0.302884 1.097643 1.096864 v 0.018884 1.097594 1.133864 v -0.265116 1.097643 1.096864 v -0.519116 1.097785 0.990865 v -0.733116 1.098005 0.826865 v -0.897116 1.098292 0.612865 v -1.003116 1.098633 0.358865 v -1.040116 1.099014 0.074865 v -1.003116 1.099395 -0.209134 v -0.897116 1.099735 -0.463134 v -0.733116 1.100023 -0.677134 v -0.519116 1.100242 -0.841134 v -0.265116 1.100385 -0.947134 v 0.018884 1.100434 -0.984134 v 0.302884 1.100385 -0.947134 v 0.556884 1.100242 -0.841134 v 0.770884 1.100023 -0.677134 v 0.934884 1.099735 -0.463134 v 1.040884 1.099395 -0.209134 v 1.250884 1.052014 0.074802 v 1.207884 1.051570 0.405802 v 1.084884 1.051175 0.700802 v 0.893884 1.050840 0.949802 v 0.644884 1.050584 1.140801 v 0.349884 1.050419 1.263801 v 0.018884 1.050362 1.306801 v -0.312116 1.050419 1.263801 v -0.607116 1.050584 1.140801 v -0.856116 1.050840 0.949802 v -1.047116 1.051175 0.700802 v -1.170116 1.051570 0.405802 v -1.213116 1.052014 0.074802 v -1.170116 1.052458 -0.256197 v -1.047116 1.052854 -0.551197 v -0.856116 1.053188 -0.800197 v -0.607116 1.053444 -0.991197 v -0.312116 1.053609 -1.114197 v 0.018884 1.053666 -1.157197 v 0.349884 1.053609 -1.114197 v 0.644884 1.053444 -0.991197 v 0.893884 1.053188 -0.800197 v 1.084884 1.052854 -0.551197 v 1.207884 1.052458 -0.256197 v 1.318884 0.988014 0.074717 v 1.272884 0.987546 0.423716 v 1.143884 0.987128 0.735716 v 0.941884 0.986776 0.997716 v 0.679884 0.986505 1.199715 v 0.367884 0.986332 1.328715 v 0.018884 0.986271 1.374715 v -0.330116 0.986332 1.328715 v -0.642116 0.986505 1.199715 v -0.904116 0.986776 0.997716 v -1.106116 0.987128 0.735716 v -1.235116 0.987546 0.423716 v -1.281116 0.988014 0.074717 v -1.235116 0.988482 -0.274283 v -1.106116 0.988901 -0.586283 v -0.904116 0.989252 -0.848283 v -0.642116 0.989523 -1.050282 v -0.330116 0.989696 -1.179282 v 0.018884 0.989758 -1.225282 v 0.367884 0.989696 -1.179282 v 0.679884 0.989523 -1.050282 v 0.941884 0.989252 -0.848283 v 1.143884 0.988901 -0.586283 v 1.272884 0.988482 -0.274283 v 1.416738 -1.218998 0.059079 v 1.367738 -1.219503 0.435078 v 1.397738 -1.163999 0.059152 v 1.349738 -1.164496 0.430152 v 1.227738 -1.219952 0.770078 v 1.211738 -1.164940 0.761152 v 1.010738 -1.220332 1.053078 v 0.997738 -1.165314 1.040151 v 0.727738 -1.220623 1.270077 v 0.718738 -1.165601 1.254151 v 0.392738 -1.220810 1.410077 v 0.387738 -1.165786 1.392151 v 0.016738 -1.220876 1.459077 v 0.016738 -1.165851 1.440151 v -0.359262 -1.220810 1.410077 v -0.354262 -1.165786 1.392151 v -0.694262 -1.220623 1.270077 v -0.685262 -1.165601 1.254151 v -0.977262 -1.220332 1.053078 v -0.964262 -1.165314 1.040151 v -1.194262 -1.219952 0.770078 v -1.178262 -1.164940 0.761152 v -1.334262 -1.219503 0.435078 v -1.316262 -1.164496 0.430152 v -1.383262 -1.218998 0.059079 v -1.364262 -1.163999 0.059152 v 1.400738 -1.130999 0.059197 v 1.352738 -1.131498 0.431196 v 1.214738 -1.131942 0.762196 v 0.999738 -1.132317 1.042196 v 0.719738 -1.132605 1.257195 v 0.388738 -1.132790 1.395195 v 0.016738 -1.132855 1.443195 v -0.355262 -1.132790 1.395195 v -0.686262 -1.132605 1.257195 v -0.966262 -1.132317 1.042196 v -1.181262 -1.131942 0.762196 v -1.319262 -1.131498 0.431196 v -1.367262 -1.130999 0.059197 v 1.419738 -1.120999 0.059210 v 1.370738 -1.121504 0.436210 v 1.230738 -1.121955 0.772209 v 1.012738 -1.122334 1.055209 v 0.729738 -1.122627 1.273209 v 0.393738 -1.122815 1.413209 v 0.016738 -1.122880 1.462209 v -0.360262 -1.122815 1.413209 v -0.696262 -1.122627 1.273209 v -0.979262 -1.122334 1.055209 v -1.197262 -1.121955 0.772209 v -1.337262 -1.121504 0.436210 v -1.386262 -1.120999 0.059210 v 1.448738 -1.130999 0.059197 v 1.398738 -1.131515 0.444196 v 1.255738 -1.131975 0.787196 v 1.033738 -1.132363 1.076196 v 0.744738 -1.132660 1.298195 v 0.401738 -1.132852 1.441195 v 0.016738 -1.132919 1.491195 v -0.368262 -1.132852 1.441195 v -0.711262 -1.132660 1.298195 v -1.000262 -1.132363 1.076196 v -1.222262 -1.131975 0.787196 v -1.365262 -1.131515 0.444196 v -1.415262 -1.130999 0.059197 v 1.483738 -1.163999 0.059152 v 1.431738 -1.164527 0.453152 v 1.285738 -1.164998 0.804152 v 1.057738 -1.165395 1.100151 v 0.761738 -1.165701 1.328151 v 0.410738 -1.165896 1.474151 v 0.016738 -1.165966 1.526151 v -0.377262 -1.165896 1.474151 v -0.728262 -1.165701 1.328151 v -1.024262 -1.165395 1.100151 v -1.252262 -1.164998 0.804152 v -1.398262 -1.164527 0.453152 v -1.450262 -1.163999 0.059152 v -1.334262 -1.218494 -0.316921 v -1.194262 -1.218045 -0.651921 v -0.977262 -1.217665 -0.934921 v -0.694262 -1.217374 -1.151920 v -0.359262 -1.217187 -1.291920 v 0.016738 -1.217121 -1.340920 v 0.392738 -1.217187 -1.291920 v 0.727738 -1.217374 -1.151920 v 1.010738 -1.217665 -0.934921 v 1.227738 -1.218045 -0.651921 v 1.367738 -1.218494 -0.316921 v -1.316262 -1.163501 -0.311847 v -1.178262 -1.163057 -0.642847 v -0.964262 -1.162683 -0.921847 v -0.685262 -1.162396 -1.135847 v -0.354262 -1.162211 -1.273847 v 0.016738 -1.162146 -1.321846 v 0.387738 -1.162211 -1.273847 v 0.718738 -1.162396 -1.135847 v 0.997738 -1.162683 -0.921847 v 1.211738 -1.163057 -0.642847 v 1.349738 -1.163501 -0.311847 v -1.319262 -1.130500 -0.312803 v -1.181262 -1.130056 -0.643803 v -0.966262 -1.129680 -0.923803 v -0.686262 -1.129392 -1.138802 v -0.355262 -1.129207 -1.276802 v 0.016738 -1.129143 -1.324802 v 0.388738 -1.129207 -1.276802 v 0.719738 -1.129392 -1.138802 v 0.999738 -1.129680 -0.923803 v 1.214738 -1.130056 -0.643803 v 1.352738 -1.130500 -0.312803 v -1.337262 -1.120493 -0.317790 v -1.197262 -1.120042 -0.653789 v -0.979262 -1.119663 -0.936789 v -0.696262 -1.119371 -1.154789 v -0.360262 -1.119183 -1.294789 v 0.016738 -1.119117 -1.343789 v 0.393738 -1.119183 -1.294789 v 0.729738 -1.119371 -1.154789 v 1.012738 -1.119663 -0.936789 v 1.230738 -1.120042 -0.653789 v 1.370738 -1.120493 -0.317790 v -1.365262 -1.130482 -0.325803 v -1.222262 -1.130022 -0.668803 v -1.000262 -1.129635 -0.957802 v -0.711262 -1.129337 -1.179802 v -0.368262 -1.129145 -1.322802 v 0.016738 -1.129078 -1.372802 v 0.401738 -1.129145 -1.322802 v 0.744738 -1.129337 -1.179802 v 1.033738 -1.129635 -0.957802 v 1.255738 -1.130022 -0.668803 v 1.398738 -1.130482 -0.325803 v -1.398262 -1.163470 -0.334847 v -1.252262 -1.163000 -0.685847 v -1.024262 -1.162603 -0.981847 v -0.728262 -1.162297 -1.209847 v -0.377262 -1.162101 -1.355846 v 0.016738 -1.162031 -1.407846 v 0.410738 -1.162101 -1.355846 v 0.761738 -1.162297 -1.209847 v 1.057738 -1.162603 -0.981847 v 1.285738 -1.163000 -0.685847 v 1.431738 -1.163470 -0.334847 v -1.483262 -1.218998 0.059079 v -1.430262 -1.218458 -0.343921 v -1.281262 -1.217976 -0.702921 v -1.048262 -1.217570 -1.005921 v -0.745262 -1.217258 -1.238920 v -0.386262 -1.217058 -1.387920 v 0.016738 -1.216987 -1.440920 v 0.419738 -1.217058 -1.387920 v 0.778738 -1.217258 -1.238920 v 1.081738 -1.217570 -1.005921 v 1.314738 -1.217976 -0.702921 v 1.463738 -1.218458 -0.343921 v 1.516738 -1.218998 0.059079 v 1.700000 -0.113500 0.327255 v 1.700000 -0.174869 0.602173 v 2.059000 -0.062500 0.327324 v 2.072000 -0.113851 0.589255 v 1.700000 -0.328090 0.766968 v 2.106000 -0.242063 0.747083 v 1.700000 -0.526163 0.821702 v 2.150000 -0.408133 0.798861 v 1.700000 -0.725089 0.766435 v 2.195000 -0.574063 0.746638 v 1.700000 -0.877868 0.601230 v 2.229000 -0.701851 0.588466 v 1.700000 -0.938499 0.326149 v 2.242000 -0.753499 0.326397 v 1.700000 -0.877130 0.051231 v 2.229000 -0.701148 0.064467 v 1.700000 -0.723909 -0.113564 v 2.195000 -0.572936 -0.093361 v 1.700000 -0.524836 -0.168297 v 2.150000 -0.406867 -0.145139 v 1.700000 -0.326910 -0.113031 v 2.106000 -0.240936 -0.092916 v 1.700000 -0.174131 0.052174 v 2.072000 -0.113149 0.065256 v 2.270000 0.072500 0.327505 v 2.290000 0.033190 0.558452 v 2.340000 -0.064995 0.696321 v 2.404000 -0.192056 0.742150 v 2.468000 -0.318995 0.695980 v 2.517000 -0.416809 0.557849 v 2.537000 -0.455500 0.326797 v 2.517000 -0.416190 0.095849 v 2.468000 -0.318005 -0.042019 v 2.404000 -0.190943 -0.087849 v 2.340000 -0.064005 -0.041679 v 2.290000 0.033810 0.096453 v 2.387000 0.261500 0.327758 v 2.410000 0.235245 0.517723 v 2.465000 0.169093 0.630635 v 2.537000 0.083043 0.668519 v 2.610000 -0.002906 0.630404 v 2.665000 -0.068755 0.517315 v 2.687000 -0.094500 0.327281 v 2.665000 -0.068245 0.137316 v 2.610000 -0.002094 0.024404 v 2.538000 0.083957 -0.013480 v 2.465000 0.169906 0.024635 v 2.410000 0.235755 0.137723 v 2.388000 0.261500 0.327758 v 2.463000 0.475500 0.328045 v 2.488000 0.460301 0.476025 v 2.549000 0.424180 0.565977 v 2.630000 0.376142 0.594912 v 2.710000 0.329181 0.565849 v 2.772000 0.292301 0.475800 v 2.796000 0.278500 0.327781 v 2.772000 0.292698 0.179800 v 2.710000 0.329819 0.089850 v 2.630000 0.376858 0.060913 v 2.549000 0.424819 0.089977 v 2.488000 0.460698 0.180025 v 2.550000 0.685499 0.328327 v 2.580000 0.679342 0.445319 v 2.658000 0.666249 0.515301 v 2.758000 0.649218 0.538278 v 2.858000 0.632249 0.515256 v 2.935000 0.618343 0.445237 v 2.966000 0.613499 0.328230 v 2.935000 0.618656 0.211237 v 2.858000 0.632750 0.141256 v 2.758000 0.649781 0.118279 v 2.658000 0.666750 0.141302 v 2.580000 0.679656 0.211319 v 2.700000 0.861499 0.328563 v 2.744000 0.861360 0.432563 v 2.856000 0.861275 0.495563 v 3.000000 0.861247 0.516563 v 3.144000 0.861275 0.495563 v 3.256000 0.861360 0.432563 v 3.300000 0.861499 0.328563 v 3.256000 0.861639 0.224563 v 3.144000 0.861723 0.161563 v 3.000000 0.861751 0.140563 v 2.856000 0.861723 0.161563 v 2.744000 0.861639 0.224563 v 2.749000 0.892499 0.328604 v 2.796000 0.893364 0.429606 v 2.915000 0.895282 0.490608 v 3.069000 0.897255 0.510611 v 3.222000 0.899282 0.490614 v 3.341000 0.901364 0.429616 v 3.388000 0.901499 0.328617 v 3.341000 0.901635 0.227617 v 3.222000 0.899716 0.166614 v 3.069000 0.897743 0.146611 v 2.915000 0.895716 0.166609 v 2.796000 0.893635 0.227606 v 2.793000 0.911499 0.328630 v 2.840000 0.912374 0.421631 v 2.958000 0.915299 0.477635 v 3.111000 0.919274 0.496641 v 3.264000 0.923299 0.477646 v 3.382000 0.926374 0.421650 v 3.430000 0.928499 0.328653 v 3.382000 0.926624 0.235650 v 3.264000 0.923699 0.179646 v 3.111000 0.919724 0.160641 v 2.958000 0.915699 0.179635 v 2.840000 0.912624 0.235631 v 2.825000 0.917499 0.328638 v 2.870000 0.919388 0.411641 v 2.981000 0.923321 0.461646 v 3.127000 0.928298 0.478653 v 3.272000 0.933321 0.461659 v 3.383000 0.937388 0.411665 v 3.428000 0.938499 0.328666 v 3.383000 0.937611 0.245665 v 3.272000 0.933677 0.195660 v 3.127000 0.928700 0.178653 v 2.981000 0.923677 0.195646 v 2.870000 0.919610 0.245641 v 2.841000 0.911499 0.328630 v 2.881000 0.913401 0.401633 v 2.982000 0.916342 0.445637 v 3.114000 0.921322 0.460643 v 3.245000 0.926342 0.445650 v 3.347000 0.930401 0.401655 v 3.387000 0.932499 0.328658 v 3.347000 0.930597 0.255655 v 3.245000 0.926656 0.211650 v 3.114000 0.921676 0.196643 v 2.982000 0.916656 0.211637 v 2.881000 0.913597 0.255633 v 2.834000 0.892499 0.328604 v 2.869000 0.893411 0.394606 v 2.958000 0.896358 0.433610 v 3.072000 0.899341 0.446614 v 3.187000 0.903358 0.433619 v 3.275000 0.906411 0.394623 v 3.310000 0.907499 0.328625 v 3.275000 0.906588 0.262623 v 3.187000 0.903640 0.223619 v 3.072000 0.899657 0.210614 v 2.958000 0.896640 0.223610 v 2.869000 0.893588 0.262606 v 2.800000 0.861499 0.328563 v 2.830000 0.861415 0.391563 v 2.904000 0.861365 0.428563 v 3.000000 0.861349 0.440563 v 3.096000 0.861365 0.428563 v 3.170000 0.861415 0.391563 v 3.200000 0.861499 0.328563 v 3.170000 0.861584 0.265563 v 3.096000 0.861633 0.228563 v 3.000000 0.861650 0.216563 v 2.904000 0.861633 0.228563 v 2.830000 0.861584 0.265563 v -1.486195 0.600000 0.214712 v -1.479195 0.616832 0.339735 v -1.811195 0.599000 0.214711 v -1.813195 0.615832 0.339733 v -1.460195 0.657731 0.414790 v -1.819195 0.656731 0.414788 v -1.436195 0.712698 0.439863 v -1.827195 0.710698 0.439861 v -1.412195 0.766731 0.414936 v -1.836195 0.764731 0.414933 v -1.393195 0.807832 0.339991 v -1.842195 0.805832 0.339988 v -1.386195 0.824999 0.215014 v -1.844195 0.822999 0.215011 v -1.393195 0.808167 0.089991 v -1.842195 0.806167 0.089989 v -1.412195 0.767268 0.014936 v -1.836195 0.765268 0.014934 v -1.436195 0.713301 -0.010136 v -1.827195 0.711301 -0.010139 v -1.460195 0.658268 0.014790 v -1.819195 0.657268 0.014789 v -1.479195 0.617167 0.089735 v -1.813195 0.616167 0.089734 v -2.082195 0.592000 0.214701 v -2.092195 0.607832 0.339723 v -2.118195 0.647731 0.414776 v -2.151195 0.699698 0.439846 v -2.184195 0.751731 0.414916 v -2.209195 0.791832 0.339969 v -2.219195 0.807999 0.214991 v -2.209195 0.792167 0.089970 v -2.184195 0.752268 0.014916 v -2.151195 0.700301 -0.010154 v -2.118195 0.648268 0.014777 v -2.092195 0.608167 0.089723 v -2.298195 0.572000 0.214675 v -2.314195 0.585832 0.339693 v -2.354195 0.622731 0.414743 v -2.405195 0.669698 0.439806 v -2.456195 0.717731 0.414870 v -2.495195 0.753832 0.339918 v -2.511195 0.768999 0.214939 v -2.495195 0.754167 0.089919 v -2.456195 0.718268 0.014871 v -2.405195 0.670301 -0.010194 v -2.354195 0.623268 0.014743 v -2.314195 0.586167 0.089693 v -2.456195 0.533000 0.214622 v -2.476195 0.544832 0.339638 v -2.525195 0.573731 0.414677 v -2.588195 0.612698 0.439729 v -2.651195 0.650731 0.414780 v -2.700195 0.679832 0.339819 v -2.719195 0.692000 0.214835 v -2.700195 0.680167 0.089820 v -2.651195 0.651268 0.014781 v -2.588195 0.613301 -0.010270 v -2.525195 0.574268 0.014677 v -2.476195 0.545167 0.089638 v -2.553195 0.470000 0.214538 v -2.575195 0.476832 0.339547 v -2.629195 0.493731 0.414570 v -2.699195 0.516698 0.439601 v -2.769195 0.539731 0.414631 v -2.823195 0.557832 0.339656 v -2.844195 0.565000 0.214665 v -2.823195 0.558167 0.089656 v -2.769195 0.540268 0.014632 v -2.699195 0.517301 -0.010399 v -2.629195 0.494268 0.014570 v -2.575195 0.477167 0.089547 v -2.586195 0.375000 0.214410 v -2.608195 0.374832 0.339410 v -2.664195 0.374731 0.414410 v -2.736195 0.374698 0.439410 v -2.808195 0.374731 0.414410 v -2.864195 0.374832 0.339410 v -2.886195 0.375000 0.214410 v -2.864195 0.375167 0.089410 v -2.808195 0.375268 0.014411 v -2.736195 0.375301 -0.010590 v -2.664195 0.375268 0.014411 v -2.608195 0.375167 0.089410 v -2.569195 0.246000 0.214237 v -2.590195 0.238832 0.339228 v -2.643195 0.221732 0.414205 v -2.713195 0.199698 0.439175 v -2.782195 0.176732 0.414145 v -2.835195 0.159832 0.339122 v -2.857195 0.153000 0.214113 v -2.835195 0.160168 0.089122 v -2.782195 0.177268 0.014145 v -2.713195 0.200302 -0.010824 v -2.643195 0.222268 0.014205 v -2.590195 0.239168 0.089228 v -2.516195 0.092000 0.214031 v -2.534195 0.079832 0.339015 v -2.581195 0.051732 0.413977 v -2.642195 0.014698 0.438927 v -2.702195 -0.022268 0.413878 v -2.749195 -0.050168 0.338840 v -2.767195 -0.061000 0.213826 v -2.749195 -0.049832 0.088840 v -2.702195 -0.021732 0.013878 v -2.642195 0.015302 -0.011072 v -2.581195 0.052268 0.013977 v -2.534195 0.080168 0.089015 v -2.423195 -0.075000 0.213807 v -2.438195 -0.089168 0.338788 v -2.474195 -0.125268 0.413740 v -2.520195 -0.171302 0.438678 v -2.567195 -0.217268 0.413616 v -2.603195 -0.253167 0.338568 v -2.617195 -0.267000 0.213549 v -2.603195 -0.252832 0.088568 v -2.567195 -0.216732 0.013617 v -2.520195 -0.170698 -0.011322 v -2.474195 -0.124732 0.013740 v -2.438195 -0.088832 0.088788 v -2.290195 -0.242000 0.213583 v -2.298195 -0.258167 0.338561 v -2.319195 -0.299268 0.413506 v -2.347195 -0.353301 0.438434 v -2.375195 -0.406268 0.413363 v -2.396195 -0.447167 0.338308 v -2.405195 -0.463999 0.213285 v -2.396195 -0.446832 0.088308 v -2.375195 -0.405731 0.013363 v -2.347195 -0.352698 -0.011566 v -2.319195 -0.298731 0.013507 v -2.298195 -0.257832 0.088562 v -2.111195 -0.396000 0.213376 v -2.113195 -0.415167 0.338351 v -2.116195 -0.462268 0.413288 v -2.120195 -0.523301 0.438206 v -2.124195 -0.584268 0.413124 v -2.127195 -0.631167 0.338061 v -2.128195 -0.649999 0.213036 v -2.127195 -0.630832 0.088061 v -2.124195 -0.583731 0.013124 v -2.120195 -0.522698 -0.011794 v -2.116195 -0.461731 0.013288 v -2.113195 -0.414832 0.088351 v -1.886195 -0.524999 0.213203 v -1.879195 -0.547167 0.338174 v -1.860195 -0.603268 0.413098 v -1.836195 -0.675301 0.438002 v -1.812195 -0.747267 0.412905 v -1.793195 -0.803167 0.337830 v -1.786195 -0.824999 0.212801 v -1.793195 -0.802832 0.087831 v -1.812195 -0.746731 0.012906 v -1.836195 -0.674698 -0.011998 v -1.860195 -0.602731 0.013099 v -1.879195 -0.546832 0.088174 v 1.500000 1.124999 0.065416 v 1.447000 1.124459 0.468416 v 1.624000 0.862999 0.065065 v 1.567000 0.862414 0.501065 v 1.298000 1.123977 0.827416 v 1.405000 0.861893 0.890064 v 1.065000 1.123571 1.130415 v 1.153000 0.861453 1.218064 v 0.762000 1.123258 1.363415 v 0.825000 0.861115 1.470064 v 0.403000 1.123058 1.512415 v 0.436000 0.860898 1.632064 v 0.000000 1.122987 1.565415 v 0.000000 0.860821 1.689063 v -0.403000 1.123058 1.512415 v -0.436000 0.860898 1.632064 v -0.762000 1.123258 1.363415 v -0.825000 0.861115 1.470064 v -1.065000 1.123571 1.130415 v -1.153000 0.861453 1.218064 v -1.298000 1.123977 0.827416 v -1.405000 0.861893 0.890064 v -1.447000 1.124459 0.468416 v -1.567000 0.862414 0.501065 v -1.500000 1.124999 0.065416 v -1.624000 0.862999 0.065065 v -1.447000 1.125540 -0.337583 v -1.567000 0.863584 -0.370935 v -1.298000 1.126021 -0.696583 v -1.405000 0.864106 -0.759934 v -1.065000 1.126427 -0.999583 v -1.153000 0.864546 -1.087934 v -0.762000 1.126740 -1.232582 v -0.825000 0.864884 -1.339934 v -0.403000 1.126940 -1.381582 v -0.436000 0.865101 -1.501934 v 0.000000 1.127011 -1.434582 v 0.000000 0.865177 -1.558934 v 0.403000 1.126940 -1.381582 v 0.436000 0.865101 -1.501934 v 0.762000 1.126740 -1.232582 v 0.825000 0.864884 -1.339934 v 1.065000 1.126427 -0.999583 v 1.153000 0.864546 -1.087934 v 1.298000 1.126021 -0.696583 v 1.405000 0.864106 -0.759934 v 1.447000 1.125540 -0.337583 v 1.567000 0.863584 -0.370935 v 1.741000 0.602999 0.064716 v 1.679000 0.602373 0.531716 v 1.506000 0.601812 0.949715 v 1.236000 0.601342 1.300715 v 0.885000 0.600980 1.570715 v 0.467000 0.600748 1.743715 v 0.000000 0.600664 1.805715 v -0.467000 0.600748 1.743715 v -0.885000 0.600980 1.570715 v -1.236000 0.601342 1.300715 v -1.506000 0.601812 0.949715 v -1.679000 0.602373 0.531716 v -1.741000 0.602999 0.064716 v -1.679000 0.603626 -0.402283 v -1.506000 0.604186 -0.820283 v -1.236000 0.604657 -1.171283 v -0.885000 0.605019 -1.441283 v -0.467000 0.605251 -1.614282 v 0.000000 0.605334 -1.676282 v 0.467000 0.605251 -1.614282 v 0.885000 0.605019 -1.441283 v 1.236000 0.604657 -1.171283 v 1.506000 0.604186 -0.820283 v 1.679000 0.603626 -0.402283 v 1.844000 0.347000 0.064373 v 1.779000 0.346336 0.559372 v 1.595000 0.345743 1.001372 v 1.309000 0.345244 1.373372 v 0.937000 0.344860 1.659371 v 0.495000 0.344614 1.843371 v 0.000000 0.344526 1.908371 v -0.495000 0.344614 1.843371 v -0.937000 0.344860 1.659371 v -1.309000 0.345244 1.373372 v -1.595000 0.345743 1.001372 v -1.779000 0.346336 0.559372 v -1.844000 0.347000 0.064373 v -1.779000 0.347663 -0.430627 v -1.595000 0.348256 -0.872626 v -1.309000 0.348755 -1.244626 v -0.937000 0.349139 -1.530626 v -0.495000 0.349386 -1.714626 v 0.000000 0.349473 -1.779625 v 0.495000 0.349386 -1.714626 v 0.937000 0.349139 -1.530626 v 1.309000 0.348755 -1.244626 v 1.595000 0.348256 -0.872626 v 1.779000 0.347663 -0.430627 v 1.926000 0.097000 0.064038 v 1.858000 0.096307 0.581037 v 1.666000 0.095687 1.043037 v 1.367000 0.095167 1.431036 v 0.979000 0.094766 1.730036 v 0.517000 0.094508 1.922036 v 0.000000 0.094417 1.990036 v -0.517000 0.094508 1.922036 v -0.979000 0.094766 1.730036 v -1.367000 0.095167 1.431036 v -1.666000 0.095687 1.043037 v -1.858000 0.096307 0.581037 v -1.926000 0.097000 0.064038 v -1.858000 0.097693 -0.452962 v -1.666000 0.098313 -0.914962 v -1.367000 0.098833 -1.302961 v -0.979000 0.099234 -1.601961 v -0.517000 0.099492 -1.793961 v 0.000000 0.099583 -1.861961 v 0.517000 0.099492 -1.793961 v 0.979000 0.099234 -1.601961 v 1.367000 0.098833 -1.302961 v 1.666000 0.098313 -0.914962 v 1.858000 0.097693 -0.452962 v 1.980000 -0.144000 0.063714 v 1.911000 -0.144713 0.595714 v 1.713000 -0.145349 1.069713 v 1.406000 -0.145886 1.469713 v 1.006000 -0.146297 1.776713 v 0.532000 -0.146563 1.974713 v 0.000000 -0.146655 2.043713 v -0.532000 -0.146563 1.974713 v -1.006000 -0.146297 1.776713 v -1.406000 -0.145886 1.469713 v -1.713000 -0.145349 1.069713 v -1.911000 -0.144713 0.595714 v -1.980000 -0.144000 0.063714 v -1.911000 -0.143286 -0.468285 v -1.713000 -0.142651 -0.942285 v -1.406000 -0.142114 -1.342284 v -1.006000 -0.141702 -1.649284 v -0.532000 -0.141437 -1.847284 v 0.000000 -0.141344 -1.916284 v 0.532000 -0.141437 -1.847284 v 1.006000 -0.141702 -1.649284 v 1.406000 -0.142114 -1.342284 v 1.713000 -0.142651 -0.942285 v 1.911000 -0.143286 -0.468285 v 2.000000 -0.375000 0.063405 v 1.930000 -0.375720 0.600404 v 1.730000 -0.376362 1.079404 v 1.420000 -0.376904 1.483403 v 1.016000 -0.377320 1.793403 v 0.537000 -0.377588 1.993403 v 0.000000 -0.377682 2.063403 v -0.537000 -0.377588 1.993403 v -1.016000 -0.377320 1.793403 v -1.420000 -0.376904 1.483403 v -1.730000 -0.376362 1.079404 v -1.930000 -0.375720 0.600404 v -2.000000 -0.375000 0.063405 v -1.930000 -0.374280 -0.473595 v -1.730000 -0.373637 -0.952595 v -1.420000 -0.373095 -1.356594 v -1.016000 -0.372680 -1.666594 v -0.537000 -0.372411 -1.866594 v 0.000000 -0.372317 -1.936594 v 0.537000 -0.372411 -1.866594 v 1.016000 -0.372680 -1.666594 v 1.420000 -0.373095 -1.356594 v 1.730000 -0.373637 -0.952595 v 1.930000 -0.374280 -0.473595 v 1.963000 -0.581999 0.063127 v 1.894000 -0.582706 0.590126 v 1.698000 -0.583337 1.060126 v 1.394000 -0.583869 1.457126 v 0.997000 -0.584277 1.761125 v 0.527000 -0.584540 1.957125 v 0.000000 -0.584632 2.026125 v -0.527000 -0.584540 1.957125 v -0.997000 -0.584277 1.761125 v -1.394000 -0.583869 1.457126 v -1.698000 -0.583337 1.060126 v -1.894000 -0.582706 0.590126 v -1.963000 -0.581999 0.063127 v -1.894000 -0.581293 -0.463873 v -1.698000 -0.580662 -0.933872 v -1.394000 -0.580130 -1.330872 v -0.997000 -0.579722 -1.634871 v -0.527000 -0.579459 -1.830871 v 0.000000 -0.579367 -1.899871 v 0.527000 -0.579459 -1.830871 v 0.997000 -0.579722 -1.634871 v 1.394000 -0.580130 -1.330872 v 1.698000 -0.580662 -0.933872 v 1.894000 -0.581293 -0.463873 v 1.870000 -0.752999 0.062898 v 1.805000 -0.753673 0.564897 v 1.618000 -0.754273 1.012897 v 1.328000 -0.754780 1.390896 v 0.950000 -0.755169 1.680896 v 0.502000 -0.755420 1.867896 v 0.000000 -0.755507 1.932896 v -0.502000 -0.755420 1.867896 v -0.950000 -0.755169 1.680896 v -1.328000 -0.754780 1.390896 v -1.618000 -0.754273 1.012897 v -1.805000 -0.753673 0.564897 v -1.870000 -0.752999 0.062898 v -1.805000 -0.752326 -0.439102 v -1.618000 -0.751725 -0.887102 v -1.328000 -0.751218 -1.265101 v -0.950000 -0.750829 -1.555101 v -0.502000 -0.750579 -1.742101 v 0.000000 -0.750491 -1.807101 v 0.502000 -0.750579 -1.742101 v 0.950000 -0.750829 -1.555101 v 1.328000 -0.751218 -1.265101 v 1.618000 -0.751725 -0.887102 v 1.805000 -0.752326 -0.439102 v 1.750000 -0.890999 0.062713 v 1.688000 -0.891630 0.532712 v 1.514000 -0.892192 0.951712 v 1.243000 -0.892666 1.305711 v 0.889000 -0.893030 1.576711 v 0.470000 -0.893263 1.750711 v 0.000000 -0.893346 1.812711 v -0.470000 -0.893263 1.750711 v -0.889000 -0.893030 1.576711 v -1.243000 -0.892666 1.305711 v -1.514000 -0.892192 0.951712 v -1.688000 -0.891630 0.532712 v -1.750000 -0.890999 0.062713 v -1.688000 -0.890369 -0.407287 v -1.514000 -0.889807 -0.826287 v -1.243000 -0.889332 -1.180286 v -0.889000 -0.888969 -1.451286 v -0.470000 -0.888735 -1.625286 v 0.000000 -0.888652 -1.687286 v 0.470000 -0.888735 -1.625286 v 0.889000 -0.888969 -1.451286 v 1.243000 -0.889332 -1.180286 v 1.514000 -0.889807 -0.826287 v 1.688000 -0.890369 -0.407287 v 1.630000 -0.996999 0.062570 v 1.572000 -0.997587 0.500570 v 1.410000 -0.998110 0.890570 v 1.157000 -0.998551 1.219569 v 0.828000 -0.998890 1.472569 v 0.438000 -0.999107 1.634569 v 0.000000 -0.999185 1.692569 v -0.438000 -0.999107 1.634569 v -0.828000 -0.998890 1.472569 v -1.157000 -0.998551 1.219569 v -1.410000 -0.998110 0.890570 v -1.572000 -0.997587 0.500570 v -1.630000 -0.996999 0.062570 v -1.572000 -0.996412 -0.375429 v -1.410000 -0.995889 -0.765429 v -1.157000 -0.995447 -1.094429 v -0.828000 -0.995108 -1.347428 v -0.438000 -0.994891 -1.509428 v 0.000000 -0.994813 -1.567428 v 0.438000 -0.994891 -1.509428 v 0.828000 -0.995108 -1.347428 v 1.157000 -0.995447 -1.094429 v 1.410000 -0.995889 -0.765429 v 1.572000 -0.996412 -0.375429 v 1.537000 -1.074999 0.062466 v 1.483000 -1.075553 0.475465 v 1.330000 -1.076047 0.843465 v 1.091000 -1.076462 1.153465 v 0.781000 -1.076783 1.392465 v 0.413000 -1.076988 1.545465 v 0.000000 -1.077060 1.599464 v -0.413000 -1.076988 1.545465 v -0.781000 -1.076783 1.392465 v -1.091000 -1.076462 1.153465 v -1.330000 -1.076047 0.843465 v -1.483000 -1.075553 0.475465 v -1.537000 -1.074999 0.062466 v -1.483000 -1.074445 -0.350534 v -1.330000 -1.073952 -0.718534 v -1.091000 -1.073536 -1.028533 v -0.781000 -1.073215 -1.267533 v -0.413000 -1.073010 -1.420533 v 0.000000 -1.072938 -1.474533 v 0.413000 -1.073010 -1.420533 v 0.781000 -1.073215 -1.267533 v 1.091000 -1.073536 -1.028533 v 1.330000 -1.073952 -0.718534 v 1.483000 -1.074445 -0.350534 v 1.500000 -1.124999 0.062399 v 1.447000 -1.125540 0.465398 v 1.298000 -1.126021 0.824398 v 1.065000 -1.126427 1.127398 v 0.762000 -1.126740 1.360397 v 0.403000 -1.126940 1.509397 v 0.000000 -1.127011 1.562397 v -0.403000 -1.126940 1.509397 v -0.762000 -1.126740 1.360397 v -1.065000 -1.126427 1.127398 v -1.298000 -1.126021 0.824398 v -1.447000 -1.125540 0.465398 v -1.500000 -1.124999 0.062399 v -1.447000 -1.124459 -0.340601 v -1.298000 -1.123977 -0.699601 v -1.065000 -1.123571 -1.002600 v -0.762000 -1.123258 -1.235600 v -0.403000 -1.123058 -1.384600 v 0.000000 -1.122987 -1.437600 v 0.403000 -1.123058 -1.384600 v 0.762000 -1.123258 -1.235600 v 1.065000 -1.123571 -1.002600 v 1.298000 -1.123977 -0.699601 v 1.447000 -1.124459 -0.340601 f 1 2 3 f 3 2 4 f 4 2 5 f 5 2 6 f 6 2 7 f 7 2 8 f 8 2 9 f 9 2 10 f 10 2 11 f 11 2 12 f 12 2 13 f 13 2 14 f 14 2 15 f 15 2 16 f 16 2 17 f 17 2 18 f 18 2 19 f 19 2 20 f 20 2 21 f 21 2 22 f 22 2 23 f 23 2 24 f 24 2 25 f 25 2 1 f 1 3 26 f 26 3 27 f 3 4 27 f 27 4 28 f 4 5 28 f 28 5 29 f 5 6 29 f 29 6 30 f 6 7 30 f 30 7 31 f 7 8 31 f 31 8 32 f 8 9 32 f 32 9 33 f 9 10 33 f 33 10 34 f 10 11 34 f 34 11 35 f 11 12 35 f 35 12 36 f 12 13 36 f 36 13 37 f 13 14 37 f 37 14 38 f 14 15 38 f 38 15 39 f 15 16 39 f 39 16 40 f 16 17 40 f 40 17 41 f 17 18 41 f 41 18 42 f 18 19 42 f 42 19 43 f 19 20 43 f 43 20 44 f 20 21 44 f 44 21 45 f 21 22 45 f 45 22 46 f 22 23 46 f 46 23 47 f 23 24 47 f 47 24 48 f 24 25 48 f 48 25 49 f 25 1 49 f 49 1 26 f 26 27 50 f 50 27 51 f 27 28 51 f 51 28 52 f 28 29 52 f 52 29 53 f 29 30 53 f 53 30 54 f 30 31 54 f 54 31 55 f 31 32 55 f 55 32 56 f 32 33 56 f 56 33 57 f 33 34 57 f 57 34 58 f 34 35 58 f 58 35 59 f 35 36 59 f 59 36 60 f 36 37 60 f 60 37 61 f 37 38 61 f 61 38 62 f 38 39 62 f 62 39 63 f 39 40 63 f 63 40 64 f 40 41 64 f 64 41 65 f 41 42 65 f 65 42 66 f 42 43 66 f 66 43 67 f 43 44 67 f 67 44 68 f 44 45 68 f 68 45 69 f 45 46 69 f 69 46 70 f 46 47 70 f 70 47 71 f 47 48 71 f 71 48 72 f 48 49 72 f 72 49 73 f 49 26 73 f 73 26 50 f 50 51 74 f 74 51 75 f 51 52 75 f 75 52 76 f 52 53 76 f 76 53 77 f 53 54 77 f 77 54 78 f 54 55 78 f 78 55 79 f 55 56 79 f 79 56 80 f 56 57 80 f 80 57 81 f 57 58 81 f 81 58 82 f 58 59 82 f 82 59 83 f 59 60 83 f 83 60 84 f 60 61 84 f 84 61 85 f 61 62 85 f 85 62 86 f 62 63 86 f 86 63 87 f 63 64 87 f 87 64 88 f 64 65 88 f 88 65 89 f 65 66 89 f 89 66 90 f 66 67 90 f 90 67 91 f 67 68 91 f 91 68 92 f 68 69 92 f 92 69 93 f 69 70 93 f 93 70 94 f 70 71 94 f 94 71 95 f 71 72 95 f 95 72 96 f 72 73 96 f 96 73 97 f 73 50 97 f 97 50 74 f 74 75 98 f 98 75 99 f 75 76 99 f 99 76 100 f 76 77 100 f 100 77 101 f 77 78 101 f 101 78 102 f 78 79 102 f 102 79 103 f 79 80 103 f 103 80 104 f 80 81 104 f 104 81 105 f 81 82 105 f 105 82 106 f 82 83 106 f 106 83 107 f 83 84 107 f 107 84 108 f 84 85 108 f 108 85 109 f 85 86 109 f 109 86 110 f 86 87 110 f 110 87 111 f 87 88 111 f 111 88 112 f 88 89 112 f 112 89 113 f 89 90 113 f 113 90 114 f 90 91 114 f 114 91 115 f 91 92 115 f 115 92 116 f 92 93 116 f 116 93 117 f 93 94 117 f 117 94 118 f 94 95 118 f 118 95 119 f 95 96 119 f 119 96 120 f 96 97 120 f 120 97 121 f 97 74 121 f 121 74 98 f 98 99 122 f 122 99 123 f 99 100 123 f 123 100 124 f 100 101 124 f 124 101 125 f 101 102 125 f 125 102 126 f 102 103 126 f 126 103 127 f 103 104 127 f 127 104 128 f 104 105 128 f 128 105 129 f 105 106 129 f 129 106 130 f 106 107 130 f 130 107 131 f 107 108 131 f 131 108 132 f 108 109 132 f 132 109 133 f 109 110 133 f 133 110 134 f 110 111 134 f 134 111 135 f 111 112 135 f 135 112 136 f 112 113 136 f 136 113 137 f 113 114 137 f 137 114 138 f 114 115 138 f 138 115 139 f 115 116 139 f 139 116 140 f 116 117 140 f 140 117 141 f 117 118 141 f 141 118 142 f 118 119 142 f 142 119 143 f 119 120 143 f 143 120 144 f 120 121 144 f 144 121 145 f 121 98 145 f 145 98 122 f 122 123 146 f 146 123 147 f 123 124 147 f 147 124 148 f 124 125 148 f 148 125 149 f 125 126 149 f 149 126 150 f 126 127 150 f 150 127 151 f 127 128 151 f 151 128 152 f 128 129 152 f 152 129 153 f 129 130 153 f 153 130 154 f 130 131 154 f 154 131 155 f 131 132 155 f 155 132 156 f 132 133 156 f 156 133 157 f 133 134 157 f 157 134 158 f 134 135 158 f 158 135 159 f 135 136 159 f 159 136 160 f 136 137 160 f 160 137 161 f 137 138 161 f 161 138 162 f 138 139 162 f 162 139 163 f 139 140 163 f 163 140 164 f 140 141 164 f 164 141 165 f 141 142 165 f 165 142 166 f 142 143 166 f 166 143 167 f 143 144 167 f 167 144 168 f 144 145 168 f 168 145 169 f 145 122 169 f 169 122 146 f 146 147 170 f 170 147 171 f 147 148 171 f 171 148 172 f 148 149 172 f 172 149 173 f 149 150 173 f 173 150 174 f 150 151 174 f 174 151 175 f 151 152 175 f 175 152 176 f 152 153 176 f 176 153 177 f 153 154 177 f 177 154 178 f 154 155 178 f 178 155 179 f 155 156 179 f 179 156 180 f 156 157 180 f 180 157 181 f 157 158 181 f 181 158 182 f 158 159 182 f 182 159 183 f 159 160 183 f 183 160 184 f 160 161 184 f 184 161 185 f 161 162 185 f 185 162 186 f 162 163 186 f 186 163 187 f 163 164 187 f 187 164 188 f 164 165 188 f 188 165 189 f 165 166 189 f 189 166 190 f 166 167 190 f 190 167 191 f 167 168 191 f 191 168 192 f 168 169 192 f 192 169 193 f 169 146 193 f 193 146 170 f 170 171 194 f 194 171 195 f 171 172 195 f 195 172 196 f 172 173 196 f 196 173 197 f 173 174 197 f 197 174 198 f 174 175 198 f 198 175 199 f 175 176 199 f 199 176 200 f 176 177 200 f 200 177 201 f 177 178 201 f 201 178 202 f 178 179 202 f 202 179 203 f 179 180 203 f 203 180 204 f 180 181 204 f 204 181 205 f 181 182 205 f 205 182 206 f 182 183 206 f 206 183 207 f 183 184 207 f 207 184 208 f 184 185 208 f 208 185 209 f 185 186 209 f 209 186 210 f 186 187 210 f 210 187 211 f 187 188 211 f 211 188 212 f 188 189 212 f 212 189 213 f 189 190 213 f 213 190 214 f 190 191 214 f 214 191 215 f 191 192 215 f 215 192 216 f 192 193 216 f 216 193 217 f 193 170 217 f 217 170 194 f 194 195 218 f 218 195 219 f 195 196 219 f 219 196 220 f 196 197 220 f 220 197 221 f 197 198 221 f 221 198 222 f 198 199 222 f 222 199 223 f 199 200 223 f 223 200 224 f 200 201 224 f 224 201 225 f 201 202 225 f 225 202 226 f 202 203 226 f 226 203 227 f 203 204 227 f 227 204 228 f 204 205 228 f 228 205 229 f 205 206 229 f 229 206 230 f 206 207 230 f 230 207 231 f 207 208 231 f 231 208 232 f 208 209 232 f 232 209 233 f 209 210 233 f 233 210 234 f 210 211 234 f 234 211 235 f 211 212 235 f 235 212 236 f 212 213 236 f 236 213 237 f 213 214 237 f 237 214 238 f 214 215 238 f 238 215 239 f 215 216 239 f 239 216 240 f 216 217 240 f 240 217 241 f 217 194 241 f 241 194 218 f 218 219 242 f 242 219 243 f 219 220 243 f 243 220 244 f 220 221 244 f 244 221 245 f 221 222 245 f 245 222 246 f 222 223 246 f 246 223 247 f 223 224 247 f 247 224 248 f 224 225 248 f 248 225 249 f 225 226 249 f 249 226 250 f 226 227 250 f 250 227 251 f 227 228 251 f 251 228 252 f 228 229 252 f 252 229 253 f 229 230 253 f 253 230 254 f 230 231 254 f 254 231 255 f 231 232 255 f 255 232 256 f 232 233 256 f 256 233 257 f 233 234 257 f 257 234 258 f 234 235 258 f 258 235 259 f 235 236 259 f 259 236 260 f 236 237 260 f 260 237 261 f 237 238 261 f 261 238 262 f 238 239 262 f 262 239 263 f 239 240 263 f 263 240 264 f 240 241 264 f 264 241 265 f 241 218 265 f 265 218 242 f 242 243 266 f 266 243 267 f 243 244 267 f 267 244 268 f 244 245 268 f 268 245 269 f 245 246 269 f 269 246 270 f 246 247 270 f 270 247 271 f 247 248 271 f 271 248 272 f 248 249 272 f 272 249 273 f 249 250 273 f 273 250 274 f 250 251 274 f 274 251 275 f 251 252 275 f 275 252 276 f 252 253 276 f 276 253 277 f 253 254 277 f 277 254 278 f 254 255 278 f 278 255 279 f 255 256 279 f 279 256 280 f 256 257 280 f 280 257 281 f 257 258 281 f 281 258 282 f 258 259 282 f 282 259 283 f 259 260 283 f 283 260 284 f 260 261 284 f 284 261 285 f 261 262 285 f 285 262 286 f 262 263 286 f 286 263 287 f 263 264 287 f 287 264 288 f 264 265 288 f 288 265 289 f 265 242 289 f 289 242 266 f 290 291 292 f 292 291 293 f 291 294 293 f 293 294 295 f 294 296 295 f 295 296 297 f 296 298 297 f 297 298 299 f 298 300 299 f 299 300 301 f 300 302 301 f 301 302 303 f 302 304 303 f 303 304 305 f 304 306 305 f 305 306 307 f 306 308 307 f 307 308 309 f 308 310 309 f 309 310 311 f 310 312 311 f 311 312 313 f 312 314 313 f 313 314 315 f 292 293 316 f 316 293 317 f 293 295 317 f 317 295 318 f 295 297 318 f 318 297 319 f 297 299 319 f 319 299 320 f 299 301 320 f 320 301 321 f 301 303 321 f 321 303 322 f 303 305 322 f 322 305 323 f 305 307 323 f 323 307 324 f 307 309 324 f 324 309 325 f 309 311 325 f 325 311 326 f 311 313 326 f 326 313 327 f 313 315 327 f 327 315 328 f 316 317 329 f 329 317 330 f 317 318 330 f 330 318 331 f 318 319 331 f 331 319 332 f 319 320 332 f 332 320 333 f 320 321 333 f 333 321 334 f 321 322 334 f 334 322 335 f 322 323 335 f 335 323 336 f 323 324 336 f 336 324 337 f 324 325 337 f 337 325 338 f 325 326 338 f 338 326 339 f 326 327 339 f 339 327 340 f 327 328 340 f 340 328 341 f 329 330 342 f 342 330 343 f 330 331 343 f 343 331 344 f 331 332 344 f 344 332 345 f 332 333 345 f 345 333 346 f 333 334 346 f 346 334 347 f 334 335 347 f 347 335 348 f 335 336 348 f 348 336 349 f 336 337 349 f 349 337 350 f 337 338 350 f 350 338 351 f 338 339 351 f 351 339 352 f 339 340 352 f 352 340 353 f 340 341 353 f 353 341 354 f 342 343 355 f 355 343 356 f 343 344 356 f 356 344 357 f 344 345 357 f 357 345 358 f 345 346 358 f 358 346 359 f 346 347 359 f 359 347 360 f 347 348 360 f 360 348 361 f 348 349 361 f 361 349 362 f 349 350 362 f 362 350 363 f 350 351 363 f 363 351 364 f 351 352 364 f 364 352 365 f 352 353 365 f 365 353 366 f 353 354 366 f 366 354 367 f 355 356 314 f 314 356 368 f 356 357 368 f 368 357 369 f 357 358 369 f 369 358 370 f 358 359 370 f 370 359 371 f 359 360 371 f 371 360 372 f 360 361 372 f 372 361 373 f 361 362 373 f 373 362 374 f 362 363 374 f 374 363 375 f 363 364 375 f 375 364 376 f 364 365 376 f 376 365 377 f 365 366 377 f 377 366 378 f 366 367 378 f 378 367 290 f 314 368 315 f 315 368 379 f 368 369 379 f 379 369 380 f 369 370 380 f 380 370 381 f 370 371 381 f 381 371 382 f 371 372 382 f 382 372 383 f 372 373 383 f 383 373 384 f 373 374 384 f 384 374 385 f 374 375 385 f 385 375 386 f 375 376 386 f 386 376 387 f 376 377 387 f 387 377 388 f 377 378 388 f 388 378 389 f 378 290 389 f 389 290 292 f 315 379 328 f 328 379 390 f 379 380 390 f 390 380 391 f 380 381 391 f 391 381 392 f 381 382 392 f 392 382 393 f 382 383 393 f 393 383 394 f 383 384 394 f 394 384 395 f 384 385 395 f 395 385 396 f 385 386 396 f 396 386 397 f 386 387 397 f 397 387 398 f 387 388 398 f 398 388 399 f 388 389 399 f 399 389 400 f 389 292 400 f 400 292 316 f 328 390 341 f 341 390 401 f 390 391 401 f 401 391 402 f 391 392 402 f 402 392 403 f 392 393 403 f 403 393 404 f 393 394 404 f 404 394 405 f 394 395 405 f 405 395 406 f 395 396 406 f 406 396 407 f 396 397 407 f 407 397 408 f 397 398 408 f 408 398 409 f 398 399 409 f 409 399 410 f 399 400 410 f 410 400 411 f 400 316 411 f 411 316 329 f 341 401 354 f 354 401 412 f 401 402 412 f 412 402 413 f 402 403 413 f 413 403 414 f 403 404 414 f 414 404 415 f 404 405 415 f 415 405 416 f 405 406 416 f 416 406 417 f 406 407 417 f 417 407 418 f 407 408 418 f 418 408 419 f 408 409 419 f 419 409 420 f 409 410 420 f 420 410 421 f 410 411 421 f 421 411 422 f 411 329 422 f 422 329 342 f 354 412 367 f 367 412 423 f 412 413 423 f 423 413 424 f 413 414 424 f 424 414 425 f 414 415 425 f 425 415 426 f 415 416 426 f 426 416 427 f 416 417 427 f 427 417 428 f 417 418 428 f 428 418 429 f 418 419 429 f 429 419 430 f 419 420 430 f 430 420 431 f 420 421 431 f 431 421 432 f 421 422 432 f 432 422 433 f 422 342 433 f 433 342 355 f 367 423 434 f 434 423 435 f 423 424 435 f 435 424 436 f 424 425 436 f 436 425 437 f 425 426 437 f 437 426 438 f 426 427 438 f 438 427 439 f 427 428 439 f 439 428 440 f 428 429 440 f 440 429 441 f 429 430 441 f 441 430 442 f 430 431 442 f 442 431 443 f 431 432 443 f 443 432 444 f 432 433 444 f 444 433 445 f 433 355 445 f 445 355 446 f 447 448 449 f 449 448 450 f 448 451 450 f 450 451 452 f 451 453 452 f 452 453 454 f 453 455 454 f 454 455 456 f 455 457 456 f 456 457 458 f 457 459 458 f 458 459 460 f 459 461 460 f 460 461 462 f 461 463 462 f 462 463 464 f 463 465 464 f 464 465 466 f 465 467 466 f 466 467 468 f 467 469 468 f 468 469 470 f 469 447 470 f 470 447 449 f 449 450 471 f 471 450 472 f 450 452 472 f 472 452 473 f 452 454 473 f 473 454 474 f 454 456 474 f 474 456 475 f 456 458 475 f 475 458 476 f 458 460 476 f 476 460 477 f 460 462 477 f 477 462 478 f 462 464 478 f 478 464 479 f 464 466 479 f 479 466 480 f 466 468 480 f 480 468 481 f 468 470 481 f 481 470 482 f 470 449 482 f 482 449 471 f 471 472 483 f 483 472 484 f 472 473 484 f 484 473 485 f 473 474 485 f 485 474 486 f 474 475 486 f 486 475 487 f 475 476 487 f 487 476 488 f 476 477 488 f 488 477 489 f 477 478 489 f 489 478 490 f 478 479 490 f 490 479 491 f 479 480 491 f 491 480 492 f 480 481 492 f 492 481 493 f 481 482 493 f 493 482 494 f 482 471 494 f 494 471 495 f 483 484 496 f 496 484 497 f 484 485 497 f 497 485 498 f 485 486 498 f 498 486 499 f 486 487 499 f 499 487 500 f 487 488 500 f 500 488 501 f 488 489 501 f 501 489 502 f 489 490 502 f 502 490 503 f 490 491 503 f 503 491 504 f 491 492 504 f 504 492 505 f 492 493 505 f 505 493 506 f 493 494 506 f 506 494 507 f 494 495 507 f 507 495 496 f 496 497 508 f 508 497 509 f 497 498 509 f 509 498 510 f 498 499 510 f 510 499 511 f 499 500 511 f 511 500 512 f 500 501 512 f 512 501 513 f 501 502 513 f 513 502 514 f 502 503 514 f 514 503 515 f 503 504 515 f 515 504 516 f 504 505 516 f 516 505 517 f 505 506 517 f 517 506 518 f 506 507 518 f 518 507 519 f 507 496 519 f 519 496 508 f 508 509 520 f 520 509 521 f 509 510 521 f 521 510 522 f 510 511 522 f 522 511 523 f 511 512 523 f 523 512 524 f 512 513 524 f 524 513 525 f 513 514 525 f 525 514 526 f 514 515 526 f 526 515 527 f 515 516 527 f 527 516 528 f 516 517 528 f 528 517 529 f 517 518 529 f 529 518 530 f 518 519 530 f 530 519 531 f 519 508 531 f 531 508 520 f 520 521 532 f 532 521 533 f 521 522 533 f 533 522 534 f 522 523 534 f 534 523 535 f 523 524 535 f 535 524 536 f 524 525 536 f 536 525 537 f 525 526 537 f 537 526 538 f 526 527 538 f 538 527 539 f 527 528 539 f 539 528 540 f 528 529 540 f 540 529 541 f 529 530 541 f 541 530 542 f 530 531 542 f 542 531 543 f 531 520 543 f 543 520 532 f 532 533 544 f 544 533 545 f 533 534 545 f 545 534 546 f 534 535 546 f 546 535 547 f 535 536 547 f 547 536 548 f 536 537 548 f 548 537 549 f 537 538 549 f 549 538 550 f 538 539 550 f 550 539 551 f 539 540 551 f 551 540 552 f 540 541 552 f 552 541 553 f 541 542 553 f 553 542 554 f 542 543 554 f 554 543 555 f 543 532 555 f 555 532 544 f 544 545 556 f 556 545 557 f 545 546 557 f 557 546 558 f 546 547 558 f 558 547 559 f 547 548 559 f 559 548 560 f 548 549 560 f 560 549 561 f 549 550 561 f 561 550 562 f 550 551 562 f 562 551 563 f 551 552 563 f 563 552 564 f 552 553 564 f 564 553 565 f 553 554 565 f 565 554 566 f 554 555 566 f 566 555 567 f 555 544 567 f 567 544 556 f 556 557 568 f 568 557 569 f 557 558 569 f 569 558 570 f 558 559 570 f 570 559 571 f 559 560 571 f 571 560 572 f 560 561 572 f 572 561 573 f 561 562 573 f 573 562 574 f 562 563 574 f 574 563 575 f 563 564 575 f 575 564 576 f 564 565 576 f 576 565 577 f 565 566 577 f 577 566 578 f 566 567 578 f 578 567 579 f 567 556 579 f 579 556 568 f 568 569 580 f 580 569 581 f 569 570 581 f 581 570 582 f 570 571 582 f 582 571 583 f 571 572 583 f 583 572 584 f 572 573 584 f 584 573 585 f 573 574 585 f 585 574 586 f 574 575 586 f 586 575 587 f 575 576 587 f 587 576 588 f 576 577 588 f 588 577 589 f 577 578 589 f 589 578 590 f 578 579 590 f 590 579 591 f 579 568 591 f 591 568 580 f 580 581 592 f 592 581 593 f 581 582 593 f 593 582 594 f 582 583 594 f 594 583 595 f 583 584 595 f 595 584 596 f 584 585 596 f 596 585 597 f 585 586 597 f 597 586 598 f 586 587 598 f 598 587 599 f 587 588 599 f 599 588 600 f 588 589 600 f 600 589 601 f 589 590 601 f 601 590 602 f 590 591 602 f 602 591 603 f 591 580 603 f 603 580 592 f 604 605 606 f 606 605 607 f 605 608 607 f 607 608 609 f 608 610 609 f 609 610 611 f 610 612 611 f 611 612 613 f 612 614 613 f 613 614 615 f 614 616 615 f 615 616 617 f 616 618 617 f 617 618 619 f 618 620 619 f 619 620 621 f 620 622 621 f 621 622 623 f 622 624 623 f 623 624 625 f 624 626 625 f 625 626 627 f 626 604 627 f 627 604 606 f 606 607 628 f 628 607 629 f 607 609 629 f 629 609 630 f 609 611 630 f 630 611 631 f 611 613 631 f 631 613 632 f 613 615 632 f 632 615 633 f 615 617 633 f 633 617 634 f 617 619 634 f 634 619 635 f 619 621 635 f 635 621 636 f 621 623 636 f 636 623 637 f 623 625 637 f 637 625 638 f 625 627 638 f 638 627 639 f 627 606 639 f 639 606 628 f 628 629 640 f 640 629 641 f 629 630 641 f 641 630 642 f 630 631 642 f 642 631 643 f 631 632 643 f 643 632 644 f 632 633 644 f 644 633 645 f 633 634 645 f 645 634 646 f 634 635 646 f 646 635 647 f 635 636 647 f 647 636 648 f 636 637 648 f 648 637 649 f 637 638 649 f 649 638 650 f 638 639 650 f 650 639 651 f 639 628 651 f 651 628 640 f 640 641 652 f 652 641 653 f 641 642 653 f 653 642 654 f 642 643 654 f 654 643 655 f 643 644 655 f 655 644 656 f 644 645 656 f 656 645 657 f 645 646 657 f 657 646 658 f 646 647 658 f 658 647 659 f 647 648 659 f 659 648 660 f 648 649 660 f 660 649 661 f 649 650 661 f 661 650 662 f 650 651 662 f 662 651 663 f 651 640 663 f 663 640 652 f 652 653 664 f 664 653 665 f 653 654 665 f 665 654 666 f 654 655 666 f 666 655 667 f 655 656 667 f 667 656 668 f 656 657 668 f 668 657 669 f 657 658 669 f 669 658 670 f 658 659 670 f 670 659 671 f 659 660 671 f 671 660 672 f 660 661 672 f 672 661 673 f 661 662 673 f 673 662 674 f 662 663 674 f 674 663 675 f 663 652 675 f 675 652 664 f 664 665 676 f 676 665 677 f 665 666 677 f 677 666 678 f 666 667 678 f 678 667 679 f 667 668 679 f 679 668 680 f 668 669 680 f 680 669 681 f 669 670 681 f 681 670 682 f 670 671 682 f 682 671 683 f 671 672 683 f 683 672 684 f 672 673 684 f 684 673 685 f 673 674 685 f 685 674 686 f 674 675 686 f 686 675 687 f 675 664 687 f 687 664 676 f 676 677 688 f 688 677 689 f 677 678 689 f 689 678 690 f 678 679 690 f 690 679 691 f 679 680 691 f 691 680 692 f 680 681 692 f 692 681 693 f 681 682 693 f 693 682 694 f 682 683 694 f 694 683 695 f 683 684 695 f 695 684 696 f 684 685 696 f 696 685 697 f 685 686 697 f 697 686 698 f 686 687 698 f 698 687 699 f 687 676 699 f 699 676 688 f 688 689 700 f 700 689 701 f 689 690 701 f 701 690 702 f 690 691 702 f 702 691 703 f 691 692 703 f 703 692 704 f 692 693 704 f 704 693 705 f 693 694 705 f 705 694 706 f 694 695 706 f 706 695 707 f 695 696 707 f 707 696 708 f 696 697 708 f 708 697 709 f 697 698 709 f 709 698 710 f 698 699 710 f 710 699 711 f 699 688 711 f 711 688 700 f 700 701 712 f 712 701 713 f 701 702 713 f 713 702 714 f 702 703 714 f 714 703 715 f 703 704 715 f 715 704 716 f 704 705 716 f 716 705 717 f 705 706 717 f 717 706 718 f 706 707 718 f 718 707 719 f 707 708 719 f 719 708 720 f 708 709 720 f 720 709 721 f 709 710 721 f 721 710 722 f 710 711 722 f 722 711 723 f 711 700 723 f 723 700 712 f 712 713 724 f 724 713 725 f 713 714 725 f 725 714 726 f 714 715 726 f 726 715 727 f 715 716 727 f 727 716 728 f 716 717 728 f 728 717 729 f 717 718 729 f 729 718 730 f 718 719 730 f 730 719 731 f 719 720 731 f 731 720 732 f 720 721 732 f 732 721 733 f 721 722 733 f 733 722 734 f 722 723 734 f 734 723 735 f 723 712 735 f 735 712 724 f 724 725 736 f 736 725 737 f 725 726 737 f 737 726 738 f 726 727 738 f 738 727 739 f 727 728 739 f 739 728 740 f 728 729 740 f 740 729 741 f 729 730 741 f 741 730 742 f 730 731 742 f 742 731 743 f 731 732 743 f 743 732 744 f 732 733 744 f 744 733 745 f 733 734 745 f 745 734 746 f 734 735 746 f 746 735 747 f 735 724 747 f 747 724 736 f 736 737 748 f 748 737 749 f 737 738 749 f 749 738 750 f 738 739 750 f 750 739 751 f 739 740 751 f 751 740 752 f 740 741 752 f 752 741 753 f 741 742 753 f 753 742 754 f 742 743 754 f 754 743 755 f 743 744 755 f 755 744 756 f 744 745 756 f 756 745 757 f 745 746 757 f 757 746 758 f 746 747 758 f 758 747 759 f 747 736 759 f 759 736 748 f 760 761 762 f 762 761 763 f 761 764 763 f 763 764 765 f 764 766 765 f 765 766 767 f 766 768 767 f 767 768 769 f 768 770 769 f 769 770 771 f 770 772 771 f 771 772 773 f 772 774 773 f 773 774 775 f 774 776 775 f 775 776 777 f 776 778 777 f 777 778 779 f 778 780 779 f 779 780 781 f 780 782 781 f 781 782 783 f 782 784 783 f 783 784 785 f 784 786 785 f 785 786 787 f 786 788 787 f 787 788 789 f 788 790 789 f 789 790 791 f 790 792 791 f 791 792 793 f 792 794 793 f 793 794 795 f 794 796 795 f 795 796 797 f 796 798 797 f 797 798 799 f 798 800 799 f 799 800 801 f 800 802 801 f 801 802 803 f 802 804 803 f 803 804 805 f 804 806 805 f 805 806 807 f 806 760 807 f 807 760 762 f 762 763 808 f 808 763 809 f 763 765 809 f 809 765 810 f 765 767 810 f 810 767 811 f 767 769 811 f 811 769 812 f 769 771 812 f 812 771 813 f 771 773 813 f 813 773 814 f 773 775 814 f 814 775 815 f 775 777 815 f 815 777 816 f 777 779 816 f 816 779 817 f 779 781 817 f 817 781 818 f 781 783 818 f 818 783 819 f 783 785 819 f 819 785 820 f 785 787 820 f 820 787 821 f 787 789 821 f 821 789 822 f 789 791 822 f 822 791 823 f 791 793 823 f 823 793 824 f 793 795 824 f 824 795 825 f 795 797 825 f 825 797 826 f 797 799 826 f 826 799 827 f 799 801 827 f 827 801 828 f 801 803 828 f 828 803 829 f 803 805 829 f 829 805 830 f 805 807 830 f 830 807 831 f 807 762 831 f 831 762 808 f 808 809 832 f 832 809 833 f 809 810 833 f 833 810 834 f 810 811 834 f 834 811 835 f 811 812 835 f 835 812 836 f 812 813 836 f 836 813 837 f 813 814 837 f 837 814 838 f 814 815 838 f 838 815 839 f 815 816 839 f 839 816 840 f 816 817 840 f 840 817 841 f 817 818 841 f 841 818 842 f 818 819 842 f 842 819 843 f 819 820 843 f 843 820 844 f 820 821 844 f 844 821 845 f 821 822 845 f 845 822 846 f 822 823 846 f 846 823 847 f 823 824 847 f 847 824 848 f 824 825 848 f 848 825 849 f 825 826 849 f 849 826 850 f 826 827 850 f 850 827 851 f 827 828 851 f 851 828 852 f 828 829 852 f 852 829 853 f 829 830 853 f 853 830 854 f 830 831 854 f 854 831 855 f 831 808 855 f 855 808 832 f 832 833 856 f 856 833 857 f 833 834 857 f 857 834 858 f 834 835 858 f 858 835 859 f 835 836 859 f 859 836 860 f 836 837 860 f 860 837 861 f 837 838 861 f 861 838 862 f 838 839 862 f 862 839 863 f 839 840 863 f 863 840 864 f 840 841 864 f 864 841 865 f 841 842 865 f 865 842 866 f 842 843 866 f 866 843 867 f 843 844 867 f 867 844 868 f 844 845 868 f 868 845 869 f 845 846 869 f 869 846 870 f 846 847 870 f 870 847 871 f 847 848 871 f 871 848 872 f 848 849 872 f 872 849 873 f 849 850 873 f 873 850 874 f 850 851 874 f 874 851 875 f 851 852 875 f 875 852 876 f 852 853 876 f 876 853 877 f 853 854 877 f 877 854 878 f 854 855 878 f 878 855 879 f 855 832 879 f 879 832 856 f 856 857 880 f 880 857 881 f 857 858 881 f 881 858 882 f 858 859 882 f 882 859 883 f 859 860 883 f 883 860 884 f 860 861 884 f 884 861 885 f 861 862 885 f 885 862 886 f 862 863 886 f 886 863 887 f 863 864 887 f 887 864 888 f 864 865 888 f 888 865 889 f 865 866 889 f 889 866 890 f 866 867 890 f 890 867 891 f 867 868 891 f 891 868 892 f 868 869 892 f 892 869 893 f 869 870 893 f 893 870 894 f 870 871 894 f 894 871 895 f 871 872 895 f 895 872 896 f 872 873 896 f 896 873 897 f 873 874 897 f 897 874 898 f 874 875 898 f 898 875 899 f 875 876 899 f 899 876 900 f 876 877 900 f 900 877 901 f 877 878 901 f 901 878 902 f 878 879 902 f 902 879 903 f 879 856 903 f 903 856 880 f 880 881 904 f 904 881 905 f 881 882 905 f 905 882 906 f 882 883 906 f 906 883 907 f 883 884 907 f 907 884 908 f 884 885 908 f 908 885 909 f 885 886 909 f 909 886 910 f 886 887 910 f 910 887 911 f 887 888 911 f 911 888 912 f 888 889 912 f 912 889 913 f 889 890 913 f 913 890 914 f 890 891 914 f 914 891 915 f 891 892 915 f 915 892 916 f 892 893 916 f 916 893 917 f 893 894 917 f 917 894 918 f 894 895 918 f 918 895 919 f 895 896 919 f 919 896 920 f 896 897 920 f 920 897 921 f 897 898 921 f 921 898 922 f 898 899 922 f 922 899 923 f 899 900 923 f 923 900 924 f 900 901 924 f 924 901 925 f 901 902 925 f 925 902 926 f 902 903 926 f 926 903 927 f 903 880 927 f 927 880 904 f 904 905 928 f 928 905 929 f 905 906 929 f 929 906 930 f 906 907 930 f 930 907 931 f 907 908 931 f 931 908 932 f 908 909 932 f 932 909 933 f 909 910 933 f 933 910 934 f 910 911 934 f 934 911 935 f 911 912 935 f 935 912 936 f 912 913 936 f 936 913 937 f 913 914 937 f 937 914 938 f 914 915 938 f 938 915 939 f 915 916 939 f 939 916 940 f 916 917 940 f 940 917 941 f 917 918 941 f 941 918 942 f 918 919 942 f 942 919 943 f 919 920 943 f 943 920 944 f 920 921 944 f 944 921 945 f 921 922 945 f 945 922 946 f 922 923 946 f 946 923 947 f 923 924 947 f 947 924 948 f 924 925 948 f 948 925 949 f 925 926 949 f 949 926 950 f 926 927 950 f 950 927 951 f 927 904 951 f 951 904 928 f 928 929 952 f 952 929 953 f 929 930 953 f 953 930 954 f 930 931 954 f 954 931 955 f 931 932 955 f 955 932 956 f 932 933 956 f 956 933 957 f 933 934 957 f 957 934 958 f 934 935 958 f 958 935 959 f 935 936 959 f 959 936 960 f 936 937 960 f 960 937 961 f 937 938 961 f 961 938 962 f 938 939 962 f 962 939 963 f 939 940 963 f 963 940 964 f 940 941 964 f 964 941 965 f 941 942 965 f 965 942 966 f 942 943 966 f 966 943 967 f 943 944 967 f 967 944 968 f 944 945 968 f 968 945 969 f 945 946 969 f 969 946 970 f 946 947 970 f 970 947 971 f 947 948 971 f 971 948 972 f 948 949 972 f 972 949 973 f 949 950 973 f 973 950 974 f 950 951 974 f 974 951 975 f 951 928 975 f 975 928 952 f 952 953 976 f 976 953 977 f 953 954 977 f 977 954 978 f 954 955 978 f 978 955 979 f 955 956 979 f 979 956 980 f 956 957 980 f 980 957 981 f 957 958 981 f 981 958 982 f 958 959 982 f 982 959 983 f 959 960 983 f 983 960 984 f 960 961 984 f 984 961 985 f 961 962 985 f 985 962 986 f 962 963 986 f 986 963 987 f 963 964 987 f 987 964 988 f 964 965 988 f 988 965 989 f 965 966 989 f 989 966 990 f 966 967 990 f 990 967 991 f 967 968 991 f 991 968 992 f 968 969 992 f 992 969 993 f 969 970 993 f 993 970 994 f 970 971 994 f 994 971 995 f 971 972 995 f 995 972 996 f 972 973 996 f 996 973 997 f 973 974 997 f 997 974 998 f 974 975 998 f 998 975 999 f 975 952 999 f 999 952 976 f 976 977 1000 f 1000 977 1001 f 977 978 1001 f 1001 978 1002 f 978 979 1002 f 1002 979 1003 f 979 980 1003 f 1003 980 1004 f 980 981 1004 f 1004 981 1005 f 981 982 1005 f 1005 982 1006 f 982 983 1006 f 1006 983 1007 f 983 984 1007 f 1007 984 1008 f 984 985 1008 f 1008 985 1009 f 985 986 1009 f 1009 986 1010 f 986 987 1010 f 1010 987 1011 f 987 988 1011 f 1011 988 1012 f 988 989 1012 f 1012 989 1013 f 989 990 1013 f 1013 990 1014 f 990 991 1014 f 1014 991 1015 f 991 992 1015 f 1015 992 1016 f 992 993 1016 f 1016 993 1017 f 993 994 1017 f 1017 994 1018 f 994 995 1018 f 1018 995 1019 f 995 996 1019 f 1019 996 1020 f 996 997 1020 f 1020 997 1021 f 997 998 1021 f 1021 998 1022 f 998 999 1022 f 1022 999 1023 f 999 976 1023 f 1023 976 1000 f 1000 1001 1024 f 1024 1001 1025 f 1001 1002 1025 f 1025 1002 1026 f 1002 1003 1026 f 1026 1003 1027 f 1003 1004 1027 f 1027 1004 1028 f 1004 1005 1028 f 1028 1005 1029 f 1005 1006 1029 f 1029 1006 1030 f 1006 1007 1030 f 1030 1007 1031 f 1007 1008 1031 f 1031 1008 1032 f 1008 1009 1032 f 1032 1009 1033 f 1009 1010 1033 f 1033 1010 1034 f 1010 1011 1034 f 1034 1011 1035 f 1011 1012 1035 f 1035 1012 1036 f 1012 1013 1036 f 1036 1013 1037 f 1013 1014 1037 f 1037 1014 1038 f 1014 1015 1038 f 1038 1015 1039 f 1015 1016 1039 f 1039 1016 1040 f 1016 1017 1040 f 1040 1017 1041 f 1017 1018 1041 f 1041 1018 1042 f 1018 1019 1042 f 1042 1019 1043 f 1019 1020 1043 f 1043 1020 1044 f 1020 1021 1044 f 1044 1021 1045 f 1021 1022 1045 f 1045 1022 1046 f 1022 1023 1046 f 1046 1023 1047 f 1023 1000 1047 f 1047 1000 1024 f 1024 1025 1048 f 1048 1025 1049 f 1025 1026 1049 f 1049 1026 1050 f 1026 1027 1050 f 1050 1027 1051 f 1027 1028 1051 f 1051 1028 1052 f 1028 1029 1052 f 1052 1029 1053 f 1029 1030 1053 f 1053 1030 1054 f 1030 1031 1054 f 1054 1031 1055 f 1031 1032 1055 f 1055 1032 1056 f 1032 1033 1056 f 1056 1033 1057 f 1033 1034 1057 f 1057 1034 1058 f 1034 1035 1058 f 1058 1035 1059 f 1035 1036 1059 f 1059 1036 1060 f 1036 1037 1060 f 1060 1037 1061 f 1037 1038 1061 f 1061 1038 1062 f 1038 1039 1062 f 1062 1039 1063 f 1039 1040 1063 f 1063 1040 1064 f 1040 1041 1064 f 1064 1041 1065 f 1041 1042 1065 f 1065 1042 1066 f 1042 1043 1066 f 1066 1043 1067 f 1043 1044 1067 f 1067 1044 1068 f 1044 1045 1068 f 1068 1045 1069 f 1045 1046 1069 f 1069 1046 1070 f 1046 1047 1070 f 1070 1047 1071 f 1047 1024 1071 f 1071 1024 1048

  • /
      </source>
   
  
 
  



Java 3D Box and a custom Cuboid implementation

   <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.BorderLayout; import java.awt.GraphicsConfigTemplate; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.net.URL; import javax.media.j3d.Alpha; import javax.media.j3d.Appearance; import javax.media.j3d.AudioDevice; import javax.media.j3d.Background; import javax.media.j3d.BoundingSphere; import javax.media.j3d.Bounds; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Geometry; import javax.media.j3d.GeometryArray; import javax.media.j3d.GraphicsConfigTemplate3D; import javax.media.j3d.Group; import javax.media.j3d.Locale; import javax.media.j3d.Node; import javax.media.j3d.NodeComponent; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.QuadArray; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TriangleArray; import javax.media.j3d.View; import javax.media.j3d.ViewPlatform; import javax.media.j3d.VirtualUniverse; import javax.vecmath.Color3f; import javax.vecmath.Point2f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.TexCoord2f; 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.Box; import com.sun.j3d.utils.geometry.Primitive; /**

* Creates a scene using the Java 3D Box and a custom Cuboid implementation that
* uses Quads for sides instead of TriArrays
*/

public class CuboidTest extends Java3dApplet implements ActionListener {

 private static int m_kWidth = 400;
 private static int m_kHeight = 400;
 public CuboidTest() {
   initJava3d();
 }
 public void actionPerformed(ActionEvent event) {
 }
 protected Background createBackground() {
   return null;
 }
 protected double getScale() {
   return 0.1;
 }
 protected BranchGroup createSceneBranchGroup() {
   BranchGroup objRoot = super.createSceneBranchGroup();
   TransformGroup objTrans = new TransformGroup();
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   Transform3D yAxis = new Transform3D();
   Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0,
       4000, 0, 0, 0, 0, 0);
   RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
       objTrans, yAxis, 0.0f, (float) Math.PI * 2.0f);
   rotator.setSchedulingBounds(bounds);
   objTrans.addChild(rotator);
   // create an appearance
   Appearance ap = new Appearance();
   // render as a wireframe
   PolygonAttributes polyAttrbutes = new PolygonAttributes();
   polyAttrbutes.setPolygonMode(PolygonAttributes.POLYGON_LINE);
   polyAttrbutes.setCullFace(PolygonAttributes.CULL_NONE);
   ap.setPolygonAttributes(polyAttrbutes);
   objTrans.addChild(new Cuboid(50, 30, 20, ap));
   objTrans.addChild(new Box(25, 15, 10, ap));
   objRoot.addChild(objTrans);
   return objRoot;
 }
 public static void main(String[] args) {
   CuboidTest cuboidTest = new CuboidTest();
   cuboidTest.saveCommandLineArguments(args);
   new MainFrame(cuboidTest, m_kWidth, m_kHeight);
 }

} //Based on Sun"s GeomBuffer.java 1.12 98/07/08 11:30:12 //This version actually returns Quadstrips for a Quadstrip array //unlike the newer version that returns TriangleStrips.... /**

* OldGeomBuffer allows OpenGL-like input of geometry data. It outputs Java 3D
* geometry array objects. This utility is to simplify porting of OpenGL
* programs to Java 3D.
* <p>
* Here is a sample code that use this utility to create some quads.
* <P>
*

*

*
 * 
 * 
 * OldGeomBuffer gbuf = new OldGeomBuffer(100);
 * gbuf.begin(OldGeomBuffer.QUADS);
 * 
 * for (int i = 0; i < 5; i++) {
 *   gbuf.normal3d(0.0, 1.0, 0.0);
 *   gbuf.vertex3d(1.0, 1.0, 0.0);
 * 
 *   gbuf.normal3d(0.0, 1.0, 0.0);
 *   gbuf.vertex3d(0.0, 1.0, 0.0);
 * 
 *   gbuf.normal3d(0.0, 1.0, 0.0);
 *   gbuf.vertex3d(0.0, 0.0, 0.0);
 * 
 *   gbuf.normal3d(0.0, 1.0, 0.0);
 *   gbuf.vertex3d(1.0, 0.0, 0.0);
 * }
 * gbuf.end();
 * Shape3D shape = new Shape3D(gbuf.getGeom(OldGeomBuffer.GENERATE_NORMALS));
 * 

*

*
Notice, that you only need to specify some upperbound on the
* number of points you"ll use at the beginning (100 in this case).
* <p>
* Currently, you are limited to one primitive type per geom buffer. Future
* versions will add support for mixed primitive types.
*  
*/

class OldGeomBuffer extends Object {

 //Supported Primitives
 static final int QUAD_STRIP = 0x01;
 static final int TRIANGLES = 0x02;
 static final int QUADS = 0x04;
 private int flags;
 static final int GENERATE_NORMALS = 0x01;
 static final int GENERATE_TEXTURE_COORDS = 0x02;
 Point3f[] pts = null;
 Vector3f[] normals = null;
 Point2f[] tcoords = null;
 int currVertCnt;
 int currPrimCnt;
 int[] currPrimType = null, currPrimStartVertex = null,
     currPrimEndVertex = null;
 GeometryArray geometry;
 int numVerts = 0;
 int numTris = 0;
 static final int debug = 0;
 /**
  * Creates a geometry buffer of given number of vertices
  * 
  * @param numVerts
  *            total number of vertices to allocate by this buffer. This is
  *            an upper bound estimate.
  */
 OldGeomBuffer(int numVerts) {
   pts = new Point3f[numVerts];
   normals = new Vector3f[numVerts];
   tcoords = new Point2f[numVerts];
   // max primitives is numV/3
   currPrimType = new int[numVerts / 3];
   currPrimStartVertex = new int[numVerts / 3];
   currPrimEndVertex = new int[numVerts / 3];
   currVertCnt = 0;
   currPrimCnt = 0;
 }
 /*
  * Returns a Java 3D geometry array from the geometry buffer. You need to
  * call begin, vertex3d, end, etc. before calling this, of course.
  * 
  * @param format vertex format.
  */
 GeometryArray getGeom(int format) {
   GeometryArray obj;
   flags = format;
   numTris = 0;
   //Switch based on first primitive.
   switch (currPrimType[0]) {
   case TRIANGLES:
     obj = processTriangles();
     obj.setCapability(Geometry.ALLOW_INTERSECT);
     return obj;
   case QUADS:
     obj = processQuads();
     obj.setCapability(Geometry.ALLOW_INTERSECT);
     return obj;
   case QUAD_STRIP:
     obj = processQuadStrips();
     obj.setCapability(Geometry.ALLOW_INTERSECT);
     return obj;
   }
   return null;
 }
 /**
  * Begins a new primitive given the primitive type.
  * 
  * @param prim
  *            the primitive type (listed above).
  *  
  */
 void begin(int prim) {
   if (debug >= 1)
     System.out.println("quad");
   currPrimType[currPrimCnt] = prim;
   currPrimStartVertex[currPrimCnt] = currVertCnt;
 }
 /**
  * End of primitive.
  * 
  *  
  */
 void end() {
   if (debug >= 1)
     System.out.println("end");
   currPrimEndVertex[currPrimCnt] = currVertCnt;
   currPrimCnt++;
 }
 void vertex3d(double x, double y, double z) {
   if (debug >= 2)
     System.out.println("v " + x + " " + y + " " + z);
   pts[currVertCnt] = new Point3f();
   pts[currVertCnt].x = (float) x;
   pts[currVertCnt].y = (float) y;
   pts[currVertCnt].z = (float) z;
   currVertCnt++;
 }
 void normal3d(double x, double y, double z) {
   if (debug >= 2)
     System.out.println("n " + x + " " + y + " " + z);
   double sum = x * x + y * y + z * z;
   if (Math.abs(sum - 1.0) > 0.001) {
     if (debug >= 2)
       System.out.println("normalizing");
     double root = Math.sqrt(sum) + 0.0000001;
     x /= root;
     y /= root;
     z /= root;
   }
   normals[currVertCnt] = new Vector3f();
   normals[currVertCnt].x = (float) x;
   normals[currVertCnt].y = (float) y;
   normals[currVertCnt].z = (float) z;
 }
 void texCoord2d(double s, double t) {
   if (debug >= 2)
     System.out.println("t " + s + " " + t);
   tcoords[currVertCnt] = new Point2f();
   tcoords[currVertCnt].x = (float) s;
   tcoords[currVertCnt].y = (float) t;
 }
 /**
  * Returns the Java 3D geometry gotten from calling getGeom.
  *  
  */
 GeometryArray getComputedGeometry() {
   return geometry;
 }
 int getNumTris() {
   return numTris;
 }
 int getNumVerts() {
   return numVerts;
 }
 private GeometryArray processQuadStrips() {
   GeometryArray obj = null;
   int i;
   int totalVerts = 0;
   for (i = 0; i < currPrimCnt; i++) {
     int numQuadStripVerts;
     numQuadStripVerts = currPrimEndVertex[i] - currPrimStartVertex[i];
     totalVerts += (numQuadStripVerts / 2 - 1) * 4;
   }
   if (debug >= 1)
     System.out.println("totalVerts " + totalVerts);
   if (((flags & GENERATE_NORMALS) != 0)
       && ((flags & GENERATE_TEXTURE_COORDS) != 0)) {
     obj = new QuadArray(totalVerts, QuadArray.COORDINATES
         | QuadArray.NORMALS | QuadArray.TEXTURE_COORDINATE_2);
   } else if (((flags & GENERATE_NORMALS) == 0)
       && ((flags & GENERATE_TEXTURE_COORDS) != 0)) {
     obj = new QuadArray(totalVerts, QuadArray.COORDINATES
         | QuadArray.TEXTURE_COORDINATE_2);
   } else if (((flags & GENERATE_NORMALS) != 0)
       && ((flags & GENERATE_TEXTURE_COORDS) == 0)) {
     obj = new QuadArray(totalVerts, QuadArray.COORDINATES
         | QuadArray.NORMALS);
   } else {
     obj = new QuadArray(totalVerts, QuadArray.COORDINATES);
   }
   Point3f[] newpts = new Point3f[totalVerts];
   Vector3f[] newnormals = new Vector3f[totalVerts];
   TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
   int currVert = 0;
   for (i = 0; i < currPrimCnt; i++) {
     for (int j = currPrimStartVertex[i] + 2; j < currPrimEndVertex[i]; j += 2) {
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j - 2);
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j - 1);
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j + 1);
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j);
       numTris += 2;
     }
   }
   numVerts = currVert;
   obj.setCoordinates(0, newpts);
   if ((flags & GENERATE_NORMALS) != 0)
     obj.setNormals(0, newnormals);
   if ((flags & GENERATE_TEXTURE_COORDS) != 0)
     obj.setTextureCoordinates(0, 0, newtcoords);
   geometry = obj;
   return obj;
 }
 private GeometryArray processQuads() {
   GeometryArray obj = null;
   int i;
   int totalVerts = 0;
   for (i = 0; i < currPrimCnt; i++) {
     totalVerts += currPrimEndVertex[i] - currPrimStartVertex[i];
   }
   if (debug >= 1)
     System.out.println("totalVerts " + totalVerts);
   if (((flags & GENERATE_NORMALS) != 0)
       && ((flags & GENERATE_TEXTURE_COORDS) != 0)) {
     obj = new QuadArray(totalVerts, QuadArray.COORDINATES
         | QuadArray.NORMALS | QuadArray.TEXTURE_COORDINATE_2);
   } else if (((flags & GENERATE_NORMALS) == 0)
       && ((flags & GENERATE_TEXTURE_COORDS) != 0)) {
     obj = new QuadArray(totalVerts, QuadArray.COORDINATES
         | QuadArray.TEXTURE_COORDINATE_2);
   } else if (((flags & GENERATE_NORMALS) != 0)
       && ((flags & GENERATE_TEXTURE_COORDS) == 0)) {
     obj = new QuadArray(totalVerts, QuadArray.COORDINATES
         | QuadArray.NORMALS);
   } else {
     obj = new QuadArray(totalVerts, QuadArray.COORDINATES);
   }
   Point3f[] newpts = new Point3f[totalVerts];
   Vector3f[] newnormals = new Vector3f[totalVerts];
   TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
   int currVert = 0;
   if (debug > 1)
     System.out.println("total prims " + currPrimCnt);
   for (i = 0; i < currPrimCnt; i++) {
     if (debug > 1)
       System.out.println("start " + currPrimStartVertex[i] + " end "
           + currPrimEndVertex[i]);
     for (int j = currPrimStartVertex[i]; j < currPrimEndVertex[i] - 3; j += 4) {
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j);
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j + 1);
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j + 2);
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j + 3);
       numTris += 2;
     }
   }
   numVerts = currVert;
   obj.setCoordinates(0, newpts);
   if ((flags & GENERATE_NORMALS) != 0)
     obj.setNormals(0, newnormals);
   if ((flags & GENERATE_TEXTURE_COORDS) != 0)
     obj.setTextureCoordinates(0, 0, newtcoords);
   geometry = obj;
   return obj;
 }
 private GeometryArray processTriangles() {
   GeometryArray obj = null;
   int i;
   int totalVerts = 0;
   for (i = 0; i < currPrimCnt; i++) {
     totalVerts += currPrimEndVertex[i] - currPrimStartVertex[i];
   }
   if (debug >= 1)
     System.out.println("totalVerts " + totalVerts);
   if (((flags & GENERATE_NORMALS) != 0)
       && ((flags & GENERATE_TEXTURE_COORDS) != 0)) {
     obj = new TriangleArray(totalVerts, TriangleArray.COORDINATES
         | TriangleArray.NORMALS
         | TriangleArray.TEXTURE_COORDINATE_2);
   } else if (((flags & GENERATE_NORMALS) == 0)
       && ((flags & GENERATE_TEXTURE_COORDS) != 0)) {
     obj = new TriangleArray(totalVerts, TriangleArray.COORDINATES
         | TriangleArray.TEXTURE_COORDINATE_2);
   } else if (((flags & GENERATE_NORMALS) != 0)
       && ((flags & GENERATE_TEXTURE_COORDS) == 0)) {
     obj = new TriangleArray(totalVerts, TriangleArray.COORDINATES
         | TriangleArray.NORMALS);
   } else {
     obj = new TriangleArray(totalVerts, TriangleArray.COORDINATES);
   }
   Point3f[] newpts = new Point3f[totalVerts];
   Vector3f[] newnormals = new Vector3f[totalVerts];
   TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
   int currVert = 0;
   for (i = 0; i < currPrimCnt; i++) {
     for (int j = currPrimStartVertex[i]; j < currPrimEndVertex[i] - 2; j += 3) {
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j);
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j + 1);
       outVertex(newpts, newnormals, newtcoords, currVert++, pts,
           normals, tcoords, j + 2);
       numTris += 1;
     }
   }
   numVerts = currVert;
   obj.setCoordinates(0, newpts);
   if ((flags & GENERATE_NORMALS) != 0)
     obj.setNormals(0, newnormals);
   if ((flags & GENERATE_TEXTURE_COORDS) != 0)
     obj.setTextureCoordinates(0, 0, newtcoords);
   geometry = obj;
   return obj;
 }
 void outVertex(Point3f[] dpts, Vector3f[] dnormals, TexCoord2f[] dtcoords,
     int dloc, Point3f[] spts, Vector3f[] snormals, Point2f[] stcoords,
     int sloc) {
   if (debug >= 1)
     System.out.println("v " + spts[sloc].x + " " + spts[sloc].y + " "
         + spts[sloc].z);
   dpts[dloc] = new Point3f();
   dpts[dloc].x = spts[sloc].x;
   dpts[dloc].y = spts[sloc].y;
   dpts[dloc].z = spts[sloc].z;
   if ((flags & GENERATE_NORMALS) != 0) {
     dnormals[dloc] = new Vector3f();
     dnormals[dloc].x = snormals[sloc].x;
     dnormals[dloc].y = snormals[sloc].y;
     dnormals[dloc].z = snormals[sloc].z;
   }
   if ((flags & GENERATE_TEXTURE_COORDS) != 0) {
     if (debug >= 2)
       System.out.println("final out tcoord");
     dtcoords[dloc] = new TexCoord2f();
     dtcoords[dloc].x = stcoords[sloc].x;
     dtcoords[dloc].y = stcoords[sloc].y;
   }
 }

} //Based on Sun"s Box.java 1.13 98/11/23 10:23:02 //Work around for the Box bug when rendered in Wireframe mode. /**

* Cuboid is a geometry primitive created with a given length, width, and
* height. It is centered at the origin. By default, it lies within the bounding
* Cuboid, [-1,-1,-1] and [1,1,1].
* 
* When a texture is applied to a Cuboid, it is map CCW like on a Cylinder. A
* texture is mapped CCW from the back of the body. The top and bottom faces are
* mapped such that the texture appears front facing when the faces are rotated
* 90 toward the viewer.
*/

class Cuboid extends Primitive {

 protected int numTris = 0;
 protected int numVerts = 0;
 /**
  * Primitive flags.
  */
 protected int flags;
 /**
  * Used to designate the front side of the Cuboid when using getShape().
  * 
  * @see Cuboid#getShape
  */
 public static final int FRONT = 0;
 /**
  * Used to designate the back side of the Cuboid when using getShape().
  * 
  * @see Cuboid#getShape
  */
 public static final int BACK = 1;
 /**
  * Used to designate the right side of the Cuboid when using getShape().
  * 
  * @see Cuboid#getShape
  */
 public static final int RIGHT = 2;
 /**
  * Used to designate the left side of the Cuboid when using getShape().
  * 
  * @see Cuboid#getShape
  */
 public static final int LEFT = 3;
 /**
  * Used to designate the top side of the Cuboid when using getShape().
  * 
  * @see Cuboid#getShape
  */
 public static final int TOP = 4;
 /**
  * Used to designate the bottom side of the Cuboid when using getShape().
  * 
  * @see Cuboid#getShape
  */
 public static final int BOTTOM = 5;
 float xDim, yDim, zDim;
 /**
  * Constructs a default Cuboid of 1.0 in all dimensions.
  */
 public Cuboid() {
   this(1.0f, 1.0f, 1.0f, GENERATE_NORMALS, null);
 }
 public Appearance getAppearance(int index) {
   return null;
 }
 /**
  * Constructs a Cuboid of a given dimension and appearance.
  * 
  * @param xdim
  *            X-dimension size.
  * @param ydim
  *            Y-dimension size.
  * @param zdim
  *            Z-dimension size.
  * @param ap
  *            Appearance
  */
 public Cuboid(float xdim, float ydim, float zdim, Appearance ap) {
   this(xdim, ydim, zdim, GENERATE_NORMALS, ap);
 }
 /**
  * Constructs a Cuboid of a given dimension, flags, and appearance.
  * 
  * @param xdim
  *            X-dimension size.
  * @param ydim
  *            Y-dimension size.
  * @param zdim
  *            Z-dimension size.
  * @param primflags
  *            primitive flags.
  * @param ap
  *            Appearance
  */
 public Cuboid(float xdim, float ydim, float zdim, int primflags,
     Appearance ap) {
   int i;
   double sign;
   xDim = xdim;
   yDim = ydim;
   zDim = zdim;
   flags = primflags;
   //Depending on whether normal inward bit is set.
   if ((flags & GENERATE_NORMALS_INWARD) != 0)
     sign = -1.0;
   else
     sign = 1.0;
   TransformGroup objTrans = new TransformGroup();
   objTrans.setCapability(ALLOW_CHILDREN_READ);
   this.addChild(objTrans);
   Shape3D shape[] = new Shape3D[6];
   for (i = FRONT; i <= BOTTOM; i++) {
     OldGeomBuffer gbuf = new OldGeomBuffer(4);
     gbuf.begin(OldGeomBuffer.QUAD_STRIP);
     for (int j = 0; j < 2; j++) {
       gbuf.normal3d((double) normals[i].x * sign,
           (double) normals[i].y * sign, (double) normals[i].z
               * sign);
       gbuf.texCoord2d(tcoords[i * 8 + j * 2], tcoords[i * 8 + j * 2
           + 1]);
       gbuf.vertex3d((double) verts[i * 12 + j * 3] * xdim,
           (double) verts[i * 12 + j * 3 + 1] * ydim,
           (double) verts[i * 12 + j * 3 + 2] * zdim);
     }
     for (int j = 3; j > 1; j--) {
       gbuf.normal3d((double) normals[i].x * sign,
           (double) normals[i].y * sign, (double) normals[i].z
               * sign);
       gbuf.texCoord2d(tcoords[i * 8 + j * 2], tcoords[i * 8 + j * 2
           + 1]);
       gbuf.vertex3d((double) verts[i * 12 + j * 3] * xdim,
           (double) verts[i * 12 + j * 3 + 1] * ydim,
           (double) verts[i * 12 + j * 3 + 2] * zdim);
     }
     gbuf.end();
     shape[i] = new Shape3D(gbuf.getGeom(flags));
     numVerts = gbuf.getNumVerts();
     numTris = gbuf.getNumTris();
     if ((flags & ENABLE_APPEARANCE_MODIFY) != 0) {
       (shape[i]).setCapability(Shape3D.ALLOW_APPEARANCE_READ);
       (shape[i]).setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
     }
     objTrans.addChild(shape[i]);
   }
   if (ap == null) {
     setAppearance();
   } else
     setAppearance(ap);
 }
 /**
  * Gets one of the faces (Shape3D) from the Cuboid that contains the
  * geometry and appearance. This allows users to modify the appearance or
  * geometry of individual parts.
  * 
  * @param partId
  *            The part to return.
  * @return The Shape3D object associated with the partID. If an invalid
  *         partId is passed in, null is returned.
  */
 public Shape3D getShape(int partId) {
   if ((partId >= FRONT) && (partId <= BOTTOM))
     return (Shape3D) (((Group) getChild(0)).getChild(partId));
   return null;
 }
 /**
  * Sets appearance of the Cuboid. This will set each face of the Cuboid to
  * the same appearance. To set each face"s appearance separately, use
  * getShape(partId) to get the individual shape and call
  * shape.setAppearance(ap).
  */
 public void setAppearance(Appearance ap) {
   ((Shape3D) ((Group) getChild(0)).getChild(TOP)).setAppearance(ap);
   ((Shape3D) ((Group) getChild(0)).getChild(LEFT)).setAppearance(ap);
   ((Shape3D) ((Group) getChild(0)).getChild(RIGHT)).setAppearance(ap);
   ((Shape3D) ((Group) getChild(0)).getChild(FRONT)).setAppearance(ap);
   ((Shape3D) ((Group) getChild(0)).getChild(BACK)).setAppearance(ap);
   ((Shape3D) ((Group) getChild(0)).getChild(BOTTOM)).setAppearance(ap);
 }
 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 double[] tcoords = {
 // front
     1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
     // back
     1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
     //right
     1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
     // left
     1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
     // top
     1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
     // bottom
     0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 };
 private static final Vector3f[] normals = { new Vector3f(0.0f, 0.0f, 1.0f), // front
                                       // face
     new Vector3f(0.0f, 0.0f, -1.0f), // back face
     new Vector3f(1.0f, 0.0f, 0.0f), // right face
     new Vector3f(-1.0f, 0.0f, 0.0f), // left face
     new Vector3f(0.0f, 1.0f, 0.0f), // top face
     new Vector3f(0.0f, -1.0f, 0.0f), // bottom face
 };
 /**
  * Used to create a new instance of the node. This routine is called by
  * cloneTree to duplicate the current node.
  * cloneNode should be overridden by any user subclassed
  * objects. All subclasses must have their cloneNode method
  * consist of the following lines:
  * <P>
*

*

*
   * public Node cloneNode(boolean forceDuplicate) {
   *   UserSubClass usc = new UserSubClass();
   *   usc.duplicateNode(this, forceDuplicate);
   *   return usc;
   * }
   * 

*

*
  * 
  * @param forceDuplicate
  *            when set to true, causes the
  *            duplicateOnCloneTree flag to be ignored. When
  *            false, the value of each node"s
  *            duplicateOnCloneTree variable determines
  *            whether NodeComponent data is duplicated or copied.
  * 
  * @see Node#cloneTree
  * @see Node#duplicateNode
  * @see NodeComponent#setDuplicateOnCloneTree
  */
 public Node cloneNode(boolean forceDuplicate) {
   Cuboid b = new Cuboid(xDim, yDim, zDim, flags, getAppearance());
   b.duplicateNode(this, forceDuplicate);
   return b;
 }
 /**
  * Copies all node information from originalNode into the
  * current node. This method is called from the cloneNode
  * method which is, in turn, called by the cloneTree method.
  * <P>
  * For any NodeComponent  objects contained by the object being
  * duplicated, each NodeComponent  object"s
  * duplicateOnCloneTree value is used to determine whether
  * the NodeComponent  should be duplicated in the new node or if just
  * a reference to the current node should be placed in the new node. This
  * flag can be overridden by setting the forceDuplicate
  * parameter in the cloneTree method to true.
  * 
  * @param originalNode
  *            the original node to duplicate.
  * @param forceDuplicate
  *            when set to true, causes the
  *            duplicateOnCloneTree flag to be ignored. When
  *            false, the value of each node"s
  *            duplicateOnCloneTree variable determines
  *            whether NodeComponent data is duplicated or copied.
  * 
  * @see Node#cloneTree
  * @see Node#cloneNode
  * @see NodeComponent#setDuplicateOnCloneTree
  */
 public void duplicateNode(Node originalNode, boolean forceDuplicate) {
   super.duplicateNode(originalNode, forceDuplicate);
 }

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

* 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>
   
  
 
  



Line Types

   <source lang="java">

/*

* %Z%%M% %I% %E% %U%
* 
* ************************************************************** "Copyright (c)
* 2001 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.Dimension; import java.awt.GraphicsConfiguration; import java.awt.GridLayout; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.text.NumberFormat; 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.ColoringAttributes; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Group; import javax.media.j3d.ImageComponent; import javax.media.j3d.ImageComponent2D; import javax.media.j3d.LineArray; import javax.media.j3d.LineAttributes; import javax.media.j3d.Screen3D; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.vecmath.AxisAngle4f; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3f; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import com.sun.image.codec.jpeg.JPEGImageEncoder; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.mouse.MouseRotate; import com.sun.j3d.utils.universe.SimpleUniverse; public class LineTypes extends Applet {

 SimpleUniverse u;
 boolean isApplication;
 Canvas3D canvas;
 View view;
 /* image capture */
 OffScreenCanvas3D offScreenCanvas;
 float offScreenScale = 1.0f;
 String snapImageString = "Snap Image";
 // GUI elements
 JTabbedPane tabbedPane;
 // Temporaries that are reused
 Transform3D tmpTrans = new Transform3D();
 Vector3f tmpVector = new Vector3f();
 AxisAngle4f tmpAxisAngle = new AxisAngle4f();
 // colors for use in the cones
 Color3f red = new Color3f(1.0f, 0.0f, 0.0f);
 Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
 Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
 // geometric constants
 Point3f origin = new Point3f();
 Vector3f yAxis = new Vector3f(0.0f, 1.0f, 0.0f);
 // NumberFormat to print out floats with only two digits
 NumberFormat nf;
 // Returns the TransformGroup we will be editing to change the tranform
 // on the lines
 Group createLineTypes() {
   Group lineGroup = new Group();
   Appearance app = new Appearance();
   ColoringAttributes ca = new ColoringAttributes(black,
       ColoringAttributes.SHADE_FLAT);
   app.setColoringAttributes(ca);
   // Plain line
   Point3f[] plaPts = new Point3f[2];
   plaPts[0] = new Point3f(-0.9f, -0.7f, 0.0f);
   plaPts[1] = new Point3f(-0.5f, 0.7f, 0.0f);
   LineArray pla = new LineArray(2, LineArray.COORDINATES);
   pla.setCoordinates(0, plaPts);
   Shape3D plShape = new Shape3D(pla, app);
   lineGroup.addChild(plShape);
   // line pattern dot
   Point3f[] dotPts = new Point3f[2];
   dotPts[0] = new Point3f(-0.4f, -0.7f, 0.0f);
   dotPts[1] = new Point3f(-0.0f, 0.7f, 0.0f);
   LineArray dot = new LineArray(2, LineArray.COORDINATES);
   dot.setCoordinates(0, dotPts);
   LineAttributes dotLa = new LineAttributes();
   dotLa.setLineWidth(2.0f);
   dotLa.setLinePattern(LineAttributes.PATTERN_DOT);
   Appearance dotApp = new Appearance();
   dotApp.setLineAttributes(dotLa);
   dotApp.setColoringAttributes(ca);
   Shape3D dotShape = new Shape3D(dot, dotApp);
   lineGroup.addChild(dotShape);
   // line pattern dash
   Point3f[] dashPts = new Point3f[2];
   dashPts[0] = new Point3f(-0.0f, -0.7f, 0.0f);
   dashPts[1] = new Point3f(0.4f, 0.7f, 0.0f);
   LineArray dash = new LineArray(2, LineArray.COORDINATES);
   dash.setCoordinates(0, dashPts);
   LineAttributes dashLa = new LineAttributes();
   dashLa.setLineWidth(4.0f);
   dashLa.setLinePattern(LineAttributes.PATTERN_DASH);
   Appearance dashApp = new Appearance();
   dashApp.setLineAttributes(dashLa);
   dashApp.setColoringAttributes(ca);
   Shape3D dashShape = new Shape3D(dash, dashApp);
   lineGroup.addChild(dashShape);
   // line pattern dot-dash
   Point3f[] dotDashPts = new Point3f[2];
   dotDashPts[0] = new Point3f(0.5f, -0.7f, 0.0f);
   dotDashPts[1] = new Point3f(0.9f, 0.7f, 0.0f);
   LineArray dotDash = new LineArray(2, LineArray.COORDINATES);
   dotDash.setCoordinates(0, dotDashPts);
   LineAttributes dotDashLa = new LineAttributes();
   dotDashLa.setLineWidth(4.0f);
   dotDashLa.setLinePattern(LineAttributes.PATTERN_DASH_DOT);
   Appearance dotDashApp = new Appearance();
   dotDashApp.setLineAttributes(dotDashLa);
   dotDashApp.setColoringAttributes(ca);
   Shape3D dotDashShape = new Shape3D(dotDash, dotDashApp);
   lineGroup.addChild(dotDashShape);
   return lineGroup;
 }
 BranchGroup createSceneGraph() {
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   // Create a TransformGroup to scale the scene down by 3.5x
   // TODO: move view platform instead of scene using orbit behavior
   TransformGroup objScale = new TransformGroup();
   Transform3D scaleTrans = new Transform3D();
   //scaleTrans.set(1 / 3.5f); // scale down by 3.5x
   objScale.setTransform(scaleTrans);
   objRoot.addChild(objScale);
   // Create a TransformGroup and initialize it to the
   // identity. Enable the TRANSFORM_WRITE capability so that
   // the mouse behaviors 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);
   objScale.addChild(objTrans);
   // Add the primitives to the scene
   objTrans.addChild(createLineTypes());
   BoundingSphere bounds = new BoundingSphere(new Point3d(), 100.0);
   Background bg = new Background(new Color3f(1.0f, 1.0f, 1.0f));
   bg.setApplicationBounds(bounds);
   objTrans.addChild(bg);
   // set up the mouse rotation behavior
   MouseRotate mr = new MouseRotate();
   mr.setTransformGroup(objTrans);
   mr.setSchedulingBounds(bounds);
   mr.setFactor(0.007);
   objTrans.addChild(mr);
   // 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, 1.0f);
   Vector3f light1Direction = new Vector3f(0.0f, -0.2f, -1.0f);
   DirectionalLight light1 = new DirectionalLight(light1Color,
       light1Direction);
   light1.setInfluencingBounds(bounds);
   objRoot.addChild(light1);
   return objRoot;
 }
 public LineTypes() {
   this(false);
 }
 public LineTypes(boolean isApplication) {
   this.isApplication = isApplication;
 }
 public void init() {
   // set up a NumFormat object to print out float with only 3 fraction
   // digits
   nf = NumberFormat.getInstance();
   nf.setMaximumFractionDigits(3);
   setLayout(new BorderLayout());
   GraphicsConfiguration config = SimpleUniverse
       .getPreferredConfiguration();
   canvas = new Canvas3D(config);
   add("Center", canvas);
   // Create a simple scene and attach it to the virtual universe
   BranchGroup scene = createSceneGraph();
   u = new SimpleUniverse(canvas);
   if (isApplication) {
     offScreenCanvas = new OffScreenCanvas3D(config, true);
     // set the size of the off-screen canvas based on a scale
     // of the on-screen size
     Screen3D sOn = canvas.getScreen3D();
     Screen3D sOff = offScreenCanvas.getScreen3D();
     Dimension dim = sOn.getSize();
     dim.width *= 1.0f;
     dim.height *= 1.0f;
     sOff.setSize(dim);
     sOff.setPhysicalScreenWidth(sOn.getPhysicalScreenWidth()
         * offScreenScale);
     sOff.setPhysicalScreenHeight(sOn.getPhysicalScreenHeight()
         * offScreenScale);
     // attach the offscreen canvas to the view
     u.getViewer().getView().addCanvas3D(offScreenCanvas);
   }
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   u.getViewingPlatform().setNominalViewingTransform();
   u.addBranchGraph(scene);
   view = u.getViewer().getView();
   add("South", guiPanel());
 }
 // create a panel with a tabbed pane holding each of the edit panels
 JPanel guiPanel() {
   JPanel panel = new JPanel();
   panel.setLayout(new GridLayout(0, 1));
   if (isApplication) {
     JButton snapButton = new JButton(snapImageString);
     snapButton.setActionCommand(snapImageString);
     snapButton.addActionListener(new ActionListener() {
       public void actionPerformed(ActionEvent e) {
         doSnapshot();
       }
     });
     panel.add(snapButton);
   }
   return panel;
 }
 void doSnapshot() {
   Point loc = canvas.getLocationOnScreen();
   offScreenCanvas.setOffScreenLocation(loc);
   Dimension dim = canvas.getSize();
   dim.width *= offScreenScale;
   dim.height *= offScreenScale;
   nf.setMinimumIntegerDigits(3);
   offScreenCanvas.snapImageFile("lineTypes", dim.width, dim.height);
   nf.setMinimumIntegerDigits(0);
 }
 public void destroy() {
   u.removeAllLocales();
 }
 // The following allows LineTypes to be run as an application
 // as well as an applet
 //
 public static void main(String[] args) {
   new MainFrame(new LineTypes(true), 600, 600);
 }

} class OffScreenCanvas3D extends Canvas3D {

 OffScreenCanvas3D(GraphicsConfiguration graphicsConfiguration,
     boolean offScreen) {
   super(graphicsConfiguration, offScreen);
 }
 private BufferedImage doRender(int width, int height) {
   BufferedImage bImage = new BufferedImage(width, height,
       BufferedImage.TYPE_INT_RGB);
   ImageComponent2D buffer = new ImageComponent2D(
       ImageComponent.FORMAT_RGB, bImage);
   //buffer.setYUp(true);
   setOffScreenBuffer(buffer);
   renderOffScreenBuffer();
   waitForOffScreenRendering();
   bImage = getOffScreenBuffer().getImage();
   return bImage;
 }
 void snapImageFile(String filename, int width, int height) {
   BufferedImage bImage = doRender(width, height);
   /*
    * JAI: RenderedImage fImage = JAI.create("format", bImage,
    * DataBuffer.TYPE_BYTE); JAI.create("filestore", fImage, filename +
    * ".tif", "tiff", null);
    */
   /* No JAI: */
   try {
     FileOutputStream fos = new FileOutputStream(filename + ".jpg");
     BufferedOutputStream bos = new BufferedOutputStream(fos);
     JPEGImageEncoder jie = JPEGCodec.createJPEGEncoder(bos);
     JPEGEncodeParam param = jie.getDefaultJPEGEncodeParam(bImage);
     param.setQuality(1.0f, true);
     jie.setJPEGEncodeParam(param);
     jie.encode(bImage);
     bos.flush();
     fos.close();
   } catch (Exception e) {
     System.out.println(e);
   }
 }

}


      </source>
   
  
 
  



Morphing

   <source lang="java">

/*

* @(#)Morphing.java 1.24 02/10/21 13:45:46
* 
* 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.GraphicsConfiguration; import java.io.FileNotFoundException; import java.util.Enumeration; import javax.media.j3d.Alpha; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.Background; import javax.media.j3d.Behavior; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.GeometryArray; import javax.media.j3d.Material; import javax.media.j3d.Morph; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.WakeupOnElapsedFrames; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; import com.sun.j3d.loaders.IncorrectFormatException; import com.sun.j3d.loaders.ParsingErrorException; import com.sun.j3d.loaders.Scene; import com.sun.j3d.loaders.objectfile.ObjectFile; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.universe.SimpleUniverse; public class Morphing extends Applet {

 private java.net.URL[] objFiles = null;
 private SimpleUniverse u = null;
 private BranchGroup createSceneGraph() {
   // 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(0.4);
   objScale.setTransform(t3d);
   objRoot.addChild(objScale);
   // Create a bounds for the background and lights
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   // Set up the background
   Color3f bgColor = new Color3f(0.05f, 0.05f, 0.2f);
   Background bg = new Background(bgColor);
   bg.setApplicationBounds(bounds);
   objScale.addChild(bg);
   // Set up the global lights
   Color3f lColor1 = new Color3f(0.7f, 0.7f, 0.7f);
   Vector3f lDir1 = new Vector3f(-1.0f, -1.0f, -1.0f);
   Color3f alColor = new Color3f(0.2f, 0.2f, 0.2f);
   AmbientLight aLgt = new AmbientLight(alColor);
   aLgt.setInfluencingBounds(bounds);
   DirectionalLight lgt1 = new DirectionalLight(lColor1, lDir1);
   lgt1.setInfluencingBounds(bounds);
   objScale.addChild(aLgt);
   objScale.addChild(lgt1);
   //
   // Create the transform group nodes for the 3 original objects
   // and the morphed object. Add them to the root of the
   // branch graph.
   //
   TransformGroup objTrans[] = new TransformGroup[4];
   for (int i = 0; i < 4; i++) {
     objTrans[i] = new TransformGroup();
     objScale.addChild(objTrans[i]);
   }
   Transform3D tr = new Transform3D();
   Transform3D rotX90 = new Transform3D();
   rotX90.rotX(90.0 * Math.PI / 180.0);
   objTrans[0].getTransform(tr);
   tr.setTranslation(new Vector3d(-2.0, 1.5, -2.0));
   tr.mul(rotX90);
   objTrans[0].setTransform(tr);
   objTrans[1].getTransform(tr);
   tr.setTranslation(new Vector3d(0.0, 1.5, -2.0));
   tr.mul(rotX90);
   objTrans[1].setTransform(tr);
   objTrans[2].getTransform(tr);
   tr.setTranslation(new Vector3d(2.0, 1.5, -2.0));
   tr.mul(rotX90);
   objTrans[2].setTransform(tr);
   objTrans[3].getTransform(tr);
   tr.setTranslation(new Vector3d(0.0, -2.0, -2.0));
   tr.mul(rotX90);
   objTrans[3].setTransform(tr);
   // Now load the object files
   Scene s[] = new Scene[3];
   GeometryArray g[] = new GeometryArray[3];
   Shape3D shape[] = new Shape3D[3];
   ObjectFile loader = new ObjectFile(ObjectFile.RESIZE);
   for (int i = 0; i < 3; i++) {
     s[i] = null;
     g[i] = null;
     shape[i] = null;
   }
   for (int i = 0; i < 3; i++) {
     try {
       s[i] = loader.load(objFiles[i]);
     } catch (FileNotFoundException e) {
       System.err.println(e);
       System.exit(1);
     } catch (ParsingErrorException e) {
       System.err.println(e);
       System.exit(1);
     } catch (IncorrectFormatException e) {
       System.err.println(e);
       System.exit(1);
     }
     BranchGroup b = s[i].getSceneGroup();
     shape[i] = (Shape3D) b.getChild(0);
     g[i] = (GeometryArray) shape[i].getGeometry();
     shape[i].setGeometry(g[i]);
     objTrans[i].addChild(b);
   }
   //
   // Create a Morph node, and set the appearance and input geometry
   // arrays. Set the Morph node"s capability bits to allow the weights
   // to be modified at runtime.
   //
   Appearance app = new Appearance();
   Color3f objColor = new Color3f(1.0f, 0.7f, 0.8f);
   Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
   app.setMaterial(new Material(objColor, black, objColor, black, 80.0f));
   Morph morph = new Morph(g, app);
   morph.setCapability(Morph.ALLOW_WEIGHTS_READ);
   morph.setCapability(Morph.ALLOW_WEIGHTS_WRITE);
   objTrans[3].addChild(morph);
   // 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, 2000, 1000, 200, 2000, 1000,
       200);
   // Finally, create the morphing behavior
   MorphingBehavior mBeh = new MorphingBehavior(morphAlpha, morph);
   mBeh.setSchedulingBounds(bounds);
   objScale.addChild(mBeh);
   return objRoot;
 }
 public Morphing() {
 }
 public Morphing(java.net.URL[] urls) {
   objFiles = urls;
 }
 public void init() {
   if (objFiles == null) {
     objFiles = new java.net.URL[3];
     // the path to the image for an applet
     String path = getCodeBase().toString();
     try {
       objFiles[0] = new java.net.URL(path + "hand1.obj");
       objFiles[1] = new java.net.URL(path + "hand2.obj");
       objFiles[2] = new java.net.URL(path + "hand3.obj");
     } 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);
   // 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();
 }
 public static void main(String[] args) {
   java.net.URL[] urls = new java.net.URL[3];
   // the path to the image file for an application
   try {
     urls[0] = new java.net.URL("file:./hand1.obj");
     urls[1] = new java.net.URL("file:./hand2.obj");
     urls[2] = new java.net.URL("file:./hand3.obj");
   } catch (java.net.MalformedURLException ex) {
     System.out.println(ex.getMessage());
     System.exit(1);
   }
   new MainFrame(new Morphing(urls), 700, 700);
 }

} //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();
 }

} //File: hand1.obj /*

  1. Mon Jun 02 17:09:33 1997

g hand1 v -0.551223 0.307562 -3.946050 v -0.215465 0.030475 -3.703516 v -0.059140 0.068255 -1.551531 v -0.487235 0.455792 -4.006029 v -0.168743 0.090975 -3.755638 v -0.338689 0.569450 -4.244848 v -0.639211 0.502297 -4.165243 v -0.760687 0.647871 -4.482797 v -0.529792 0.073768 -3.945949 v -0.707612 0.258064 -4.192451 v -0.866004 0.446161 -4.511733 v -0.367733 -0.147323 -4.191223 v -0.717413 0.071719 -4.433171 v -0.893823 0.253971 -4.589350 v -0.172976 -0.188212 -3.754734 v -0.089148 -0.103984 -1.450071 v -0.234491 -0.100206 -3.756646 v -0.131305 -0.032994 -1.531782 v -0.589492 0.641054 -4.376035 v -0.050594 -0.257375 -4.417058 v 0.208857 -0.205637 -4.768191 v 0.007882 -0.231806 -4.028160 v 0.230232 -0.186379 -4.335583 v 0.390435 -0.043258 -4.060836 v 0.002626 -0.129308 -1.430840 v -0.058465 -0.217994 -3.717670 v 0.087189 -0.100005 -1.425612 v 0.044163 -0.171797 -3.707954 v 0.044240 0.657156 -4.536777 v -0.137070 0.604272 -4.344090 v 0.041139 0.604901 -4.118776 v -0.080844 0.531805 -3.993031 v 0.165095 0.484110 -3.906230 v -0.081629 0.087632 -3.782753 v -0.013872 0.088823 -1.554481 v 0.008630 0.041677 -3.708195 v 0.070162 0.059225 -1.467241 v 0.349126 0.784380 -4.327246 v 0.192656 0.707311 -4.316467 v 0.240026 0.669896 -4.092967 v 0.614077 0.770599 -4.245997 v 0.448901 0.789330 -4.242595 v 0.390683 0.635870 -4.050064 v 0.823568 1.030378 -5.230011 v 0.583262 0.935220 -4.789198 v 0.936485 1.075914 -5.144932 v 0.708930 0.972489 -4.713959 v 1.079595 1.050653 -5.079602 v 0.863290 0.942616 -4.657226 v 0.731356 0.950572 -5.335061 v 0.698927 0.816156 -5.569689 v 0.452954 0.862935 -4.860037 v 0.354245 0.777679 -5.103039 v 0.109515 -0.020305 -1.439012 v 0.321579 0.190660 -3.847763 v 0.056950 -0.068344 -3.678991 v 0.551677 0.397382 -4.027330 v 0.748943 0.261978 -4.201552 v 0.797463 0.611225 -4.241810 v 0.934536 0.472987 -4.298673 v 0.919641 0.370477 -5.597496 v 1.079582 0.375487 -5.341094 v 1.225601 0.456396 -5.207421 v 0.593068 0.043314 -5.202118 v 0.711852 0.101000 -4.865152 v 0.871615 0.211454 -4.690717 v 1.063296 0.399320 -4.647913 v 1.342637 0.585582 -5.122607 v 1.150690 0.608137 -4.641154 v 1.366648 0.748651 -5.071675 v 0.745367 0.246406 -5.988852 v 0.494019 -0.022198 -5.740361 v 0.141480 -0.193021 -5.470416 v 0.693354 0.148862 -6.455598 v 0.458179 -0.058425 -6.342125 v 0.092861 -0.121753 -6.334044 v 0.001903 0.615014 -5.359071 v 0.310613 0.694999 -5.659912 v 0.602326 0.700149 -5.960638 v 0.014377 0.478587 -6.304075 v 0.335968 0.619833 -6.312831 v 0.600780 0.612337 -6.446789 v -0.303419 0.594566 -6.098518 v -0.599974 0.655996 -6.132385 v -0.241202 0.626083 -5.200386 v -0.457099 0.677790 -5.161324 v -0.259616 -0.163854 -6.116562 v -0.183392 -0.223625 -5.241480 v -0.635209 0.061396 -6.121774 v -0.504788 -0.103060 -5.122423 v -0.950019 0.234128 -5.837874 v -0.810067 0.092804 -5.080121 v -1.144829 0.478824 -5.746136 v -0.998398 0.334709 -5.084644 v -0.994164 0.856674 -5.773610 v -0.863354 0.756330 -5.102725 v -0.801998 0.842826 -5.870856 v -0.671650 0.764754 -5.123487 v 1.045049 0.802118 -4.632644 v 1.252493 0.924338 -5.055513 v -0.995449 0.583125 -5.083862 v -1.137996 0.713069 -5.735577 v 1.598002 0.816988 -5.564189 v 1.599381 0.700758 -5.624741 v 1.532017 0.614642 -5.716787 v 1.715526 0.933794 -5.717422 v 1.699604 0.816034 -5.787023 v 1.629737 0.731598 -5.898082 v 1.883043 1.059492 -5.899169 v 1.855109 0.932664 -5.998640 v 1.774384 0.842472 -6.140775 v 1.424351 0.559021 -5.523375 v 1.505227 0.658051 -5.434678 v 1.502338 0.787710 -5.373565 v 1.297397 0.577850 -5.903827 v 1.425129 0.560695 -5.822476 v 1.155962 0.509306 -5.718982 v 1.300644 0.494656 -5.623770 v 1.509245 0.835318 -6.384689 v 1.646807 0.801147 -6.286009 v 1.406474 0.713747 -6.133959 v 1.525574 0.687385 -6.031679 v 1.380351 1.065119 -5.565239 v 1.564172 1.172023 -5.714888 v 1.780605 1.304970 -5.893034 v 1.255719 1.087198 -5.619839 v 1.438416 1.182678 -5.766468 v 1.652418 1.312790 -5.952035 v 1.154437 1.043031 -5.702960 v 1.320461 1.134701 -5.855917 v 1.512782 1.262635 -6.051604 v 1.003945 1.036752 -5.521133 v 1.104476 1.081637 -5.435655 v 1.236055 1.056913 -5.374795 v 1.089111 0.843044 -5.888583 v 1.089661 0.962064 -5.803318 v 1.230625 0.966122 -6.097103 v 1.242952 1.066407 -5.981094 v 1.362597 1.098246 -6.323909 v 1.405432 1.196541 -6.191591 v 0.929064 0.824679 -5.709339 v 0.934340 0.953520 -5.615597 v 1.859089 1.203879 -5.868989 v 1.664971 1.072200 -5.695913 v 1.510868 0.957577 -5.544997 v 1.391678 0.940769 -5.352942 v 1.170557 0.692380 -5.926214 v 1.027666 0.653090 -5.757548 v 0.869972 0.619560 -5.748698 v 1.295478 0.827279 -6.155195 v 1.403801 0.956111 -6.395917 v 1.981874 0.878914 -6.465936 v 1.802272 0.826665 -6.577847 v 1.615752 0.851027 -6.620514 v 2.128560 0.944598 -6.721747 v 1.907593 0.869058 -6.790360 v 1.708489 0.849226 -6.769275 v 2.238363 1.116521 -6.349912 v 2.094190 1.105140 -6.141595 v 2.237261 1.035889 -6.535950 v 2.075505 0.976585 -6.291769 v 1.727506 1.346013 -6.328338 v 1.936762 1.311864 -6.600124 v 1.576315 1.256378 -6.447272 v 1.741231 1.205721 -6.680005 v 1.483882 1.132384 -6.546886 v 1.595348 1.106596 -6.700094 v 2.143625 1.363027 -6.343407 v 2.083770 1.364678 -6.472173 v 1.997907 1.370713 -6.136065 v 1.880283 1.392692 -6.219747 v 2.220069 1.245977 -6.358671 v 2.223785 1.204368 -6.587201 v 2.097329 1.131385 -6.757537 v 1.644286 0.966614 -6.763514 v 1.867680 1.032451 -6.812611 v 0.883363 0.124343 -7.228944 v 0.646839 -0.024425 -7.259110 v 0.390212 -0.005959 -7.292361 v 1.070393 0.135169 -7.703971 v 0.802047 0.006235 -7.763816 v 0.511476 0.026061 -7.813804 v 1.163011 0.161832 -8.064369 v 0.918797 0.093289 -8.161346 v 0.636154 0.076768 -8.160398 v 0.269275 -0.049054 -6.787587 v 0.524823 -0.050661 -6.806285 v 0.744409 0.117607 -6.839493 v 0.827585 0.571806 -7.238711 v 1.016438 0.562215 -7.711038 v 1.115469 0.520019 -8.067395 v 0.573132 0.588769 -7.270417 v 0.731449 0.578986 -7.772986 v 0.865027 0.502425 -8.164807 v 0.338782 0.438496 -7.299040 v 0.460865 0.446711 -7.820236 v 0.590458 0.430524 -8.163703 v 0.208617 0.434283 -6.784674 v 0.437333 0.591011 -6.807528 v 0.678646 0.577267 -6.844694 v 0.947532 0.372788 -7.222228 v 0.797216 0.376391 -6.856188 v 0.734974 0.417910 -6.504792 v 1.142651 0.368565 -7.694477 v 1.195867 0.347815 -8.107895 v 0.272439 0.191555 -7.307303 v 0.163854 0.163934 -6.807784 v 0.050485 0.143298 -6.551455 v 0.390845 0.216656 -7.842326 v 0.587957 0.247899 -8.218260 v -0.187159 -0.021301 -8.489817 v -0.144520 -0.066015 -8.115219 v -0.135056 -0.086523 -7.519433 v -0.455856 -0.036286 -8.505733 v -0.424768 -0.127085 -8.081474 v -0.379623 -0.149656 -7.480232 v -0.721089 0.002465 -8.418228 v -0.711949 -0.032964 -8.033904 v -0.633023 -0.036474 -7.439595 v -0.083764 -0.101907 -6.888419 v -0.321252 -0.155635 -6.827525 v -0.570598 -0.013135 -6.792706 v -0.205536 0.346922 -8.488331 v -0.478068 0.389386 -8.503635 v -0.741261 0.375015 -8.416031 v -0.166164 0.372104 -8.112885 v -0.454556 0.470532 -8.077909 v -0.734413 0.413380 -8.030973 v -0.161420 0.377122 -7.515023 v -0.412007 0.496828 -7.474960 v -0.653762 0.440220 -7.436335 v -0.124968 0.400042 -6.878002 v -0.359615 0.536135 -6.818819 v -0.582637 0.502600 -6.791322 v -0.736234 0.212481 -7.423101 v -0.655151 0.259193 -6.812274 v -0.663333 0.364684 -6.389957 v -0.775997 0.191334 -8.463245 v -0.822719 0.196893 -8.024588 v -0.031942 0.130966 -6.924860 v -0.055396 0.134692 -7.532089 v -0.056604 0.146553 -8.134798 v -0.157928 0.161766 -8.546125 v -1.836226 1.016590 -7.410828 v -1.627684 0.872918 -7.538481 v -1.370280 0.758218 -7.595252 v -1.747767 0.932613 -7.142950 v -1.528535 0.732919 -7.246038 v -1.256016 0.658972 -7.340291 v -1.538345 0.794709 -6.746178 v -1.346968 0.594312 -6.836720 v -1.106538 0.540492 -6.926594 v -1.327304 0.638226 -6.296957 v -1.144801 0.423090 -6.386161 v -0.907648 0.349198 -6.500935 v -1.381548 1.162123 -6.749738 v -1.167106 1.131764 -6.834267 v -1.001718 0.954827 -6.919466 v -1.579033 1.276060 -7.151250 v -1.336962 1.223187 -7.246882 v -1.140912 1.040889 -7.333368 v -1.682336 1.295016 -7.423892 v -1.479018 1.212733 -7.544489 v -1.266431 1.072053 -7.592119 v -1.173291 1.003628 -6.309747 v -0.980917 0.984092 -6.395974 v -0.826961 0.810684 -6.501183 v -0.978037 0.704393 -6.955856 v -1.119137 0.806439 -7.374477 v -1.298471 0.903687 -7.643332 v -0.811802 0.542748 -6.562383 v -1.320080 0.864534 -6.271852 v -1.536038 1.021683 -6.715133 v -1.746360 1.149667 -7.118443 v -1.808232 1.181964 -7.439637 v 2.071132 1.255908 -6.105393 v 1.505985 0.975476 -6.611821 v 0.931009 0.299286 -8.285854 v -0.474965 0.178488 -8.633644 v -1.589683 1.061216 -7.631387 v 0.763920 0.520049 -6.078023

  1. 281 vertices
  2. 0 texture vertices
  3. 0 normals

usemtl hand f 2 4 1 f 5 4 2 f 3 5 2 f 5 6 4 f 1 10 9 f 1 7 10 f 7 11 10 f 7 8 11 f 10 12 9 f 12 10 13 f 10 14 13 f 10 11 14 f 12 17 9 f 12 15 17 f 18 15 16 f 15 18 17 f 9 2 1 f 9 17 2 f 18 2 17 f 2 18 3 f 19 4 6 f 7 4 19 f 8 7 19 f 7 1 4 f 20 22 12 f 23 22 20 f 21 23 20 f 23 24 22 f 16 26 25 f 16 15 26 f 15 22 26 f 15 12 22 f 25 28 27 f 25 26 28 f 22 28 26 f 28 22 24 f 30 31 29 f 32 31 30 f 6 32 30 f 32 33 31 f 5 32 6 f 32 5 34 f 5 35 34 f 5 3 35 f 34 33 32 f 33 34 36 f 35 36 34 f 36 35 37 f 39 40 38 f 31 40 39 f 29 31 39 f 31 33 40 f 42 43 41 f 40 43 42 f 38 40 42 f 40 33 43 f 45 46 44 f 46 45 47 f 38 47 45 f 47 38 42 f 46 49 48 f 46 47 49 f 47 41 49 f 47 42 41 f 44 52 45 f 44 50 52 f 50 53 52 f 50 51 53 f 52 38 45 f 38 52 39 f 52 29 39 f 52 53 29 f 36 55 33 f 55 36 56 f 37 56 36 f 56 37 54 f 56 24 55 f 24 56 28 f 27 56 54 f 56 27 28 f 33 57 43 f 33 55 57 f 55 58 57 f 55 24 58 f 57 41 43 f 41 57 59 f 58 59 57 f 59 58 60 f 62 64 61 f 64 62 65 f 63 65 62 f 65 63 66 f 65 21 64 f 21 65 23 f 66 23 65 f 23 66 24 f 66 58 24 f 58 66 67 f 63 67 66 f 67 63 68 f 67 60 58 f 60 67 69 f 68 69 67 f 69 68 70 f 61 72 71 f 61 64 72 f 64 73 72 f 64 21 73 f 71 75 74 f 71 72 75 f 72 76 75 f 72 73 76 f 53 77 29 f 77 53 78 f 51 78 53 f 78 51 79 f 78 80 77 f 80 78 81 f 79 81 78 f 81 79 82 f 83 77 80 f 77 83 85 f 83 86 85 f 83 84 86 f 85 29 77 f 29 85 30 f 86 30 85 f 30 86 6 f 73 87 76 f 87 73 88 f 21 88 73 f 88 21 20 f 88 89 87 f 89 88 90 f 20 90 88 f 90 20 12 f 90 91 89 f 91 90 92 f 90 13 92 f 90 12 13 f 91 94 93 f 91 92 94 f 92 14 94 f 92 13 14 f 95 98 97 f 95 96 98 f 8 98 96 f 98 8 19 f 97 86 84 f 97 98 86 f 19 86 98 f 86 19 6 f 59 49 41 f 49 59 99 f 59 69 99 f 59 60 69 f 99 48 49 f 48 99 100 f 99 70 100 f 99 69 70 f 8 101 11 f 8 96 101 f 96 102 101 f 96 95 102 f 101 14 11 f 14 101 94 f 101 93 94 f 101 102 93 f 103 107 106 f 103 104 107 f 105 107 104 f 107 105 108 f 107 109 106 f 109 107 110 f 108 110 107 f 110 108 111 f 63 113 68 f 63 112 113 f 112 104 113 f 112 105 104 f 68 114 70 f 68 113 114 f 113 103 114 f 113 104 103 f 115 118 117 f 115 116 118 f 105 118 116 f 118 105 112 f 117 62 61 f 117 118 62 f 112 62 118 f 62 112 63 f 120 121 119 f 121 120 122 f 111 122 120 f 122 111 108 f 122 115 121 f 115 122 116 f 108 116 122 f 116 108 105 f 123 127 126 f 123 124 127 f 124 128 127 f 124 125 128 f 126 130 129 f 126 127 130 f 127 131 130 f 127 128 131 f 44 133 132 f 44 46 133 f 48 133 46 f 133 48 134 f 132 126 129 f 132 133 126 f 134 126 133 f 126 134 123 f 135 138 137 f 135 136 138 f 136 130 138 f 136 129 130 f 137 140 139 f 137 138 140 f 138 131 140 f 138 130 131 f 51 142 141 f 51 50 142 f 50 132 142 f 50 44 132 f 141 136 135 f 141 142 136 f 142 129 136 f 142 132 129 f 109 144 106 f 109 143 144 f 125 144 143 f 144 125 124 f 106 145 103 f 106 144 145 f 124 145 144 f 145 124 123 f 100 134 48 f 134 100 146 f 70 146 100 f 146 70 114 f 146 123 134 f 123 146 145 f 114 145 146 f 145 114 103 f 135 148 141 f 135 147 148 f 147 117 148 f 147 115 117 f 141 149 51 f 141 148 149 f 148 61 149 f 148 117 61 f 115 150 121 f 115 147 150 f 135 150 147 f 150 135 137 f 121 151 119 f 121 150 151 f 137 151 150 f 151 137 139 f 120 152 111 f 152 120 153 f 119 153 120 f 153 119 154 f 152 156 155 f 152 153 156 f 153 157 156 f 153 154 157 f 158 161 160 f 158 159 161 f 159 110 161 f 159 109 110 f 160 152 155 f 160 161 152 f 161 111 152 f 161 110 111 f 162 140 131 f 140 162 164 f 162 165 164 f 162 163 165 f 164 139 140 f 139 164 166 f 164 167 166 f 164 165 167 f 168 171 170 f 168 169 171 f 163 171 169 f 171 163 162 f 171 125 170 f 125 171 128 f 162 128 171 f 128 162 131 f 172 169 168 f 169 172 173 f 158 173 172 f 173 158 160 f 169 174 163 f 169 173 174 f 160 174 173 f 174 160 155 f 157 176 156 f 157 175 176 f 167 176 175 f 176 167 165 f 176 155 156 f 155 176 174 f 176 163 174 f 176 165 163 f 177 181 180 f 177 178 181 f 178 182 181 f 178 179 182 f 181 183 180 f 183 181 184 f 181 185 184 f 181 182 185 f 186 75 76 f 75 186 187 f 179 187 186 f 187 179 178 f 187 74 75 f 74 187 188 f 178 188 187 f 188 178 177 f 189 193 192 f 189 190 193 f 191 193 190 f 193 191 194 f 192 196 195 f 192 193 196 f 193 197 196 f 193 194 197 f 81 198 80 f 198 81 199 f 82 199 81 f 199 82 200 f 199 195 198 f 195 199 192 f 200 192 199 f 192 200 189 f 200 201 189 f 201 200 202 f 200 203 202 f 200 82 203 f 202 177 201 f 177 202 188 f 202 74 188 f 202 203 74 f 177 204 201 f 177 180 204 f 183 204 180 f 204 183 205 f 204 189 201 f 189 204 190 f 204 191 190 f 204 205 191 f 195 207 198 f 195 206 207 f 179 207 206 f 207 179 186 f 198 208 80 f 198 207 208 f 186 208 207 f 208 186 76 f 206 182 179 f 182 206 209 f 206 196 209 f 206 195 196 f 209 185 182 f 185 209 210 f 209 197 210 f 209 196 197 f 211 215 214 f 211 212 215 f 213 215 212 f 215 213 216 f 215 217 214 f 217 215 218 f 216 218 215 f 218 216 219 f 220 216 213 f 216 220 221 f 76 221 220 f 221 76 87 f 221 219 216 f 219 221 222 f 87 222 221 f 222 87 89 f 223 227 226 f 223 224 227 f 225 227 224 f 227 225 228 f 227 229 226 f 229 227 230 f 228 230 227 f 230 228 231 f 230 232 229 f 232 230 233 f 231 233 230 f 233 231 234 f 233 80 232 f 80 233 83 f 233 84 83 f 233 234 84 f 222 235 219 f 235 222 236 f 222 237 236 f 222 89 237 f 236 231 235 f 231 236 234 f 237 234 236 f 234 237 84 f 217 239 238 f 217 218 239 f 219 239 218 f 239 219 235 f 239 225 238 f 225 239 228 f 239 231 228 f 239 235 231 f 220 208 76 f 208 220 240 f 213 240 220 f 240 213 241 f 208 232 80 f 208 240 232 f 240 229 232 f 240 241 229 f 241 226 229 f 226 241 242 f 241 212 242 f 241 213 212 f 242 223 226 f 223 242 243 f 242 211 243 f 242 212 211 f 244 248 247 f 244 245 248 f 246 248 245 f 248 246 249 f 248 250 247 f 250 248 251 f 249 251 248 f 251 249 252 f 250 254 253 f 250 251 254 f 252 254 251 f 254 252 255 f 253 91 93 f 253 254 91 f 254 89 91 f 254 255 89 f 256 260 259 f 256 257 260 f 258 260 257 f 260 258 261 f 260 262 259 f 262 260 263 f 260 264 263 f 260 261 264 f 97 265 95 f 265 97 266 f 84 266 97 f 266 84 267 f 265 257 256 f 265 266 257 f 267 257 266 f 257 267 258 f 249 268 252 f 268 249 269 f 249 270 269 f 249 246 270 f 269 258 268 f 258 269 261 f 269 264 261 f 269 270 264 f 255 237 89 f 237 255 271 f 252 271 255 f 271 252 268 f 271 84 237 f 84 271 267 f 268 267 271 f 267 268 258 f 102 253 93 f 253 102 272 f 102 265 272 f 102 95 265 f 272 250 253 f 250 272 273 f 272 256 273 f 272 265 256 f 259 273 256 f 273 259 274 f 262 274 259 f 274 262 275 f 273 247 250 f 273 274 247 f 274 244 247 f 274 275 244 f 172 159 158 f 159 172 276 f 172 170 276 f 172 168 170 f 276 109 159 f 109 276 143 f 170 143 276 f 143 170 125 f 151 154 119 f 154 151 277 f 151 166 277 f 151 139 166 f 154 175 157 f 154 277 175 f 277 167 175 f 277 166 167 f 197 278 210 f 197 194 278 f 191 278 194 f 278 191 205 f 278 185 210 f 185 278 184 f 278 183 184 f 278 205 183 f 223 279 224 f 223 243 279 f 211 279 243 f 279 211 214 f 279 225 224 f 225 279 238 f 279 217 238 f 279 214 217 f 262 280 275 f 262 263 280 f 264 280 263 f 280 264 270 f 280 244 275 f 244 280 245 f 270 245 280 f 245 270 246 f 74 281 71 f 74 203 281 f 82 281 203 f 281 82 79 f 71 149 61 f 71 281 149 f 79 149 281 f 149 79 51

  1. 552 elements
  • /

//File: hand2.obj /*

  1. Mon Jun 02 17:09:49 1997

g hand2 v -0.545629 0.226597 -3.972744 v -0.215053 0.028788 -3.704237 v -0.048631 -0.141870 -1.731539 v -0.486661 0.360120 -4.035744 v -0.168475 0.089529 -3.756256 v -0.340613 0.471505 -4.270064 v -0.635471 0.403031 -4.188368 v -0.756139 0.537011 -4.495984 v -0.519863 0.020651 -3.964786 v -0.700655 0.190824 -4.211964 v -0.861473 0.372102 -4.526962 v -0.356499 -0.174538 -4.199869 v -0.714045 0.044261 -4.445632 v -0.890476 0.203518 -4.607591 v -0.170313 -0.192685 -3.756315 v -0.069766 -0.312358 -1.638721 v -0.232940 -0.103910 -3.758020 v -0.115092 -0.245076 -1.715384 v -0.586581 0.541254 -4.390105 v -0.035952 -0.274007 -4.418982 v 0.255124 -0.249237 -4.776807 v 0.018833 -0.240104 -4.027362 v 0.284973 -0.207728 -4.316310 v 0.434752 -0.000032 -4.022241 v 0.022704 -0.329702 -1.621020 v -0.055377 -0.221593 -3.718934 v 0.105371 -0.295391 -1.615597 v 0.046896 -0.174033 -3.708722 v 0.033445 0.525248 -4.572588 v -0.146022 0.491685 -4.378734 v -0.008484 0.509017 -4.183765 v -0.109786 0.450335 -4.040698 v 0.106167 0.452120 -3.961211 v -0.081537 0.087205 -3.782939 v -0.004783 -0.118520 -1.734107 v 0.008732 0.041375 -3.708363 v 0.080374 -0.144013 -1.651651 v 0.267743 0.688582 -4.403843 v 0.134602 0.595547 -4.385927 v 0.155445 0.603098 -4.172839 v 0.510348 0.750695 -4.322186 v 0.351763 0.725704 -4.323452 v 0.293357 0.616488 -4.126201 v 0.644985 0.911535 -5.278749 v 0.476753 0.808807 -4.843080 v 0.729327 1.001220 -5.209341 v 0.576282 0.887766 -4.779078 v 0.861206 1.041806 -5.155231 v 0.720826 0.920527 -4.727794 v 0.591358 0.800004 -5.365947 v 0.601106 0.662395 -5.579942 v 0.385222 0.705498 -4.899085 v 0.327338 0.605102 -5.113508 v 0.123562 -0.217362 -1.626587 v 0.301415 0.221510 -3.856624 v 0.057648 -0.069121 -3.679395 v 0.481419 0.465636 -4.058800 v 0.733329 0.364516 -4.192796 v 0.715407 0.668961 -4.293678 v 0.891503 0.576285 -4.325380 v 0.925616 0.325221 -5.607038 v 1.087404 0.428685 -5.355153 v 1.192964 0.581656 -5.247297 v 0.655301 -0.002104 -5.205223 v 0.826001 0.093037 -4.822896 v 0.936937 0.282795 -4.650935 v 1.071822 0.521897 -4.652002 v 1.253768 0.746632 -5.184807 v 1.087957 0.735338 -4.683784 v 1.216838 0.899384 -5.149589 v 0.711147 0.230918 -6.030735 v 0.476647 -0.030016 -5.767413 v 0.142223 -0.215576 -5.512595 v 0.589280 0.158661 -6.504986 v 0.382367 -0.041679 -6.374435 v 0.052545 -0.020831 -6.416378 v 0.004866 0.539221 -5.338164 v 0.294897 0.599163 -5.651150 v 0.547241 0.615171 -5.966590 v -0.001080 0.527218 -6.226285 v 0.274900 0.607360 -6.287489 v 0.507029 0.599694 -6.459079 v -0.304989 0.605648 -6.026434 v -0.588412 0.775369 -6.061018 v -0.235417 0.550011 -5.181865 v -0.450388 0.614566 -5.143874 v -0.283040 -0.067515 -6.255307 v -0.179973 -0.263960 -5.306118 v -0.665295 0.178195 -6.225147 v -0.506975 -0.143513 -5.176296 v -0.975091 0.334957 -5.897993 v -0.814140 0.069075 -5.111338 v -1.151849 0.543036 -5.754441 v -1.001447 0.285489 -5.111672 v -0.965973 0.855410 -5.679462 v -0.853225 0.658026 -5.081767 v -0.768725 0.885422 -5.758699 v -0.661677 0.680318 -5.098948 v 0.926772 0.868255 -4.695576 v 1.052723 1.006416 -5.135924 v -0.991553 0.504328 -5.086818 v -1.125149 0.731518 -5.686989 v 1.303689 1.033657 -5.689645 v 1.349170 0.926230 -5.744081 v 1.316995 0.810848 -5.819848 v 1.335402 1.170071 -5.865595 v 1.362673 1.055005 -5.926610 v 1.324385 0.938256 -6.020778 v 1.410471 1.327249 -6.076220 v 1.420585 1.201262 -6.166119 v 1.368728 1.073079 -6.289456 v 1.275447 0.732420 -5.607525 v 1.315548 0.861839 -5.536830 v 1.265631 0.978431 -5.481887 v 1.109960 0.647515 -5.964428 v 1.236318 0.701507 -5.903873 v 1.045745 0.541486 -5.756546 v 1.185145 0.607547 -5.683672 v 1.126042 0.911004 -6.484125 v 1.260541 0.959921 -6.409129 v 1.116033 0.789199 -6.215408 v 1.238526 0.835123 -6.132965 v 1.008562 1.150313 -5.667244 v 1.106643 1.305370 -5.848235 v 1.233100 1.484675 -6.059801 v 0.888559 1.106689 -5.702088 v 0.985226 1.254602 -5.879530 v 1.105698 1.433834 -6.098895 v 0.812199 1.014149 -5.765767 v 0.891119 1.151850 -5.946655 v 0.987588 1.322413 -6.173646 v 0.736157 0.957482 -5.567209 v 0.810319 1.047137 -5.499653 v 0.932046 1.090406 -5.456793 v 0.822744 0.790022 -5.929116 v 0.782579 0.903754 -5.850531 v 0.867396 0.936043 -6.161350 v 0.843523 1.042929 -6.053780 v 0.911772 1.081739 -6.408180 v 0.912443 1.201594 -6.290159 v 0.737027 0.724935 -5.731150 v 0.703318 0.847734 -5.646091 v 1.341226 1.437246 -6.046185 v 1.236369 1.267617 -5.841922 v 1.167446 1.119645 -5.663458 v 1.107867 1.064412 -5.452231 v 0.948806 0.689125 -5.971970 v 0.872849 0.609231 -5.783209 v 0.781035 0.526092 -5.762100 v 0.973032 0.836092 -6.223403 v 0.994805 0.967427 -6.481477 v 1.495197 1.158527 -6.645423 v 1.354724 1.014236 -6.722411 v 1.195778 0.940855 -6.732456 v 1.565488 1.249424 -6.923759 v 1.406339 1.071370 -6.949717 v 1.265445 0.960990 -6.892314 v 1.638914 1.485047 -6.580676 v 1.546930 1.431636 -6.350698 v 1.642671 1.399706 -6.762676 v 1.557898 1.303849 -6.492972 v 1.099399 1.460928 -6.484489 v 1.242754 1.502103 -6.790419 v 0.999544 1.301628 -6.571692 v 1.118751 1.308856 -6.829766 v 0.979609 1.139385 -6.646541 v 1.060424 1.149347 -6.815580 v 1.455248 1.654590 -6.566786 v 1.372638 1.624035 -6.688066 v 1.365156 1.609915 -6.335397 v 1.234614 1.575107 -6.401853 v 1.565822 1.588197 -6.591331 v 1.547752 1.535880 -6.818796 v 1.445347 1.397323 -6.963596 v 1.158417 1.039164 -6.880589 v 1.288292 1.198123 -6.973975 v 0.664087 0.148083 -7.294943 v 0.435748 0.025040 -7.292446 v 0.212877 0.160088 -7.281471 v 0.785373 0.173634 -7.783887 v 0.518575 0.067897 -7.800985 v 0.271345 0.242325 -7.758057 v 0.826827 0.208746 -8.147941 v 0.572939 0.148727 -8.206624 v 0.325508 0.231584 -8.119010 v 0.164075 0.075407 -6.818721 v 0.380953 -0.013843 -6.839242 v 0.580180 0.132467 -6.892866 v 0.608535 0.593486 -7.282530 v 0.726502 0.591761 -7.775616 v 0.772896 0.554086 -8.142780 v 0.360286 0.622050 -7.265000 v 0.437249 0.612740 -7.792085 v 0.509853 0.535394 -8.204787 v 0.160224 0.549868 -7.218602 v 0.209808 0.590107 -7.721076 v 0.267898 0.534017 -8.108936 v 0.111090 0.516500 -6.720913 v 0.298230 0.611278 -6.790854 v 0.518079 0.589180 -6.874673 v 0.726888 0.393165 -7.292970 v 0.628159 0.389210 -6.913399 v 0.624790 0.421710 -6.550771 v 0.855781 0.401525 -7.780616 v 0.850483 0.389631 -8.193182 v 0.126257 0.432018 -7.223687 v 0.081097 0.333542 -6.781929 v 0.024773 0.331692 -6.543201 v 0.179967 0.513803 -7.691848 v 0.270466 0.398086 -8.149796 v -0.085803 2.071088 -7.365792 v -0.089283 1.657050 -7.409026 v -0.132752 1.024134 -7.355868 v -0.339231 2.178852 -7.313980 v -0.362585 1.717826 -7.403921 v -0.376816 1.020220 -7.374946 v -0.609086 2.098261 -7.268658 v -0.644951 1.683101 -7.308946 v -0.620699 1.049622 -7.252518 v -0.115696 0.389618 -6.975528 v -0.348229 0.364394 -6.960135 v -0.589678 0.477314 -6.850625 v -0.063362 2.126922 -6.994926 v -0.317776 2.207434 -6.893541 v -0.592443 2.122036 -6.922650 v -0.060384 1.753711 -6.967503 v -0.330655 1.784850 -6.821116 v -0.622382 1.744780 -6.913632 v -0.111831 1.216582 -6.951138 v -0.351669 1.253255 -6.832911 v -0.599234 1.235825 -6.874247 v -0.113630 0.786347 -6.638087 v -0.343041 0.846074 -6.551879 v -0.571143 0.863954 -6.597034 v -0.702952 1.143454 -7.043127 v -0.659979 0.708124 -6.719869 v -0.688492 0.602267 -6.399982 v -0.640513 2.158446 -7.091597 v -0.733751 1.708568 -7.108687 v -0.042639 0.608451 -6.846946 v -0.033981 1.117844 -7.181334 v 0.014576 1.681971 -7.232140 v -0.034099 2.140646 -7.197904 v -1.427884 2.125531 -6.104109 v -1.232856 2.217431 -6.261067 v -1.030471 2.172613 -6.454438 v -1.433002 1.846260 -6.128913 v -1.256178 1.899456 -6.333560 v -1.021006 1.878065 -6.513752 v -1.382181 1.396092 -6.219269 v -1.241525 1.399828 -6.428739 v -1.025330 1.377688 -6.574033 v -1.304705 0.946481 -6.184714 v -1.170819 0.841650 -6.394479 v -0.946587 0.786927 -6.537124 v -1.133362 1.480745 -5.995321 v -0.908216 1.491027 -6.055746 v -0.781984 1.482366 -6.234836 v -1.166789 1.889461 -5.900780 v -0.912111 1.929120 -5.973505 v -0.773154 1.928164 -6.197147 v -1.192128 2.159473 -5.918907 v -0.979939 2.235226 -6.018824 v -0.820842 2.203268 -6.203417 v -1.073035 1.127979 -6.002315 v -0.883316 1.138491 -6.095742 v -0.766101 1.081268 -6.289536 v -0.842475 1.437964 -6.469625 v -0.835837 1.902370 -6.431089 v -0.901630 2.225091 -6.358479 v -0.809658 0.951527 -6.487935 v -1.248762 1.053319 -6.037439 v -1.326974 1.438433 -6.057952 v -1.378537 1.859137 -5.972835 v -1.347264 2.171041 -5.994931 v 1.476370 1.548335 -6.314360 v 1.060616 1.003273 -6.708851 v 0.566455 0.353316 -8.324208 v -0.326088 2.309241 -7.118046 v -1.118212 2.311149 -6.146525 v 0.706268 0.472086 -6.106736

  1. 281 vertices
  2. 0 texture vertices
  3. 0 normals

usemtl hand f 2 4 1 f 5 4 2 f 3 5 2 f 5 6 4 f 1 10 9 f 1 7 10 f 7 11 10 f 7 8 11 f 10 12 9 f 12 10 13 f 10 14 13 f 10 11 14 f 12 17 9 f 12 15 17 f 18 15 16 f 15 18 17 f 9 2 1 f 9 17 2 f 18 2 17 f 2 18 3 f 19 4 6 f 7 4 19 f 8 7 19 f 7 1 4 f 20 22 12 f 23 22 20 f 21 23 20 f 23 24 22 f 16 26 25 f 16 15 26 f 15 22 26 f 15 12 22 f 25 28 27 f 25 26 28 f 22 28 26 f 28 22 24 f 30 31 29 f 32 31 30 f 6 32 30 f 32 33 31 f 5 32 6 f 32 5 34 f 5 35 34 f 5 3 35 f 34 33 32 f 33 34 36 f 35 36 34 f 36 35 37 f 39 40 38 f 31 40 39 f 29 31 39 f 31 33 40 f 42 43 41 f 40 43 42 f 38 40 42 f 40 33 43 f 45 46 44 f 46 45 47 f 38 47 45 f 47 38 42 f 46 49 48 f 46 47 49 f 47 41 49 f 47 42 41 f 44 52 45 f 44 50 52 f 50 53 52 f 50 51 53 f 52 38 45 f 38 52 39 f 52 29 39 f 52 53 29 f 36 55 33 f 55 36 56 f 37 56 36 f 56 37 54 f 56 24 55 f 24 56 28 f 27 56 54 f 56 27 28 f 33 57 43 f 33 55 57 f 55 58 57 f 55 24 58 f 57 41 43 f 41 57 59 f 58 59 57 f 59 58 60 f 62 64 61 f 64 62 65 f 63 65 62 f 65 63 66 f 65 21 64 f 21 65 23 f 66 23 65 f 23 66 24 f 66 58 24 f 58 66 67 f 63 67 66 f 67 63 68 f 67 60 58 f 60 67 69 f 68 69 67 f 69 68 70 f 61 72 71 f 61 64 72 f 64 73 72 f 64 21 73 f 71 75 74 f 71 72 75 f 72 76 75 f 72 73 76 f 53 77 29 f 77 53 78 f 51 78 53 f 78 51 79 f 78 80 77 f 80 78 81 f 79 81 78 f 81 79 82 f 83 77 80 f 77 83 85 f 83 86 85 f 83 84 86 f 85 29 77 f 29 85 30 f 86 30 85 f 30 86 6 f 73 87 76 f 87 73 88 f 21 88 73 f 88 21 20 f 88 89 87 f 89 88 90 f 20 90 88 f 90 20 12 f 90 91 89 f 91 90 92 f 90 13 92 f 90 12 13 f 91 94 93 f 91 92 94 f 92 14 94 f 92 13 14 f 95 98 97 f 95 96 98 f 8 98 96 f 98 8 19 f 97 86 84 f 97 98 86 f 19 86 98 f 86 19 6 f 59 49 41 f 49 59 99 f 59 69 99 f 59 60 69 f 99 48 49 f 48 99 100 f 99 70 100 f 99 69 70 f 8 101 11 f 8 96 101 f 96 102 101 f 96 95 102 f 101 14 11 f 14 101 94 f 101 93 94 f 101 102 93 f 103 107 106 f 103 104 107 f 105 107 104 f 107 105 108 f 107 109 106 f 109 107 110 f 108 110 107 f 110 108 111 f 63 113 68 f 63 112 113 f 112 104 113 f 112 105 104 f 68 114 70 f 68 113 114 f 113 103 114 f 113 104 103 f 115 118 117 f 115 116 118 f 105 118 116 f 118 105 112 f 117 62 61 f 117 118 62 f 112 62 118 f 62 112 63 f 120 121 119 f 121 120 122 f 111 122 120 f 122 111 108 f 122 115 121 f 115 122 116 f 108 116 122 f 116 108 105 f 123 127 126 f 123 124 127 f 124 128 127 f 124 125 128 f 126 130 129 f 126 127 130 f 127 131 130 f 127 128 131 f 44 133 132 f 44 46 133 f 48 133 46 f 133 48 134 f 132 126 129 f 132 133 126 f 134 126 133 f 126 134 123 f 135 138 137 f 135 136 138 f 136 130 138 f 136 129 130 f 137 140 139 f 137 138 140 f 138 131 140 f 138 130 131 f 51 142 141 f 51 50 142 f 50 132 142 f 50 44 132 f 141 136 135 f 141 142 136 f 142 129 136 f 142 132 129 f 109 144 106 f 109 143 144 f 125 144 143 f 144 125 124 f 106 145 103 f 106 144 145 f 124 145 144 f 145 124 123 f 100 134 48 f 134 100 146 f 70 146 100 f 146 70 114 f 146 123 134 f 123 146 145 f 114 145 146 f 145 114 103 f 135 148 141 f 135 147 148 f 147 117 148 f 147 115 117 f 141 149 51 f 141 148 149 f 148 61 149 f 148 117 61 f 115 150 121 f 115 147 150 f 135 150 147 f 150 135 137 f 121 151 119 f 121 150 151 f 137 151 150 f 151 137 139 f 120 152 111 f 152 120 153 f 119 153 120 f 153 119 154 f 152 156 155 f 152 153 156 f 153 157 156 f 153 154 157 f 158 161 160 f 158 159 161 f 159 110 161 f 159 109 110 f 160 152 155 f 160 161 152 f 161 111 152 f 161 110 111 f 162 140 131 f 140 162 164 f 162 165 164 f 162 163 165 f 164 139 140 f 139 164 166 f 164 167 166 f 164 165 167 f 168 171 170 f 168 169 171 f 163 171 169 f 171 163 162 f 171 125 170 f 125 171 128 f 162 128 171 f 128 162 131 f 172 169 168 f 169 172 173 f 158 173 172 f 173 158 160 f 169 174 163 f 169 173 174 f 160 174 173 f 174 160 155 f 157 176 156 f 157 175 176 f 167 176 175 f 176 167 165 f 176 155 156 f 155 176 174 f 176 163 174 f 176 165 163 f 177 181 180 f 177 178 181 f 178 182 181 f 178 179 182 f 181 183 180 f 183 181 184 f 181 185 184 f 181 182 185 f 186 75 76 f 75 186 187 f 179 187 186 f 187 179 178 f 187 74 75 f 74 187 188 f 178 188 187 f 188 178 177 f 189 193 192 f 189 190 193 f 191 193 190 f 193 191 194 f 192 196 195 f 192 193 196 f 193 197 196 f 193 194 197 f 81 198 80 f 198 81 199 f 82 199 81 f 199 82 200 f 199 195 198 f 195 199 192 f 200 192 199 f 192 200 189 f 200 201 189 f 201 200 202 f 200 203 202 f 200 82 203 f 202 177 201 f 177 202 188 f 202 74 188 f 202 203 74 f 177 204 201 f 177 180 204 f 183 204 180 f 204 183 205 f 204 189 201 f 189 204 190 f 204 191 190 f 204 205 191 f 195 207 198 f 195 206 207 f 179 207 206 f 207 179 186 f 198 208 80 f 198 207 208 f 186 208 207 f 208 186 76 f 206 182 179 f 182 206 209 f 206 196 209 f 206 195 196 f 209 185 182 f 185 209 210 f 209 197 210 f 209 196 197 f 211 215 214 f 211 212 215 f 213 215 212 f 215 213 216 f 215 217 214 f 217 215 218 f 216 218 215 f 218 216 219 f 220 216 213 f 216 220 221 f 76 221 220 f 221 76 87 f 221 219 216 f 219 221 222 f 87 222 221 f 222 87 89 f 223 227 226 f 223 224 227 f 225 227 224 f 227 225 228 f 227 229 226 f 229 227 230 f 228 230 227 f 230 228 231 f 230 232 229 f 232 230 233 f 231 233 230 f 233 231 234 f 233 80 232 f 80 233 83 f 233 84 83 f 233 234 84 f 222 235 219 f 235 222 236 f 222 237 236 f 222 89 237 f 236 231 235 f 231 236 234 f 237 234 236 f 234 237 84 f 217 239 238 f 217 218 239 f 219 239 218 f 239 219 235 f 239 225 238 f 225 239 228 f 239 231 228 f 239 235 231 f 220 208 76 f 208 220 240 f 213 240 220 f 240 213 241 f 208 232 80 f 208 240 232 f 240 229 232 f 240 241 229 f 241 226 229 f 226 241 242 f 241 212 242 f 241 213 212 f 242 223 226 f 223 242 243 f 242 211 243 f 242 212 211 f 244 248 247 f 244 245 248 f 246 248 245 f 248 246 249 f 248 250 247 f 250 248 251 f 249 251 248 f 251 249 252 f 250 254 253 f 250 251 254 f 252 254 251 f 254 252 255 f 253 91 93 f 253 254 91 f 254 89 91 f 254 255 89 f 256 260 259 f 256 257 260 f 258 260 257 f 260 258 261 f 260 262 259 f 262 260 263 f 260 264 263 f 260 261 264 f 97 265 95 f 265 97 266 f 84 266 97 f 266 84 267 f 265 257 256 f 265 266 257 f 267 257 266 f 257 267 258 f 249 268 252 f 268 249 269 f 249 270 269 f 249 246 270 f 269 258 268 f 258 269 261 f 269 264 261 f 269 270 264 f 255 237 89 f 237 255 271 f 252 271 255 f 271 252 268 f 271 84 237 f 84 271 267 f 268 267 271 f 267 268 258 f 102 253 93 f 253 102 272 f 102 265 272 f 102 95 265 f 272 250 253 f 250 272 273 f 272 256 273 f 272 265 256 f 259 273 256 f 273 259 274 f 262 274 259 f 274 262 275 f 273 247 250 f 273 274 247 f 274 244 247 f 274 275 244 f 172 159 158 f 159 172 276 f 172 170 276 f 172 168 170 f 276 109 159 f 109 276 143 f 170 143 276 f 143 170 125 f 151 154 119 f 154 151 277 f 151 166 277 f 151 139 166 f 154 175 157 f 154 277 175 f 277 167 175 f 277 166 167 f 197 278 210 f 197 194 278 f 191 278 194 f 278 191 205 f 278 185 210 f 185 278 184 f 278 183 184 f 278 205 183 f 223 279 224 f 223 243 279 f 211 279 243 f 279 211 214 f 279 225 224 f 225 279 238 f 279 217 238 f 279 214 217 f 262 280 275 f 262 263 280 f 264 280 263 f 280 264 270 f 280 244 275 f 244 280 245 f 270 245 280 f 245 270 246 f 74 281 71 f 74 203 281 f 82 281 203 f 281 82 79 f 71 149 61 f 71 281 149 f 79 149 281 f 149 79 51

  1. 552 elements
  • /

//File: hand3.obj /*

  1. Mon Jun 02 17:10:02 1997

g hand3 v -0.532397 0.197223 -3.999972 v -0.214601 0.028608 -3.704992 v -0.062767 -0.039672 -1.969593 v -0.474970 0.318713 -4.067389 v -0.168129 0.089251 -3.756891 v -0.328587 0.420355 -4.296443 v -0.623073 0.363357 -4.216684 v -0.746171 0.497060 -4.524076 v -0.506368 0.006295 -3.982003 v -0.689049 0.168417 -4.231982 v -0.853662 0.351475 -4.548802 v -0.344509 -0.179734 -4.206146 v -0.709169 0.037344 -4.456913 v -0.884746 0.194925 -4.627260 v -0.168024 -0.191951 -3.757912 v -0.076841 -0.196481 -1.877360 v -0.231457 -0.103955 -3.759368 v -0.123436 -0.138285 -1.951048 v -0.575776 0.499057 -4.413718 v -0.022556 -0.274054 -4.419171 v 0.295391 -0.244860 -4.781412 v 0.027764 -0.237028 -4.026483 v 0.328292 -0.191608 -4.297441 v 0.452126 0.065151 -3.999771 v 0.014266 -0.206977 -1.861471 v -0.053052 -0.219763 -3.720458 v 0.093672 -0.170271 -1.858756 v 0.048687 -0.171678 -3.710009 v 0.050155 0.444476 -4.604692 v -0.133492 0.423989 -4.410464 v -0.027107 0.434472 -4.242275 v -0.117598 0.396084 -4.085021 v 0.065233 0.421440 -4.017992 v -0.081428 0.087141 -3.783137 v -0.020959 -0.015459 -1.973519 v 0.008804 0.041460 -3.708582 v 0.062893 -0.032292 -1.896764 v 0.225177 0.615409 -4.482480 v 0.113530 0.511149 -4.450598 v 0.102865 0.542478 -4.253375 v 0.431656 0.735739 -4.416512 v 0.288424 0.675882 -4.413925 v 0.218974 0.589731 -4.211629 v 0.541405 0.777453 -5.314148 v 0.432074 0.710021 -4.892318 v 0.593949 0.890727 -5.268293 v 0.501790 0.814034 -4.847951 v 0.700343 0.972337 -5.234181 v 0.623032 0.889368 -4.811626 v 0.521872 0.654464 -5.378404 v 0.555062 0.525950 -5.571719 v 0.375075 0.594255 -4.928543 v 0.345045 0.495994 -5.115907 v 0.108176 -0.097133 -1.871658 v 0.273705 0.252739 -3.878058 v 0.058055 -0.068344 -3.680041 v 0.405284 0.512264 -4.112417 v 0.687825 0.464139 -4.216795 v 0.632930 0.719769 -4.375288 v 0.825419 0.677113 -4.390901 v 0.917800 0.280915 -5.602854 v 1.056579 0.438767 -5.371966 v 1.116715 0.631123 -5.302998 v 0.705199 0.003471 -5.203117 v 0.907904 0.141760 -4.788020 v 0.962510 0.376613 -4.635034 v 1.041596 0.636992 -4.691114 v 1.130266 0.811997 -5.270994 v 1.005013 0.831826 -4.762492 v 1.055534 0.946727 -5.251543 v 0.677585 0.233496 -6.061008 v 0.460633 -0.018720 -5.787735 v 0.144938 -0.190839 -5.542907 v 0.494372 0.173628 -6.534559 v 0.317081 -0.008497 -6.384122 v 0.027201 0.131783 -6.428380 v 0.013685 0.508910 -5.331713 v 0.293216 0.555930 -5.655271 v 0.510499 0.560260 -5.972243 v -0.013202 0.565924 -6.175734 v 0.224494 0.612542 -6.271984 v 0.426059 0.599110 -6.464377 v -0.306255 0.646060 -5.996577 v -0.569808 0.913747 -5.981158 v -0.228316 0.516391 -5.181461 v -0.445620 0.586733 -5.146332 v -0.293245 0.113327 -6.323775 v -0.173597 -0.243629 -5.356423 v -0.670974 0.376359 -6.246881 v -0.505876 -0.129238 -5.220592 v -0.981059 0.486591 -5.904088 v -0.816316 0.081391 -5.139109 v -1.148463 0.669179 -5.736072 v -1.003358 0.292548 -5.142035 v -0.951535 0.915719 -5.633423 v -0.848045 0.626223 -5.094282 v -0.743315 0.948671 -5.677959 v -0.655824 0.645151 -5.103795 v 0.822461 0.905362 -4.784215 v 0.878885 0.998810 -5.230596 v -0.989810 0.492494 -5.109306 v -1.116492 0.823014 -5.656571 v 0.996042 1.008486 -5.820419 v 1.064506 0.912915 -5.870014 v 1.060480 0.782157 -5.923663 v 0.953680 1.113737 -6.014114 v 1.005018 1.004616 -6.065710 v 0.992276 0.867260 -6.135736 v 0.944026 1.244268 -6.251624 v 0.973965 1.115774 -6.327374 v 0.945827 0.958451 -6.421946 v 1.083427 0.733990 -5.698505 v 1.090716 0.878610 -5.652200 v 1.016854 0.980850 -5.602205 v 0.904979 0.542860 -6.003450 v 1.010214 0.640802 -5.976042 v 0.918015 0.464134 -5.777233 v 1.030665 0.577144 -5.740035 v 0.758712 0.703562 -6.541620 v 0.866703 0.798472 -6.502394 v 0.825719 0.632441 -6.264884 v 0.930940 0.724822 -6.214890 v 0.693610 1.030609 -5.753376 v 0.707614 1.171851 -5.966817 v 0.745009 1.336440 -6.216925 v 0.595931 0.948287 -5.758795 v 0.607525 1.083062 -5.967039 v 0.635682 1.245807 -6.223903 v 0.548429 0.829721 -5.795010 v 0.543563 0.948272 -6.001235 v 0.548405 1.095687 -6.260015 v 0.548777 0.793549 -5.588580 v 0.593876 0.906330 -5.546043 v 0.689842 0.988075 -5.529473 v 0.608749 0.600589 -5.930038 v 0.547295 0.706322 -5.859049 v 0.567538 0.708497 -6.180083 v 0.523106 0.816241 -6.083089 v 0.535313 0.817538 -6.443928 v 0.506392 0.943775 -6.343649 v 0.600681 0.560351 -5.721073 v 0.545933 0.674730 -5.647308 v 0.856788 1.328405 -6.220259 v 0.836996 1.177698 -5.982326 v 0.846715 1.051347 -5.777648 v 0.851110 1.017751 -5.553206 v 0.745225 0.534151 -5.983995 v 0.739831 0.476319 -5.779583 v 0.715754 0.412378 -5.751285 v 0.683826 0.635181 -6.249702 v 0.633316 0.723667 -6.518804 v 0.980715 1.013307 -6.803527 v 0.892386 0.823377 -6.831568 v 0.786718 0.714033 -6.798828 v 0.975463 1.069959 -7.098132 v 0.890573 0.852994 -7.068334 v 0.825719 0.727882 -6.968780 v 1.025155 1.371318 -6.805808 v 0.995242 1.333836 -6.557353 v 1.022430 1.262102 -6.975050 v 1.017056 1.195056 -6.684767 v 0.555587 1.202589 -6.599424 v 0.612038 1.229948 -6.932652 v 0.508225 1.012148 -6.644658 v 0.562058 1.006498 -6.921506 v 0.546766 0.850772 -6.693409 v 0.585298 0.851819 -6.874451 v 0.808246 1.473531 -6.773156 v 0.714197 1.400582 -6.872624 v 0.784961 1.443287 -6.523914 v 0.661185 1.361980 -6.558956 v 0.923633 1.442370 -6.812841 v 0.880870 1.349604 -7.026019 v 0.806732 1.163577 -7.130162 v 0.703304 0.769882 -6.944597 v 0.730493 0.929054 -7.083601 v 0.467013 0.166173 -7.322286 v 0.252376 0.062331 -7.273434 v 0.071629 0.273589 -7.155980 v 0.529329 0.193273 -7.810286 v 0.270539 0.096977 -7.776154 v 0.075855 0.318280 -7.578300 v 0.525577 0.226801 -8.169828 v 0.268313 0.167598 -8.189743 v 0.062406 0.262263 -7.985266 v 0.085250 0.215999 -6.753068 v 0.257265 0.029724 -6.830193 v 0.432281 0.147121 -6.919346 v 0.412813 0.603853 -7.296127 v 0.466553 0.601779 -7.797064 v 0.466023 0.565097 -8.166368 v 0.174599 0.635304 -7.236838 v 0.178594 0.622429 -7.773725 v 0.196329 0.546003 -8.196803 v 0.010991 0.597067 -7.106261 v -0.002380 0.607430 -7.576752 v -0.009555 0.537996 -8.004534 v 0.032977 0.584260 -6.637498 v 0.178619 0.629919 -6.764370 v 0.375331 0.599437 -6.884651 v 0.527273 0.406770 -7.327760 v 0.475094 0.400761 -6.944777 v 0.524815 0.430983 -6.577858 v 0.596379 0.415394 -7.817393 v 0.540282 0.403398 -8.220389 v 0.014701 0.567519 -7.027500 v 0.022146 0.486002 -6.671004 v 0.012141 0.498590 -6.467365 v 0.012762 0.578347 -7.426854 v 0.000619 0.410973 -8.007980 v 0.092196 1.869408 -5.545787 v 0.047882 1.788186 -5.963855 v -0.060104 1.571916 -6.553101 v -0.143875 1.937950 -5.383014 v -0.207255 1.899992 -5.860848 v -0.295062 1.638036 -6.546325 v -0.421009 1.885218 -5.447442 v -0.494485 1.814856 -5.875438 v -0.539028 1.586470 -6.471877 v -0.106805 0.842813 -6.743448 v -0.330308 0.861681 -6.742823 v -0.563357 0.915028 -6.614289 v 0.092672 1.563475 -5.409472 v -0.152484 1.549881 -5.266574 v -0.427491 1.564068 -5.366186 v 0.055291 1.459964 -5.769153 v -0.213200 1.392345 -5.673015 v -0.489819 1.484210 -5.757663 v -0.047655 1.402047 -6.272863 v -0.286444 1.362850 -6.194754 v -0.519624 1.405953 -6.217000 v -0.089194 0.975227 -6.316360 v -0.314427 0.991839 -6.268511 v -0.524734 1.082759 -6.324799 v -0.620360 1.490346 -6.331055 v -0.618762 1.036157 -6.434135 v -0.671873 0.861513 -6.294051 v -0.458822 1.733320 -5.357014 v -0.588193 1.649792 -5.825307 v -0.026324 0.948276 -6.554249 v 0.032057 1.491511 -6.432297 v 0.133877 1.609963 -5.922091 v 0.135806 1.725175 -5.451552 v -1.006792 1.503643 -5.022816 v -0.746747 1.667615 -5.005004 v -0.544041 1.766946 -5.171136 v -1.101978 1.447230 -5.268406 v -0.865298 1.642242 -5.298347 v -0.629541 1.716881 -5.454040 v -1.200089 1.376122 -5.716522 v -1.019358 1.528275 -5.796288 v -0.804275 1.567503 -5.929291 v -1.252437 1.200355 -6.000518 v -1.113296 1.218534 -6.177490 v -0.889340 1.184153 -6.312213 v -0.996484 1.194600 -5.651621 v -0.760670 1.184919 -5.687916 v -0.601537 1.292810 -5.762637 v -0.889795 1.206167 -5.227293 v -0.606970 1.236079 -5.234110 v -0.434302 1.401078 -5.343227 v -0.814929 1.299698 -4.991332 v -0.554814 1.384489 -4.970828 v -0.382345 1.502313 -5.098981 v -1.034163 1.181285 -5.881442 v -0.840806 1.210840 -5.961395 v -0.711468 1.257639 -6.107090 v -0.631209 1.479578 -5.875779 v -0.464679 1.605436 -5.447018 v -0.423460 1.665314 -5.121157 v -0.743932 1.268292 -6.251357 v -1.204943 1.178799 -5.894271 v -1.175692 1.262678 -5.660164 v -1.087312 1.296968 -5.240851 v -0.942971 1.397147 -4.977907 v 0.905754 1.424581 -6.519624 v 0.658060 0.741935 -6.754919 v 0.245147 0.365997 -8.304296 v -0.134337 1.769119 -5.224316 v -0.634812 1.552140 -4.922270 v 0.657481 0.439112 -6.123274

  1. 281 vertices
  2. 0 texture vertices
  3. 0 normals

usemtl hand f 2 4 1 f 5 4 2 f 3 5 2 f 5 6 4 f 1 10 9 f 1 7 10 f 7 11 10 f 7 8 11 f 10 12 9 f 12 10 13 f 10 14 13 f 10 11 14 f 12 17 9 f 12 15 17 f 18 15 16 f 15 18 17 f 9 2 1 f 9 17 2 f 18 2 17 f 2 18 3 f 19 4 6 f 7 4 19 f 8 7 19 f 7 1 4 f 20 22 12 f 23 22 20 f 21 23 20 f 23 24 22 f 16 26 25 f 16 15 26 f 15 22 26 f 15 12 22 f 25 28 27 f 25 26 28 f 22 28 26 f 28 22 24 f 30 31 29 f 32 31 30 f 6 32 30 f 32 33 31 f 5 32 6 f 32 5 34 f 5 35 34 f 5 3 35 f 34 33 32 f 33 34 36 f 35 36 34 f 36 35 37 f 39 40 38 f 31 40 39 f 29 31 39 f 31 33 40 f 42 43 41 f 40 43 42 f 38 40 42 f 40 33 43 f 45 46 44 f 46 45 47 f 38 47 45 f 47 38 42 f 46 49 48 f 46 47 49 f 47 41 49 f 47 42 41 f 44 52 45 f 44 50 52 f 50 53 52 f 50 51 53 f 52 38 45 f 38 52 39 f 52 29 39 f 52 53 29 f 36 55 33 f 55 36 56 f 37 56 36 f 56 37 54 f 56 24 55 f 24 56 28 f 27 56 54 f 56 27 28 f 33 57 43 f 33 55 57 f 55 58 57 f 55 24 58 f 57 41 43 f 41 57 59 f 58 59 57 f 59 58 60 f 62 64 61 f 64 62 65 f 63 65 62 f 65 63 66 f 65 21 64 f 21 65 23 f 66 23 65 f 23 66 24 f 66 58 24 f 58 66 67 f 63 67 66 f 67 63 68 f 67 60 58 f 60 67 69 f 68 69 67 f 69 68 70 f 61 72 71 f 61 64 72 f 64 73 72 f 64 21 73 f 71 75 74 f 71 72 75 f 72 76 75 f 72 73 76 f 53 77 29 f 77 53 78 f 51 78 53 f 78 51 79 f 78 80 77 f 80 78 81 f 79 81 78 f 81 79 82 f 83 77 80 f 77 83 85 f 83 86 85 f 83 84 86 f 85 29 77 f 29 85 30 f 86 30 85 f 30 86 6 f 73 87 76 f 87 73 88 f 21 88 73 f 88 21 20 f 88 89 87 f 89 88 90 f 20 90 88 f 90 20 12 f 90 91 89 f 91 90 92 f 90 13 92 f 90 12 13 f 91 94 93 f 91 92 94 f 92 14 94 f 92 13 14 f 95 98 97 f 95 96 98 f 8 98 96 f 98 8 19 f 97 86 84 f 97 98 86 f 19 86 98 f 86 19 6 f 59 49 41 f 49 59 99 f 59 69 99 f 59 60 69 f 99 48 49 f 48 99 100 f 99 70 100 f 99 69 70 f 8 101 11 f 8 96 101 f 96 102 101 f 96 95 102 f 101 14 11 f 14 101 94 f 101 93 94 f 101 102 93 f 103 107 106 f 103 104 107 f 105 107 104 f 107 105 108 f 107 109 106 f 109 107 110 f 108 110 107 f 110 108 111 f 63 113 68 f 63 112 113 f 112 104 113 f 112 105 104 f 68 114 70 f 68 113 114 f 113 103 114 f 113 104 103 f 115 118 117 f 115 116 118 f 105 118 116 f 118 105 112 f 117 62 61 f 117 118 62 f 112 62 118 f 62 112 63 f 120 121 119 f 121 120 122 f 111 122 120 f 122 111 108 f 122 115 121 f 115 122 116 f 108 116 122 f 116 108 105 f 123 127 126 f 123 124 127 f 124 128 127 f 124 125 128 f 126 130 129 f 126 127 130 f 127 131 130 f 127 128 131 f 44 133 132 f 44 46 133 f 48 133 46 f 133 48 134 f 132 126 129 f 132 133 126 f 134 126 133 f 126 134 123 f 135 138 137 f 135 136 138 f 136 130 138 f 136 129 130 f 137 140 139 f 137 138 140 f 138 131 140 f 138 130 131 f 51 142 141 f 51 50 142 f 50 132 142 f 50 44 132 f 141 136 135 f 141 142 136 f 142 129 136 f 142 132 129 f 109 144 106 f 109 143 144 f 125 144 143 f 144 125 124 f 106 145 103 f 106 144 145 f 124 145 144 f 145 124 123 f 100 134 48 f 134 100 146 f 70 146 100 f 146 70 114 f 146 123 134 f 123 146 145 f 114 145 146 f 145 114 103 f 135 148 141 f 135 147 148 f 147 117 148 f 147 115 117 f 141 149 51 f 141 148 149 f 148 61 149 f 148 117 61 f 115 150 121 f 115 147 150 f 135 150 147 f 150 135 137 f 121 151 119 f 121 150 151 f 137 151 150 f 151 137 139 f 120 152 111 f 152 120 153 f 119 153 120 f 153 119 154 f 152 156 155 f 152 153 156 f 153 157 156 f 153 154 157 f 158 161 160 f 158 159 161 f 159 110 161 f 159 109 110 f 160 152 155 f 160 161 152 f 161 111 152 f 161 110 111 f 162 140 131 f 140 162 164 f 162 165 164 f 162 163 165 f 164 139 140 f 139 164 166 f 164 167 166 f 164 165 167 f 168 171 170 f 168 169 171 f 163 171 169 f 171 163 162 f 171 125 170 f 125 171 128 f 162 128 171 f 128 162 131 f 172 169 168 f 169 172 173 f 158 173 172 f 173 158 160 f 169 174 163 f 169 173 174 f 160 174 173 f 174 160 155 f 157 176 156 f 157 175 176 f 167 176 175 f 176 167 165 f 176 155 156 f 155 176 174 f 176 163 174 f 176 165 163 f 177 181 180 f 177 178 181 f 178 182 181 f 178 179 182 f 181 183 180 f 183 181 184 f 181 185 184 f 181 182 185 f 186 75 76 f 75 186 187 f 179 187 186 f 187 179 178 f 187 74 75 f 74 187 188 f 178 188 187 f 188 178 177 f 189 193 192 f 189 190 193 f 191 193 190 f 193 191 194 f 192 196 195 f 192 193 196 f 193 197 196 f 193 194 197 f 81 198 80 f 198 81 199 f 82 199 81 f 199 82 200 f 199 195 198 f 195 199 192 f 200 192 199 f 192 200 189 f 200 201 189 f 201 200 202 f 200 203 202 f 200 82 203 f 202 177 201 f 177 202 188 f 202 74 188 f 202 203 74 f 177 204 201 f 177 180 204 f 183 204 180 f 204 183 205 f 204 189 201 f 189 204 190 f 204 191 190 f 204 205 191 f 195 207 198 f 195 206 207 f 179 207 206 f 207 179 186 f 198 208 80 f 198 207 208 f 186 208 207 f 208 186 76 f 206 182 179 f 182 206 209 f 206 196 209 f 206 195 196 f 209 185 182 f 185 209 210 f 209 197 210 f 209 196 197 f 211 215 214 f 211 212 215 f 213 215 212 f 215 213 216 f 215 217 214 f 217 215 218 f 216 218 215 f 218 216 219 f 220 216 213 f 216 220 221 f 76 221 220 f 221 76 87 f 221 219 216 f 219 221 222 f 87 222 221 f 222 87 89 f 223 227 226 f 223 224 227 f 225 227 224 f 227 225 228 f 227 229 226 f 229 227 230 f 228 230 227 f 230 228 231 f 230 232 229 f 232 230 233 f 231 233 230 f 233 231 234 f 233 80 232 f 80 233 83 f 233 84 83 f 233 234 84 f 222 235 219 f 235 222 236 f 222 237 236 f 222 89 237 f 236 231 235 f 231 236 234 f 237 234 236 f 234 237 84 f 217 239 238 f 217 218 239 f 219 239 218 f 239 219 235 f 239 225 238 f 225 239 228 f 239 231 228 f 239 235 231 f 220 208 76 f 208 220 240 f 213 240 220 f 240 213 241 f 208 232 80 f 208 240 232 f 240 229 232 f 240 241 229 f 241 226 229 f 226 241 242 f 241 212 242 f 241 213 212 f 242 223 226 f 223 242 243 f 242 211 243 f 242 212 211 f 244 248 247 f 244 245 248 f 246 248 245 f 248 246 249 f 248 250 247 f 250 248 251 f 249 251 248 f 251 249 252 f 250 254 253 f 250 251 254 f 252 254 251 f 254 252 255 f 253 91 93 f 253 254 91 f 254 89 91 f 254 255 89 f 256 260 259 f 256 257 260 f 258 260 257 f 260 258 261 f 260 262 259 f 262 260 263 f 260 264 263 f 260 261 264 f 97 265 95 f 265 97 266 f 84 266 97 f 266 84 267 f 265 257 256 f 265 266 257 f 267 257 266 f 257 267 258 f 249 268 252 f 268 249 269 f 249 270 269 f 249 246 270 f 269 258 268 f 258 269 261 f 269 264 261 f 269 270 264 f 255 237 89 f 237 255 271 f 252 271 255 f 271 252 268 f 271 84 237 f 84 271 267 f 268 267 271 f 267 268 258 f 102 253 93 f 253 102 272 f 102 265 272 f 102 95 265 f 272 250 253 f 250 272 273 f 272 256 273 f 272 265 256 f 259 273 256 f 273 259 274 f 262 274 259 f 274 262 275 f 273 247 250 f 273 274 247 f 274 244 247 f 274 275 244 f 172 159 158 f 159 172 276 f 172 170 276 f 172 168 170 f 276 109 159 f 109 276 143 f 170 143 276 f 143 170 125 f 151 154 119 f 154 151 277 f 151 166 277 f 151 139 166 f 154 175 157 f 154 277 175 f 277 167 175 f 277 166 167 f 197 278 210 f 197 194 278 f 191 278 194 f 278 191 205 f 278 185 210 f 185 278 184 f 278 183 184 f 278 205 183 f 223 279 224 f 223 243 279 f 211 279 243 f 279 211 214 f 279 225 224 f 225 279 238 f 279 217 238 f 279 214 217 f 262 280 275 f 262 263 280 f 264 280 263 f 280 264 270 f 280 244 275 f 244 280 245 f 270 245 280 f 245 270 246 f 74 281 71 f 74 203 281 f 82 281 203 f 281 82 79 f 71 149 61 f 71 281 149 f 79 149 281 f 149 79 51

  1. 552 elements
  • /
      </source>
   
  
 
  



Red Green Girl

   <source lang="java">

//Copyright 2001 Resplendent Technology Ltd. greg@resplendent.ru import java.applet.Applet; import java.awt.FlowLayout; import java.awt.GraphicsConfiguration; import java.net.URL; import java.util.Enumeration; import java.util.Hashtable; 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.Material; import javax.media.j3d.RenderingAttributes; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TransparencyAttributes; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import com.sun.j3d.loaders.Scene; import com.sun.j3d.loaders.objectfile.ObjectFile; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior; import com.sun.j3d.utils.behaviors.mouse.MouseRotate; import com.sun.j3d.utils.behaviors.mouse.MouseTranslate; import com.sun.j3d.utils.universe.SimpleUniverse; public class RedGreenGirl extends Applet {

   protected Canvas3D c1 = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
  // private Canvas3D c2 = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
   private static MainFrame mf;
   protected SimpleUniverse u = null;
   protected BranchGroup scene = null;
   protected String URLString = "http://www.java3d.org/renee.obj";
   protected float eyeOffset =0.03F;
   protected static int size=600;
   public void init() {
       setLayout(new FlowLayout());
       GraphicsConfiguration config =
          SimpleUniverse.getPreferredConfiguration();
       String v = getParameter("url");   
       if (v != null) { URLString = v; }
       c1.setSize(size, size);
       add(c1);
       scene = createSceneGraph(0);
       u = new SimpleUniverse(c1);
       // This will move the ViewPlatform back a bit so the
       // objects in the scene can be viewed.
       //u.getViewingPlatform().setNominalViewingTransform();
       u.addBranchGraph(scene);
   }
   public BranchGroup createSceneGraph(int i) {
       System.out.println("Creating scene for: "+URLString);
       // Create the root of the branch graph
       BranchGroup objRoot = new BranchGroup();
       try{
         Transform3D myTransform3D = new Transform3D();
         myTransform3D.setTranslation(new Vector3f(+0.0f,-0.15f,-3.6f));
         TransformGroup objTrans = new TransformGroup(myTransform3D);
           objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
           Transform3D t = new Transform3D();
         TransformGroup tg = new TransformGroup(t);
         tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
         tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
         objTrans.addChild(tg);
           URL url = new URL(URLString) ;
           ObjectFile f = new ObjectFile();
           f.setFlags(ObjectFile.RESIZE | ObjectFile.TRIANGULATE | ObjectFile.STRIPIFY);
           System.out.println( "About to load" );
           
           Scene s = f.load(url);
           Transform3D myTrans = new Transform3D();
           myTrans.setTranslation(new Vector3f(eyeOffset, -eyeOffset, 0F));
           TransformGroup mytg = new TransformGroup(myTrans);
           //mytg.addChild(s.getSceneGroup());
           tg.addChild(mytg);
           Transform3D myTrans2 = new Transform3D();
           myTrans2.setTranslation(new Vector3f(-eyeOffset, +eyeOffset, 0F));
           TransformGroup mytg2 = new TransformGroup(myTrans2);
           //mytg2.addChild(s.getSceneGroup());
           Hashtable table = s.getNamedObjects(); 
           for (Enumeration e = table.keys() ; e.hasMoreElements() ;) {
           Object key = e.nextElement();
           System.out.println(key);
           Object obj = table.get(key);
           System.out.println(obj.getClass().getName());
           Shape3D shape  = (Shape3D)obj;
           //shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
           Appearance ap = new Appearance();
           Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
           Color3f red = new Color3f(0.7f, .0f, .15f);
           Color3f green = new Color3f(0f, .7f, .15f);
           ap.setMaterial(new Material(green,black, green, black, 1.0f));
           Appearance ap2 = new Appearance();
           ap2.setMaterial(new Material(red, black, red, black, 1.0f));
           float transparencyValue = 0.5f;
           TransparencyAttributes t_attr =
               new TransparencyAttributes(
               TransparencyAttributes.BLENDED,
               transparencyValue,
               TransparencyAttributes.BLEND_SRC_ALPHA,
               TransparencyAttributes.BLEND_ONE);
           ap2.setTransparencyAttributes( t_attr );
           ap2.setRenderingAttributes( new RenderingAttributes() );
           ap.setTransparencyAttributes( t_attr );
           ap.setRenderingAttributes( new RenderingAttributes() );
           // bg.addChild(ap);
           shape.setAppearance(ap);
           mytg2.addChild(new Shape3D(shape.getGeometry(),ap2));
           mytg.addChild(new Shape3D(shape.getGeometry(),ap));
       }
       tg.addChild(mytg2);
       System.out.println( "Finished Loading" );
       BoundingSphere bounds =
         new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
       Color3f light1Color = new Color3f(.9f, 0.9f, 0.9f);
       Vector3f light1Direction  = new Vector3f(4.0f, -7.0f, -12.0f);
       DirectionalLight light1
       = new DirectionalLight(light1Color, light1Direction);
       light1.setInfluencingBounds(bounds);
       objTrans.addChild(light1);
             // Set up the ambient light
       Color3f ambientColor = new Color3f(1.0f, .4f, 0.3f);
       AmbientLight ambientLightNode = new AmbientLight(ambientColor);
       ambientLightNode.setInfluencingBounds(bounds);
       objTrans.addChild(ambientLightNode);
       
       
       MouseRotate behavior = new MouseRotate();
     behavior.setTransformGroup(tg);
     objTrans.addChild(behavior);
       // Create the translate behavior node
     MouseTranslate behavior3 = new MouseTranslate();
     behavior3.setTransformGroup(tg);
     objTrans.addChild(behavior3);
     behavior3.setSchedulingBounds(bounds);
     
     KeyNavigatorBehavior keyNavBeh = new KeyNavigatorBehavior(tg);
   keyNavBeh.setSchedulingBounds(new BoundingSphere(
     new Point3d(),1000.0));
   objTrans.addChild(keyNavBeh);
   
     behavior.setSchedulingBounds(bounds);
       objRoot.addChild(objTrans);
       } catch(Throwable t){System.out.println("Error: "+t);}
       return objRoot;
   }     
   public RedGreenGirl() {
   }
   public void destroy() {
       u.removeAllLocales();
   }

   public static void main(String[] args) {
      
       RedGreenGirl s = new RedGreenGirl();
       if (args.length > 0) {
           s.URLString = args[0];
       }
       mf = new MainFrame(s, size, size);
   }

}


      </source>
   
  
 
  



Red Green Griffin

   <source lang="java">

// Copyright 2001 Resplendent Technology Ltd. greg@resplendent.ru import java.applet.Applet; import java.awt.FlowLayout; import java.awt.GraphicsConfiguration; import java.net.URL; import java.util.Enumeration; import java.util.Hashtable; 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.Material; import javax.media.j3d.RenderingAttributes; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TransparencyAttributes; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import com.sun.j3d.loaders.Scene; import com.sun.j3d.loaders.objectfile.ObjectFile; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior; import com.sun.j3d.utils.behaviors.mouse.MouseRotate; import com.sun.j3d.utils.behaviors.mouse.MouseTranslate; import com.sun.j3d.utils.universe.SimpleUniverse; public class RedGreenGriffin extends Applet {

 protected Canvas3D c1 = new Canvas3D(SimpleUniverse
     .getPreferredConfiguration());
 // private Canvas3D c2 = new
 // Canvas3D(SimpleUniverse.getPreferredConfiguration());
 private static MainFrame mf;
 protected SimpleUniverse u = null;
 protected BranchGroup scene = null;
 protected String URLString = "http://www.java3d.org/saurus.obj";
 protected float eyeOffset = 0.03F;
 protected static int size = 600;
 public void init() {
   setLayout(new FlowLayout());
   GraphicsConfiguration config = SimpleUniverse
       .getPreferredConfiguration();
   String v = getParameter("url");
   if (v != null) {
     URLString = v;
   }
   c1.setSize(size, size);
   add(c1);
   scene = createSceneGraph(0);
   u = new SimpleUniverse(c1);
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   //u.getViewingPlatform().setNominalViewingTransform();
   u.addBranchGraph(scene);
 }
 public BranchGroup createSceneGraph(int i) {
   System.out.println("Creating scene for: " + URLString);
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   try {
     Transform3D myTransform3D = new Transform3D();
     myTransform3D.setTranslation(new Vector3f(+0.0f, -0.15f, -3.6f));
     TransformGroup objTrans = new TransformGroup(myTransform3D);
     objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
     Transform3D t = new Transform3D();
     TransformGroup tg = new TransformGroup(t);
     tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
     tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
     objTrans.addChild(tg);
     URL url = new URL(URLString);
     ObjectFile f = new ObjectFile();
     f.setFlags(ObjectFile.RESIZE | ObjectFile.TRIANGULATE
         | ObjectFile.STRIPIFY);
     System.out.println("About to load");
     Scene s = f.load(url);
     Transform3D myTrans = new Transform3D();
     myTrans.setTranslation(new Vector3f(eyeOffset, -eyeOffset, 0F));
     TransformGroup mytg = new TransformGroup(myTrans);
     //mytg.addChild(s.getSceneGroup());
     tg.addChild(mytg);
     Transform3D myTrans2 = new Transform3D();
     myTrans2.setTranslation(new Vector3f(-eyeOffset, +eyeOffset, 0F));
     TransformGroup mytg2 = new TransformGroup(myTrans2);
     //mytg2.addChild(s.getSceneGroup());
     Hashtable table = s.getNamedObjects();
     for (Enumeration e = table.keys(); e.hasMoreElements();) {
       Object key = e.nextElement();
       System.out.println(key);
       Object obj = table.get(key);
       System.out.println(obj.getClass().getName());
       Shape3D shape = (Shape3D) obj;
       //shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
       Appearance ap = new Appearance();
       Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
       Color3f red = new Color3f(0.7f, .0f, .15f);
       Color3f green = new Color3f(0f, .7f, .15f);
       ap.setMaterial(new Material(green, black, green, black, 1.0f));
       Appearance ap2 = new Appearance();
       ap2.setMaterial(new Material(red, black, red, black, 1.0f));
       float transparencyValue = 0.5f;
       TransparencyAttributes t_attr = new TransparencyAttributes(
           TransparencyAttributes.BLENDED, transparencyValue,
           TransparencyAttributes.BLEND_SRC_ALPHA,
           TransparencyAttributes.BLEND_ONE);
       ap2.setTransparencyAttributes(t_attr);
       ap2.setRenderingAttributes(new RenderingAttributes());
       ap.setTransparencyAttributes(t_attr);
       ap.setRenderingAttributes(new RenderingAttributes());
       // bg.addChild(ap);
       shape.setAppearance(ap);
       mytg2.addChild(new Shape3D(shape.getGeometry(), ap2));
       mytg.addChild(new Shape3D(shape.getGeometry(), ap));
     }
     tg.addChild(mytg2);
     System.out.println("Finished Loading");
     BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0,
         0.0), 100.0);
     Color3f light1Color = new Color3f(.9f, 0.9f, 0.9f);
     Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
     DirectionalLight light1 = new DirectionalLight(light1Color,
         light1Direction);
     light1.setInfluencingBounds(bounds);
     objTrans.addChild(light1);
     // Set up the ambient light
     Color3f ambientColor = new Color3f(1.0f, .4f, 0.3f);
     AmbientLight ambientLightNode = new AmbientLight(ambientColor);
     ambientLightNode.setInfluencingBounds(bounds);
     objTrans.addChild(ambientLightNode);
     MouseRotate behavior = new MouseRotate();
     behavior.setTransformGroup(tg);
     objTrans.addChild(behavior);
     // Create the translate behavior node
     MouseTranslate behavior3 = new MouseTranslate();
     behavior3.setTransformGroup(tg);
     objTrans.addChild(behavior3);
     behavior3.setSchedulingBounds(bounds);
     KeyNavigatorBehavior keyNavBeh = new KeyNavigatorBehavior(tg);
     keyNavBeh.setSchedulingBounds(new BoundingSphere(new Point3d(),
         1000.0));
     objTrans.addChild(keyNavBeh);
     behavior.setSchedulingBounds(bounds);
     objRoot.addChild(objTrans);
   } catch (Throwable t) {
     System.out.println("Error: " + t);
   }
   return objRoot;
 }
 public RedGreenGriffin() {
 }
 public void destroy() {
   u.removeAllLocales();
 }
 public static void main(String[] args) {
   RedGreenGriffin s = new RedGreenGriffin();
   if (args.length > 0) {
     s.URLString = args[0];
   }
   mf = new MainFrame(s, size, size);
 }

}


      </source>
   
  
 
  



ShadowApp creates a single plane

   <source lang="java">

/*

*      ShadowApp.java 1.0 99/04/12
*
* Copyright (c) 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.
*/

/*

* This application demonstrates how a programmer can create shadows
* in Java 3D automatically.
*
* The class SimpleShadow produces shadow polygons for simple visual
* objects in certain situations.
*
* Note that no real time 3D graphics API provides automatic
* shadowing.
*
* This application (or a version of it) generated one or more
* of the images in Chapter 6 of Getting Started with the Java 3D API.
* The Java 3D Turtorial.
*
* See http://www.sun.ru/desktop/java3d/collateral for more information.
*
*/

import java.applet.Applet; import java.awt.BorderLayout; 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.Geometry; import javax.media.j3d.GeometryArray; import javax.media.j3d.Material; import javax.media.j3d.QuadArray; import javax.media.j3d.Shape3D; import javax.vecmath.Color3f; import javax.vecmath.Point3f; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.universe.SimpleUniverse; /**

* ShadowApp creates a single plane
*/

public class ShadowApp extends Applet {

 public class LitQuad extends Shape3D {
   LitQuad(Point3f A, Point3f B, Point3f C, Point3f D) {
     this.setGeometry(createGeometry(A, B, C, D));
     this.setAppearance(createAppearance());
   }
   Geometry createGeometry(Point3f A, Point3f B, Point3f C, Point3f D) {
     QuadArray plane = new QuadArray(4, GeometryArray.COORDINATES
         | GeometryArray.NORMALS);
     plane.setCoordinate(0, A);
     plane.setCoordinate(1, B);
     plane.setCoordinate(2, C);
     plane.setCoordinate(3, D);
     Vector3f a = new Vector3f(A.x - B.x, A.y - B.y, A.z - B.z);
     Vector3f b = new Vector3f(C.x - B.x, C.y - B.y, C.z - B.z);
     Vector3f n = new Vector3f();
     n.cross(b, a);
     n.normalize();
     plane.setNormal(0, n);
     plane.setNormal(1, n);
     plane.setNormal(2, n);
     plane.setNormal(3, n);
     return plane;
   }
   Appearance createAppearance() {
     Appearance appear = new Appearance();
     Material material = new Material();
     appear.setMaterial(material);
     return appear;
   }
 }
 public class SimpleShadow extends Shape3D {
   SimpleShadow(GeometryArray geom, Vector3f direction, Color3f col,
       float height) {
     int vCount = geom.getVertexCount();
     QuadArray poly = new QuadArray(vCount, GeometryArray.COORDINATES
         | GeometryArray.COLOR_3);
     int v;
     Point3f vertex = new Point3f();
     Point3f shadow = new Point3f();
     for (v = 0; v < vCount; v++) {
       geom.getCoordinate(v, vertex);
       shadow.set(vertex.x + (vertex.y - height) * direction.x,
           height + 0.0001f, vertex.z + (vertex.y - height)
               * direction.y);
       poly.setCoordinate(v, shadow);
       poly.setColor(v, col);
     }
     this.setGeometry(poly);
   }
 } // end of PolyFour class
 public ShadowApp() {
   setLayout(new BorderLayout());
   Canvas3D c = new Canvas3D(null);
   add("Center", c);
   BranchGroup scene = new BranchGroup();
   Shape3D plane = new LitQuad(new Point3f(-0.3f, 0.6f, 0.2f),
       new Point3f(-0.3f, -0.3f, 0.2f),
       new Point3f(0.6f, -0.3f, -0.3f), new Point3f(0.6f, 0.6f, -0.3f));
   scene.addChild(plane);
   Shape3D floor = new LitQuad(new Point3f(-1.0f, -0.5f, -1.0f),
       new Point3f(-1.0f, -0.5f, 1.0f),
       new Point3f(1.0f, -0.5f, 1.0f), new Point3f(1.0f, -0.5f, -1.0f));
   scene.addChild(floor);
   AmbientLight lightA = new AmbientLight();
   lightA.setInfluencingBounds(new BoundingSphere());
   scene.addChild(lightA);
   DirectionalLight lightD1 = new DirectionalLight();
   lightD1.setInfluencingBounds(new BoundingSphere());
   Vector3f direction = new Vector3f(-1.0f, -1.0f, -1.0f);
   direction.normalize();
   lightD1.setDirection(direction);
   scene.addChild(lightD1);
   Shape3D shadow = new SimpleShadow((GeometryArray) plane.getGeometry(),
       direction, new Color3f(0.2f, 0.2f, 0.2f), -0.5f);
   scene.addChild(shadow);
   SimpleUniverse u = new SimpleUniverse(c);
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   u.getViewingPlatform().setNominalViewingTransform();
   u.addBranchGraph(scene);
 }
 public static void main(String argv[]) {
   new MainFrame(new ShadowApp(), 256, 256);
 }

}


      </source>
   
  
 
  



Shape: Point outline

   <source lang="java">

/*

* YoyoPointApp.java 1.0 98/11/23
* 
* Copyright (c) 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.
*/

/*

* Getting Started with the Java 3D API written in Java 3D
* 
* YoyoPointApp.java demonstrates using an Appearance to render only the points
* from a more complex geometry.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.Alpha; import javax.media.j3d.Appearance; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Geometry; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TriangleFanArray; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.universe.SimpleUniverse; public class YoyoPointApp extends Applet {

 /////////////////////////////////////////////////
 //
 // create scene graph branch group
 //
 public class Yoyo extends Shape3D {
   ////////////////////////////////////////////
   //
   // create Shape3D with geometry and appearance
   // the geometry is created in method yoyoGeometry
   // the appearance is created in method yoyoAppearance
   //
   public Yoyo() {
     this.setGeometry(yoyoGeometry());
     this.setAppearance(yoyoAppearance());
   } // end of Yoyo constructor
   ////////////////////////////////////////////
   //
   // create yoyo geometry
   // four triangle fans represent the yoyo
   // strip indicies_______________
   //   0 0N+0 to 1N+0 ( 0 to N )
   //   1 1N+1 to 2N+1
   //   2 2N+2 to 3N+2
   //   3 3N+4 to 4N+3
   //
   private Geometry yoyoGeometry() {
     TriangleFanArray tfa;
     int N = 17;
     int totalN = 4 * (N + 1);
     Point3f coords[] = new Point3f[totalN];
     int stripCounts[] = { N + 1, N + 1, N + 1, N + 1 };
     float r = 0.6f;
     float w = 0.4f;
     int n;
     double a;
     float x, y;
     // set the central points for four triangle fan strips
     coords[0 * (N + 1)] = new Point3f(0.0f, 0.0f, w);
     coords[1 * (N + 1)] = new Point3f(0.0f, 0.0f, 0.0f);
     coords[2 * (N + 1)] = new Point3f(0.0f, 0.0f, 0.0f);
     coords[3 * (N + 1)] = new Point3f(0.0f, 0.0f, -w);
     for (a = 0, n = 0; n < N; a = 2.0 * Math.PI / (N - 1) * ++n) {
       x = (float) (r * Math.cos(a));
       y = (float) (r * Math.sin(a));
       coords[0 * (N + 1) + n + 1] = new Point3f(x, y, w);
       coords[1 * (N + 1) + N - n] = new Point3f(x, y, w);
       coords[2 * (N + 1) + n + 1] = new Point3f(x, y, -w);
       coords[3 * (N + 1) + N - n] = new Point3f(x, y, -w);
     }
     tfa = new TriangleFanArray(totalN, TriangleFanArray.COORDINATES,
         stripCounts);
     tfa.setCoordinates(0, coords);
     return tfa;
   } // end of method yoyoGeometry in class Yoyo
   ////////////////////////////////////////////
   //
   // create yoyo geometry
   //
   private Appearance yoyoAppearance() {
     Appearance appearance = new Appearance();
     PolygonAttributes polyAttrib = new PolygonAttributes();
     polyAttrib.setPolygonMode(PolygonAttributes.POLYGON_POINT);
     appearance.setPolygonAttributes(polyAttrib);
     return appearance;
   } // end of method yoyoAppearance of class Yoyo
 } // end of class Yoyo
 /////////////////////////////////////////////////
 //
 // create scene graph branch group
 //
 public BranchGroup createSceneGraph() {
   BranchGroup objRoot = new BranchGroup();
   // 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 objSpin = new TransformGroup();
   objSpin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objRoot.addChild(objSpin);
   objSpin.addChild(new Yoyo());
   // Create a new Behavior object that will perform the desired
   // operation on the specified transform object and add it into
   // the scene graph.
   Transform3D yAxis = new Transform3D();
   Alpha rotationAlpha = new Alpha(-1, 4000);
   RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
       objSpin);
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   rotator.setSchedulingBounds(bounds);
   objSpin.addChild(rotator);
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 } // end of CreateSceneGraph method of YoyoPointApp
 // Create a simple scene and attach it to the virtual universe
 public YoyoPointApp() {
   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 YoyoPointApp constructor
 //  The following allows this to be run as an application
 //  as well as an applet
 public static void main(String[] args) {
   Frame frame = new MainFrame(new YoyoPointApp(), 256, 256);
 } // end of main method of YoyoPointApp

} // end of class YoyoPointApp


      </source>
   
  
 
  



Simple Indexed Quad

   <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.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.IndexedQuadArray; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.Node; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; 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.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3f; /**

* This builds a simple class using the an indexed quadrilateral array. This
* demonstrates the use of the IndexedQuadArray class. It defines both the
* vertices and the normals of the cube such that the shape is shaded with flat
* faces.
* 
* @author I.J.Palmer
* @version 1.0
*/

public class SimpleIndexedQuad extends Frame implements ActionListener {

 protected Canvas3D myCanvas3D = new Canvas3D(null);
 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) {
   BranchGroup viewBranch = new BranchGroup();
   Transform3D viewXfm = new Transform3D();
   viewXfm.set(new Vector3f(0.0f, 0.0f, 5.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 so that we can illuminate the scene. This adds one
  * ambient light to bring up the overall lighting level and one directional
  * shape to show the shape of the objects in the scene.
  * 
  * @param b
  *            BranchGroup that the lights are to be added to.
  */
 protected void addLights(BranchGroup b) {
   //Create a bounding sphere to act as the active bounds
   //of the lights
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   //Create the colours and directions
   Color3f lightColour = new Color3f(1.0f, 1.0f, 1.0f);
   Vector3f lightDir = new Vector3f(-1.0f, -1.0f, -1.0f);
   Color3f ambientColour = new Color3f(0.2f, 0.2f, 0.2f);
   //Create the lights
   AmbientLight ambientLight = new AmbientLight(ambientColour);
   ambientLight.setInfluencingBounds(bounds);
   DirectionalLight directionalLight = new DirectionalLight(lightColour,
       lightDir);
   directionalLight.setInfluencingBounds(bounds);
   //Add the lights to the branch
   b.addChild(ambientLight);
   b.addChild(directionalLight);
 }
 /**
  * This builds the content branch of our scene graph. It uses the buildShape
  * function to create the actual shape, adding to to the transform group so
  * that the shape is slightly tilted to reveal its 3D shape. It also uses
  * the addLights function to add some lights to the scene.
  * 
  * @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) {
   BranchGroup contentBranch = new BranchGroup();
   Transform3D rotateCube = new Transform3D();
   rotateCube.set(new AxisAngle4d(1.0, 1.0, 0.0, Math.PI / 4.0));
   TransformGroup rotationGroup = new TransformGroup(rotateCube);
   contentBranch.addChild(rotationGroup);
   rotationGroup.addChild(shape);
   addLights(contentBranch);
   return contentBranch;
 }
 /**
  * Build a cube from an IndexedQuadArray. This method creates the vertices
  * as a set of eight points and the normals as a set of six vectors (one for
  * each face). The data is then defined such that each vertex has a
  * different normal associated with it when it is being used for a different
  * face.
  * 
  * @return Node that is the shape.
  */
 protected Node buildShape() {
   //The shape. The constructor specifies 8 vertices, that both
   //vertices and normals are to be defined and that there are
   //24 normals to be specified (4 for each of the 6 faces).
   IndexedQuadArray indexedCube = new IndexedQuadArray(8,
       IndexedQuadArray.COORDINATES | IndexedQuadArray.NORMALS, 24);
   //The vertex coordinates defined as an array of points.
   Point3f[] cubeCoordinates = { new Point3f(1.0f, 1.0f, 1.0f),
       new Point3f(-1.0f, 1.0f, 1.0f),
       new Point3f(-1.0f, -1.0f, 1.0f),
       new Point3f(1.0f, -1.0f, 1.0f), new Point3f(1.0f, 1.0f, -1.0f),
       new Point3f(-1.0f, 1.0f, -1.0f),
       new Point3f(-1.0f, -1.0f, -1.0f),
       new Point3f(1.0f, -1.0f, -1.0f) };
   //The vertex normals defined as an array of vectors
   Vector3f[] normals = { new Vector3f(0.0f, 0.0f, 1.0f),
       new Vector3f(0.0f, 0.0f, -1.0f),
       new Vector3f(1.0f, 0.0f, 0.0f),
       new Vector3f(-1.0f, 0.0f, 0.0f),
       new Vector3f(0.0f, 1.0f, 0.0f), new Vector3f(0.0f, -1.0f, 0.0f) };
   //Define the indices used to reference vertex array
   int coordIndices[] = { 0, 1, 2, 3, 7, 6, 5, 4, 0, 3, 7, 4, 5, 6, 2, 1,
       0, 4, 5, 1, 6, 7, 3, 2 };
   //Define the indices used to reference normal array
   int normalIndices[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
       4, 4, 4, 4, 5, 5, 5, 5 };
   //Set the data
   indexedCube.setCoordinates(0, cubeCoordinates);
   indexedCube.setNormals(0, normals);
   indexedCube.setCoordinateIndices(0, coordIndices);
   indexedCube.setNormalIndices(0, normalIndices);
   //Define an appearance for the shape
   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));
   //Create and return the shape
   return new Shape3D(indexedCube, app);
 }
 /**
  * Handles the exit button action to quit the program.
  */
 public void actionPerformed(ActionEvent e) {
   dispose();
   System.exit(0);
 }
 public SimpleIndexedQuad() {
   VirtualUniverse myUniverse = new VirtualUniverse();
   Locale myLocale = new Locale(myUniverse);
   myLocale.addBranchGraph(buildViewBranch(myCanvas3D));
   myLocale.addBranchGraph(buildContentBranch(buildShape()));
   setTitle("SimpleIndexedQuad");
   setSize(400, 400);
   setLayout(new BorderLayout());
   add("Center", myCanvas3D);
   add("South", myButton);
   myButton.addActionListener(this);
   setVisible(true);
 }
 public static void main(String[] args) {
   SimpleIndexedQuad siq = new SimpleIndexedQuad();
 }

}

      </source>
   
  
 
  



Simple Indexed Quad Normals

   <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.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.IndexedQuadArray; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.Node; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; 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.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3f; /**

* This builds a simple class using the an indexed quadrilateral array. This
* demonstrates the use of the IndexedQuadArray class. It defines both the
* vertices and the normals of the cube such that the shape is shaded with flat
* faces.
* 
* @author I.J.Palmer
* @version 1.0
*/

public class SimpleIndexedQuadNormals extends Frame implements ActionListener {

 protected Canvas3D myCanvas3D = new Canvas3D(null);
 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) {
   BranchGroup viewBranch = new BranchGroup();
   Transform3D viewXfm = new Transform3D();
   viewXfm.set(new Vector3f(0.0f, 0.0f, 5.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 so that we can illuminate the scene. This adds one
  * ambient light to bring up the overall lighting level and one directional
  * shape to show the shape of the objects in the scene.
  * 
  * @param b
  *            BranchGroup that the lights are to be added to.
  */
 protected void addLights(BranchGroup b) {
   //Create a bounding sphere to act as the active bounds
   //of the lights
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   //Create the colours and directions
   Color3f lightColour = new Color3f(1.0f, 1.0f, 1.0f);
   Vector3f lightDir = new Vector3f(-1.0f, -1.0f, -1.0f);
   Color3f ambientColour = new Color3f(0.2f, 0.2f, 0.2f);
   //Create the lights
   AmbientLight ambientLight = new AmbientLight(ambientColour);
   ambientLight.setInfluencingBounds(bounds);
   DirectionalLight directionalLight = new DirectionalLight(lightColour,
       lightDir);
   directionalLight.setInfluencingBounds(bounds);
   //Add the lights to the branch
   b.addChild(ambientLight);
   b.addChild(directionalLight);
 }
 /**
  * This builds the content branch of our scene graph. It uses the buildShape
  * function to create the actual shape, adding to to the transform group so
  * that the shape is slightly tilted to reveal its 3D shape. It also uses
  * the addLights function to add some lights to the scene.
  * 
  * @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) {
   BranchGroup contentBranch = new BranchGroup();
   Transform3D rotateCube = new Transform3D();
   rotateCube.set(new AxisAngle4d(1.0, 1.0, 0.0, Math.PI / 4.0));
   TransformGroup rotationGroup = new TransformGroup(rotateCube);
   contentBranch.addChild(rotationGroup);
   rotationGroup.addChild(shape);
   addLights(contentBranch);
   return contentBranch;
 }
 /**
  * Build a cube from an IndexedQuadArray. This method creates the vertices
  * as a set of eight points and the normals as a set of six vectors (one for
  * each face). The data is then defined such that each vertex has a
  * different normal associated with it when it is being used for a different
  * face.
  * 
  * @return Node that is the shape.
  */
 protected Node buildShape() {
   //The shape. The constructor specifies 8 vertices, that both
   //vertices and normals are to be defined and that there are
   //24 normals to be specified (4 for each of the 6 faces).
   IndexedQuadArray indexedCube = new IndexedQuadArray(8,
       IndexedQuadArray.COORDINATES | IndexedQuadArray.NORMALS, 24);
   //The vertex coordinates defined as an array of points.
   Point3f[] cubeCoordinates = { new Point3f(1.0f, 1.0f, 1.0f),
       new Point3f(-1.0f, 1.0f, 1.0f),
       new Point3f(-1.0f, -1.0f, 1.0f),
       new Point3f(1.0f, -1.0f, 1.0f), new Point3f(1.0f, 1.0f, -1.0f),
       new Point3f(-1.0f, 1.0f, -1.0f),
       new Point3f(-1.0f, -1.0f, -1.0f),
       new Point3f(1.0f, -1.0f, -1.0f) };
   //The vertex normals defined as an array of vectors
   Vector3f[] normals = { new Vector3f(0.0f, 0.0f, 1.0f),
       new Vector3f(0.0f, 0.0f, -1.0f),
       new Vector3f(1.0f, 0.0f, 0.0f),
       new Vector3f(-1.0f, 0.0f, 0.0f),
       new Vector3f(0.0f, 1.0f, 0.0f), new Vector3f(0.0f, -1.0f, 0.0f) };
   //Define the indices used to reference vertex array
   int coordIndices[] = { 0, 1, 2, 3, 7, 6, 5, 4, 0, 3, 7, 4, 5, 6, 2, 1,
       0, 4, 5, 1, 6, 7, 3, 2 };
   //Define the indices used to reference normal array
   int normalIndices[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
       4, 4, 4, 4, 5, 5, 5, 5 };
   //Set the data
   indexedCube.setCoordinates(0, cubeCoordinates);
   indexedCube.setNormals(0, normals);
   indexedCube.setCoordinateIndices(0, coordIndices);
   indexedCube.setNormalIndices(0, normalIndices);
   //Define an appearance for the shape
   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));
   //Create and return the shape
   return new Shape3D(indexedCube, app);
 }
 /**
  * Handles the exit button action to quit the program.
  */
 public void actionPerformed(ActionEvent e) {
   dispose();
   System.exit(0);
 }
 public SimpleIndexedQuadNormals() {
   VirtualUniverse myUniverse = new VirtualUniverse();
   Locale myLocale = new Locale(myUniverse);
   myLocale.addBranchGraph(buildViewBranch(myCanvas3D));
   myLocale.addBranchGraph(buildContentBranch(buildShape()));
   setTitle("SimpleIndexedQuadNormals");
   setSize(400, 400);
   setLayout(new BorderLayout());
   add("Center", myCanvas3D);
   add("South", myButton);
   myButton.addActionListener(this);
   setVisible(true);
 }
 public static void main(String[] args) {
   SimpleIndexedQuadNormals siqn = new SimpleIndexedQuadNormals();
 }

}

      </source>
   
  
 
  



Stereo Girl

   <source lang="java">

// //Copyright 2001 Resplendent Technology Ltd. greg@resplendent.ru import java.applet.Applet; import java.awt.FlowLayout; import java.awt.GraphicsConfiguration; import java.net.URL; import javax.media.j3d.AmbientLight; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.PhysicalBody; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import com.sun.j3d.loaders.Scene; import com.sun.j3d.loaders.objectfile.ObjectFile; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior; import com.sun.j3d.utils.behaviors.mouse.MouseRotate; import com.sun.j3d.utils.behaviors.mouse.MouseTranslate; import com.sun.j3d.utils.universe.SimpleUniverse; public class StereoGirl extends Applet {

 private Canvas3D c1 = new Canvas3D(SimpleUniverse
     .getPreferredConfiguration());
 private Canvas3D c2 = new Canvas3D(SimpleUniverse
     .getPreferredConfiguration());
 private static MainFrame mf;
 private SimpleUniverse u = null;
 private BranchGroup scene = null;
 private String URLString = "http://216.250.225.154/renee.obj";
 public void init() {
   setLayout(new FlowLayout());
   GraphicsConfiguration config = SimpleUniverse
       .getPreferredConfiguration();
   String v = getParameter("url");
   if (v != null) {
     URLString = v;
   }
   c1.setSize(140, 140);
   c1.setMonoscopicViewPolicy(View.LEFT_EYE_VIEW);
   add(c1);
   c2.setSize(140, 140);
   c2.setMonoscopicViewPolicy(View.RIGHT_EYE_VIEW);
   add(c2);
   // Create a simple scene and attach it to the virtual universe
   scene = createSceneGraph(0);
   u = new SimpleUniverse(c1);
   View view0 = u.getViewer().getView();
   View view = new View();
   PhysicalBody myBod = view0.getPhysicalBody();
   myBod.setLeftEyePosition(new Point3d(-.006, 0.0, 0.0)); // default
                               // is(-0.033,
                               // 0.0, 0.0)
   myBod.setRightEyePosition(new Point3d(+.006, 0.0, 0.0));
   view.setPhysicalBody(myBod);
   view.setPhysicalEnvironment(view0.getPhysicalEnvironment());
   view.attachViewPlatform(u.getViewingPlatform().getViewPlatform());
   view.addCanvas3D(c2);
   // This will move the ViewPlatform back a bit so the
   // objects in the scene can be viewed.
   u.getViewingPlatform().setNominalViewingTransform();
   u.addBranchGraph(scene);
 }
 public BranchGroup createSceneGraph(int i) {
   System.out.println("Creating scene for: " + URLString);
   // Create the root of the branch graph
   BranchGroup objRoot = new BranchGroup();
   try {
     Transform3D myTransform3D = new Transform3D();
     myTransform3D.setTranslation(new Vector3f(+0.0f, -0.1f, -1.2f));
     TransformGroup objTrans = new TransformGroup(myTransform3D);
     objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
     Transform3D t = new Transform3D();
     TransformGroup tg = new TransformGroup(t);
     tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
     tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
     objTrans.addChild(tg);
     URL url = new URL(URLString);
     ObjectFile f = new ObjectFile();
     f.setFlags(ObjectFile.RESIZE | ObjectFile.TRIANGULATE
         | ObjectFile.STRIPIFY);
     System.out.println("About to load");
     Scene s = f.load(url);
     tg.addChild(s.getSceneGroup());
     System.out.println("Finished Loading");
     BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0,
         0.0), 100.0);
     Color3f light1Color = new Color3f(.9f, 0.8f, 0.8f);
     Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
     DirectionalLight light1 = new DirectionalLight(light1Color,
         light1Direction);
     light1.setInfluencingBounds(bounds);
     objTrans.addChild(light1);
     // Set up the ambient light
     Color3f ambientColor = new Color3f(1.0f, .4f, 0.3f);
     AmbientLight ambientLightNode = new AmbientLight(ambientColor);
     ambientLightNode.setInfluencingBounds(bounds);
     objTrans.addChild(ambientLightNode);
     MouseRotate behavior = new MouseRotate();
     behavior.setTransformGroup(tg);
     objTrans.addChild(behavior);
     // Create the translate behavior node
     MouseTranslate behavior3 = new MouseTranslate();
     behavior3.setTransformGroup(tg);
     objTrans.addChild(behavior3);
     behavior3.setSchedulingBounds(bounds);
     KeyNavigatorBehavior keyNavBeh = new KeyNavigatorBehavior(tg);
     keyNavBeh.setSchedulingBounds(new BoundingSphere(new Point3d(),
         1000.0));
     objTrans.addChild(keyNavBeh);
     behavior.setSchedulingBounds(bounds);
     objRoot.addChild(objTrans);
   } catch (Throwable t) {
     System.out.println("Error: " + t);
   }
   return objRoot;
 }
 public StereoGirl() {
 }
 public void destroy() {
   u.removeAllLocales();
 }
 public static void main(String[] args) {
   StereoGirl s = new StereoGirl();
   if (args.length > 0) {
     s.URLString = args[0];
   }
   mf = new MainFrame(s, 400, 200);
 }

}

      </source>
   
  
 
  



Teapot

   <source lang="java">

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import java.awt.GraphicsConfiguration; import java.io.FileNotFoundException; import java.net.MalformedURLException; import java.net.URL; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import com.sun.j3d.loaders.IncorrectFormatException; import com.sun.j3d.loaders.ParsingErrorException; import com.sun.j3d.loaders.Scene; import com.sun.j3d.loaders.objectfile.ObjectFile; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.universe.SimpleUniverse; /**

* !Diese Klasse wurde fur das Laden uber ein JAR-Archiv oder Applet welches ein
* JAR - Archiv nutzt angepasst Um das Programm als einfache Applikation uber
* einen class-File laufen zu lassen bitte auf den Code zum Einladen der OBJ
* Datei im Tutorial zuruckgreifen!
*/

public class Phong extends Applet {

 /**
  * init Methoden fur die Darstellung als Applet
  */
 public void init() {
   setLayout(new BorderLayout());
   GraphicsConfiguration config = SimpleUniverse
       .getPreferredConfiguration();
   canvas3D = new Canvas3D(config);
   add("Center", canvas3D);
   BranchGroup szene = macheSzene();
   szene.rupile();
   universe = new SimpleUniverse(canvas3D);
   universe.getViewingPlatform().setNominalViewingTransform();
   universe.addBranchGraph(szene);
 }
 /**
  * Erstellt den Szenegraphen
  * 
  * @return BranchGroup
  */
 public BranchGroup macheSzene() {
   BranchGroup objWurzel = new BranchGroup();
   // Transformation, 2 Rotationen:
   Transform3D drehung = new Transform3D();
   Transform3D drehung2 = new Transform3D();
   drehung.rotX(Math.PI / 4.0d);
   drehung2.rotY(Math.PI / 5.0d);
   drehung.mul(drehung2);
   TransformGroup objDreh = new TransformGroup(drehung);
   //Loader
   ObjectFile file = new ObjectFile(ObjectFile.RESIZE);
   Scene scene = null;
   try {
       scene = file.load(ClassLoader.getSystemResource("teapot.obj"));
   } catch (Exception e) {
     System.err.println(e);
     System.exit(1);
   }
   objDreh.addChild(scene.getSceneGroup());
   DirectionalLight d_Licht = new DirectionalLight(new Color3f(1.0f, 1.0f,
       1.0f), new Vector3f(-1.0f, -1.0f, -1.0f));
   d_Licht.setInfluencingBounds(new BoundingSphere(new Point3d(0.0d, 0.0d,
       0.0d), 100.0d));
   objDreh.addChild(d_Licht);
   objWurzel.addChild(objDreh);
   return objWurzel;
 }
 /**
  * gibt speicher frei
  */
 public void destroy() {
   universe.removeAllLocales();
 }
 public static void main(String[] args) {
   frame = new MainFrame(new Phong(), 500, 500);
   frame.setTitle("Phong");
 }
 //---- Attribute -----------------------
 private SimpleUniverse universe;
 private Canvas3D canvas3D;
 private static Frame frame;

}


      </source>
   
  
 
  



The use of the GeometryInfo class and related classes

   <source lang="java">

/*

* GeomInfoApp.java 1.0 99/02/19
* 
* Copyright (c) 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.
*/

/*

* GeomInfoApp.java demonstrates the use of the GeometryInfo class and related
* classes.
* 
* This program creates a car shape (not a fancy car, though) using GeometryInfo
* objects. One GeometryInfo object specifies the side of the car using a
* polygon (not a triangle, nor a quad). The GeometryInfo and other classes
* convert the polygons into a triangle strips with normals.
* 
* Note that about half of the source code just specifies the input data to the
* GeometryInfo objects. The interesting part starts around line 210.
* 
* An alternative data set is provided (in the comments) for further
* experimentation - see the tutorial text.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.Alpha; 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.ColoringAttributes; import javax.media.j3d.DirectionalLight; import javax.media.j3d.LineArray; import javax.media.j3d.LineAttributes; import javax.media.j3d.LineStripArray; import javax.media.j3d.Material; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Shape3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Color3f; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.GeometryInfo; import com.sun.j3d.utils.geometry.NormalGenerator; import com.sun.j3d.utils.geometry.Stripifier; import com.sun.j3d.utils.geometry.Triangulator; import com.sun.j3d.utils.universe.SimpleUniverse; public class GeomInfoApp extends Applet {

 float[] createCoordinateData() {
   float[] data = new float[69 * 3]; // ******
   int i = 0;
   data[i++] = -1.3f;
   data[i++] = -0.3f;
   data[i++] = 0.3f; //0
   data[i++] = -0.9f;
   data[i++] = -0.3f;
   data[i++] = 0.3f; //1
   data[i++] = -0.8f;
   data[i++] = -0.1f;
   data[i++] = 0.3f; //2
   data[i++] = -0.6f;
   data[i++] = -0.1f;
   data[i++] = 0.3f; //3
   data[i++] = -0.5f;
   data[i++] = -0.3f;
   data[i++] = 0.3f; //4
   data[i++] = 0.2f;
   data[i++] = -0.3f;
   data[i++] = 0.3f; //5
   data[i++] = 0.3f;
   data[i++] = -0.1f;
   data[i++] = 0.3f; //6
   data[i++] = 0.5f;
   data[i++] = -0.1f;
   data[i++] = 0.3f; //7
   data[i++] = 0.6f;
   data[i++] = -0.3f;
   data[i++] = 0.3f; //8
   data[i++] = 1.3f;
   data[i++] = -0.3f;
   data[i++] = 0.3f; //9
   data[i++] = 1.2f;
   data[i++] = -0.1f;
   data[i++] = 0.3f; //10
   data[i++] = 0.5f;
   data[i++] = 0.0f;
   data[i++] = 0.3f; //11
   data[i++] = 0.1f;
   data[i++] = 0.3f;
   data[i++] = 0.3f; //12
   data[i++] = -0.5f;
   data[i++] = 0.3f;
   data[i++] = 0.3f; //13
   data[i++] = -1.1f;
   data[i++] = 0.0f;
   data[i++] = 0.3f; //14
   data[i++] = -1.3f;
   data[i++] = 0.0f;
   data[i++] = 0.3f; //15
   data[i++] = -1.3f;
   data[i++] = -0.3f;
   data[i++] = 0.3f; //16
   System.out.println("end polygon; total vertex count: " + i / 3);
   data[i++] = -1.3f;
   data[i++] = -0.3f;
   data[i++] = -0.3f; // 0 17
   data[i++] = -1.3f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 1 18
   data[i++] = -1.1f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 2 19
   data[i++] = -0.5f;
   data[i++] = 0.3f;
   data[i++] = -0.3f; // 3 20
   data[i++] = 0.1f;
   data[i++] = 0.3f;
   data[i++] = -0.3f; // 4 21
   data[i++] = 0.5f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 5 22
   data[i++] = 1.2f;
   data[i++] = -0.1f;
   data[i++] = -0.3f; // 6 23
   data[i++] = 1.3f;
   data[i++] = -0.3f;
   data[i++] = -0.3f; // 7 24
   data[i++] = 0.6f;
   data[i++] = -0.3f;
   data[i++] = -0.3f; // 8 25
   data[i++] = 0.5f;
   data[i++] = -0.1f;
   data[i++] = -0.3f; // 9 26
   data[i++] = 0.3f;
   data[i++] = -0.1f;
   data[i++] = -0.3f; //10 27
   data[i++] = 0.2f;
   data[i++] = -0.3f;
   data[i++] = -0.3f; //11 28
   data[i++] = -0.5f;
   data[i++] = -0.3f;
   data[i++] = -0.3f; //12 29
   data[i++] = -0.6f;
   data[i++] = -0.1f;
   data[i++] = -0.3f; //13 30
   data[i++] = -0.8f;
   data[i++] = -0.1f;
   data[i++] = -0.3f; //14 31
   data[i++] = -0.9f;
   data[i++] = -0.3f;
   data[i++] = -0.3f; //15 32
   data[i++] = -1.3f;
   data[i++] = -0.3f;
   data[i++] = -0.3f; //16 33
   System.out.println("end polygon; total vertex count: " + i / 3);
   data[i++] = 1.3f;
   data[i++] = -0.3f;
   data[i++] = -0.3f; // 0 34
   data[i++] = 1.2f;
   data[i++] = -0.1f;
   data[i++] = -0.3f; // 1 35
   data[i++] = 1.2f;
   data[i++] = -0.1f;
   data[i++] = 0.3f; // 2 36
   data[i++] = 1.3f;
   data[i++] = -0.3f;
   data[i++] = 0.3f; // 3 37
   data[i++] = 1.3f;
   data[i++] = -0.3f;
   data[i++] = -0.3f; // 4 38
   System.out.println("end polygon; total vertex count: " + i / 3);
   data[i++] = 1.2f;
   data[i++] = -0.1f;
   data[i++] = -0.3f; // 0 39
   data[i++] = 0.5f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 1 40
   data[i++] = 0.5f;
   data[i++] = 0.0f;
   data[i++] = 0.3f; // 2 41
   data[i++] = 1.2f;
   data[i++] = -0.1f;
   data[i++] = 0.3f; // 3 42
   data[i++] = 1.2f;
   data[i++] = -0.1f;
   data[i++] = -0.3f; // 4 43
   System.out.println("end polygon; total vertex count: " + i / 3);
   data[i++] = 0.5f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 0 44
   data[i++] = 0.1f;
   data[i++] = 0.3f;
   data[i++] = -0.3f; // 1 45
   data[i++] = 0.1f;
   data[i++] = 0.3f;
   data[i++] = 0.3f; // 2 46
   data[i++] = 0.5f;
   data[i++] = 0.0f;
   data[i++] = 0.3f; // 3 47
   data[i++] = 0.5f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 4 48
   System.out.println("end polygon; total vertex count: " + i / 3);
   data[i++] = 0.1f;
   data[i++] = 0.3f;
   data[i++] = -0.3f; // 0 49
   data[i++] = -0.5f;
   data[i++] = 0.3f;
   data[i++] = -0.3f; // 1 50
   data[i++] = -0.5f;
   data[i++] = 0.3f;
   data[i++] = 0.3f; // 2 51
   data[i++] = 0.1f;
   data[i++] = 0.3f;
   data[i++] = 0.3f; // 3 52
   data[i++] = 0.1f;
   data[i++] = 0.3f;
   data[i++] = -0.3f; // 4 53
   System.out.println("end polygon; total vertex count: " + i / 3);
   data[i++] = -0.5f;
   data[i++] = 0.3f;
   data[i++] = -0.3f; // 0 54
   data[i++] = -1.1f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 1 55
   data[i++] = -1.1f;
   data[i++] = 0.0f;
   data[i++] = 0.3f; // 2 56
   data[i++] = -0.5f;
   data[i++] = 0.3f;
   data[i++] = 0.3f; // 3 57
   data[i++] = -0.5f;
   data[i++] = 0.3f;
   data[i++] = -0.3f; // 4 58
   System.out.println("end polygon; total vertex count: " + i / 3);
   data[i++] = -1.1f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 0 59
   data[i++] = -1.3f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 1 60
   data[i++] = -1.3f;
   data[i++] = 0.0f;
   data[i++] = 0.3f; // 2 61
   data[i++] = -1.1f;
   data[i++] = 0.0f;
   data[i++] = 0.3f; // 3 62
   data[i++] = -1.1f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 4 63
   System.out.println("end polygon; total vertex count: " + i / 3);
   data[i++] = -1.3f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 0 64
   data[i++] = -1.3f;
   data[i++] = -0.3f;
   data[i++] = -0.3f; // 1 65
   data[i++] = -1.3f;
   data[i++] = -0.3f;
   data[i++] = 0.3f; // 2 66
   data[i++] = -1.3f;
   data[i++] = 0.0f;
   data[i++] = 0.3f; // 3 67
   data[i++] = -1.3f;
   data[i++] = 0.0f;
   data[i++] = -0.3f; // 4 68
   System.out.println("end polygon; total vertex count: " + i / 3);
   // ****** This is the data for the hood, roof, trunk, front and rear
   // glass
   // ****** remove the comments markers below (slash-star) and (star
   // slash)
   // ****** and add the appropriate comment markers above.
   // ****** modification of other lines of code is necessary to use this
   // data
   // ****** one line above and two lines below
   /*
    * data[i++]= 1.3f; data[i++]= -0.3f; data[i++]=-0.3f; // 0 35
    * data[i++]= 1.2f; data[i++]= -0.1f; data[i++]=-0.3f; // 1 36
    * data[i++]= 0.5f; data[i++]= 0.0f; data[i++]=-0.3f; // 2 37 data[i++]=
    * 0.1f; data[i++]= 0.3f; data[i++]=-0.3f; // 3 38 data[i++]= -0.5f;
    * data[i++]= 0.3f; data[i++]=-0.3f; // 4 39 data[i++]= -1.1f;
    * data[i++]= 0.0f; data[i++]=-0.3f; // 5 40 data[i++]= -1.3f;
    * data[i++]= 0.0f; data[i++]=-0.3f; // 6 41 data[i++]= -1.3f;
    * data[i++]= -0.3f; data[i++]=-0.3f; // 7 42 data[i++]= -1.3f;
    * data[i++]= -0.3f; data[i++]= 0.3f; // 8 43 data[i++]= -1.3f;
    * data[i++]= 0.0f; data[i++]= 0.3f; // 9 44 data[i++]= -1.1f;
    * data[i++]= 0.0f; data[i++]= 0.3f; // 10 45 data[i++]= -0.5f;
    * data[i++]= 0.3f; data[i++]= 0.3f; // 11 46 data[i++]= 0.1f;
    * data[i++]= 0.3f; data[i++]= 0.3f; // 12 47 data[i++]= 0.5f;
    * data[i++]= 0.0f; data[i++]= 0.3f; // 13 48 data[i++]= 1.2f;
    * data[i++]= -0.1f; data[i++]= 0.3f; // 14 49 data[i++]= 1.3f;
    * data[i++]= -0.3f; data[i++]= 0.3f; // 15 50 data[i++]= 1.3f;
    * data[i++]= -0.3f; data[i++]=-0.3f; // 16 51 System.out.println("end
    * polygon; total vertex count: "+i/3);
    */
   // ****** end of the alternative polygon data
   return data;
 }
 Appearance createMaterialAppearance() {
   Appearance materialAppear = new Appearance();
   PolygonAttributes polyAttrib = new PolygonAttributes();
   polyAttrib.setCullFace(PolygonAttributes.CULL_NONE);
   materialAppear.setPolygonAttributes(polyAttrib);
   Material material = new Material();
   material.setDiffuseColor(new Color3f(1.0f, 0.0f, 0.0f));
   materialAppear.setMaterial(material);
   return materialAppear;
 }
 Appearance createWireFrameAppearance() {
   Appearance materialAppear = new Appearance();
   PolygonAttributes polyAttrib = new PolygonAttributes();
   polyAttrib.setPolygonMode(PolygonAttributes.POLYGON_LINE);
   materialAppear.setPolygonAttributes(polyAttrib);
   ColoringAttributes redColoring = new ColoringAttributes();
   redColoring.setColor(1.0f, 0.0f, 0.0f);
   materialAppear.setColoringAttributes(redColoring);
   return materialAppear;
 }
 /////////////////////////////////////////////////
 //
 // create scene graph branch group
 //
 public BranchGroup createSceneGraph(boolean wireFrame) {
   int total = 0;
   System.out.println("\n --- geometry debug information --- \n");
   float[] coordinateData = null;
   coordinateData = createCoordinateData();
   int[] stripCount = { 17, 17, 5, 5, 5, 5, 5, 5, 5 }; // ******
   //        int[] stripCount = {17,17,17}; // ******
   for (int i = 0; i < stripCount.length; i++) {
     System.out.println("stripCount[" + i + "] = " + stripCount[i]);
     total += stripCount[i];
   }
   if (total != coordinateData.length / 3) {
     System.out.println("  coordinateData vertex count: "
         + coordinateData.length / 3);
     System.out.println("stripCount total vertex count: " + total);
   }
   GeometryInfo gi = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
   gi.setCoordinates(coordinateData);
   gi.setStripCounts(stripCount);
   Triangulator tr = new Triangulator();
   //        Triangulator tr = new Triangulator(1);
   System.out.println("begin triangulation");
   tr.triangulate(gi);
   System.out.println("  END triangulation");
   gi.recomputeIndices();
   NormalGenerator ng = new NormalGenerator();
   ng.generateNormals(gi);
   gi.recomputeIndices();
   Stripifier st = new Stripifier();
   st.stripify(gi);
   gi.recomputeIndices();
   Shape3D part = new Shape3D();
   if (wireFrame == true)
     part.setAppearance(createWireFrameAppearance());
   else
     part.setAppearance(createMaterialAppearance());
   part.setGeometry(gi.getGeometryArray());
   /////////////////////////////
   BranchGroup contentRoot = new BranchGroup();
   // Create the transform group node and initialize it to the
   // identity. Add it to the root of the subgraph.
   TransformGroup objSpin = new TransformGroup();
   objSpin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   contentRoot.addChild(objSpin);
   objSpin.addChild(part);
   ////////////////////////
   LineStripArray lineArray = new LineStripArray(69,
       LineArray.COORDINATES, stripCount); //*****
   //        LineStripArray lineArray = new LineStripArray(51,
   // LineArray.COORDINATES, stripCount); //*****
   lineArray.setCoordinates(0, coordinateData);
   Appearance blueColorAppearance = new Appearance();
   ColoringAttributes blueColoring = new ColoringAttributes();
   blueColoring.setColor(0.0f, 0.0f, 1.0f);
   blueColorAppearance.setColoringAttributes(blueColoring);
   LineAttributes lineAttrib = new LineAttributes();
   lineAttrib.setLineWidth(2.0f);
   blueColorAppearance.setLineAttributes(lineAttrib);
   objSpin.addChild(new Shape3D(lineArray, blueColorAppearance));
   Alpha rotationAlpha = new Alpha(-1, 16000);
   RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
       objSpin);
   // a bounding sphere specifies a region a behavior is active
   // create a sphere centered at the origin with radius of 1
   BoundingSphere bounds = new BoundingSphere();
   rotator.setSchedulingBounds(bounds);
   objSpin.addChild(rotator);
   DirectionalLight lightD = new DirectionalLight();
   lightD.setDirection(new Vector3f(0.0f, -0.7f, -0.7f));
   lightD.setInfluencingBounds(bounds);
   contentRoot.addChild(lightD);
   AmbientLight lightA = new AmbientLight();
   lightA.setInfluencingBounds(bounds);
   contentRoot.addChild(lightA);
   Background background = new Background();
   background.setColor(1.0f, 1.0f, 1.0f);
   background.setApplicationBounds(bounds);
   contentRoot.addChild(background);
   // Let Java 3D perform optimizations on this scene graph.
   // contentRoot.rupile();
   return contentRoot;
 } // end of CreateSceneGraph method of MobiusApp
 // Create a simple scene and attach it to the virtual universe
 public GeomInfoApp(String[] args) {
   setLayout(new BorderLayout());
   Canvas3D canvas3D = new Canvas3D(null);
   add("Center", canvas3D);
   BranchGroup scene = createSceneGraph(args.length > 0);
   // 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 GeomInfoApp 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("GeomInfoApp - Java 3D API demo program\n");
   System.out.print("A demonstration of using the GeometryInfo class.\n");
   System.out.print("The blue lines show the input geometry - the red ");
   System.out
       .print("geometry was created by the GeometryInfo and other classes.\n");
   System.out
       .print("Running the program without any command line arguments will show a solid object\n");
   System.out
       .print("Supplying any command line argument will show the wireframe.\n");
   System.out.print("http://www.sun.ru/desktop/java3d\n");
   Frame frame = new MainFrame(new GeomInfoApp(args), 256, 256);
 } // end of main method of MobiusApp

} // end of class GeomInfoApp


      </source>
   
  
 
  



Twist Strip visual object

   <source lang="java">

/*

* LitTwistApp.java 1.0 99/02/19
* 
* Copyright (c) 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.
*/

/*

* LitTwistApp.java is intended to demonstrate lighting complex surfaces A Twist
* strip is a continuous surface with a complete twist in it. (As opposed to a
* half-twist which would make a Mobius Strip.) The Class Twist creates a
* surface using a TriangleStripArray. A Twist strip is placed in a scene graph
* with a RotationInterpolator so the strip spins.
* 
* One Twist strip is created using the inner class (Twist). This visual object
* is rendered as filled polygons.
* 
* This application (or a version of it) generated one or more of the images in
* Chapter 6 of Getting Started with the Java 3D API. The Java 3D Turtorial.
* 
* See http://www.sun.ru/desktop/java3d/collateral for more information.
*  
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.Alpha; 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.Geometry; import javax.media.j3d.Material; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Shape3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TriangleStripArray; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.universe.SimpleUniverse; public class LitTwistApp extends Applet {

 /////////////////////////////////////////////////
 //
 // create Twist Strip visual object
 //
 public class Twist extends Shape3D {
   ////////////////////////////////////////////
   //
   // create twisted strip subgraph
   //
   public Twist() {
     this.setGeometry(createGeometry());
     this.setAppearance(createAppearance());
   } // end of Twist constructor
   Geometry createGeometry() {
     TriangleStripArray twistStrip;
     Color3f blue = new Color3f(0.0f, 0.0f, 1.0f);
     // create triangle strip for Twist
     int N = 80;
     int stripCounts[] = { N };
     twistStrip = new TriangleStripArray(
         N,
         TriangleStripArray.COORDINATES | TriangleStripArray.NORMALS,
         stripCounts);
     double a;
     int v;
     Vector3f norm = new Vector3f();
     for (v = 0, a = 0.0; v < N; v += 2, a = v * 2.0 * Math.PI / (N - 2)) {
       twistStrip.setCoordinate(v, new Point3d(0.7 * Math.cos(a) + 0.2
           * Math.sin(a), -0.3 * Math.cos(a), 0.7 * Math.sin(a)
           + 0.2 * Math.sin(a)));
       twistStrip.setCoordinate(v + 1, new Point3d(0.7 * Math.cos(a)
           - 0.2 * Math.sin(a), 0.3 * Math.cos(a), 0.7
           * Math.sin(a) - 0.2 * Math.sin(a)));
       norm.set((float) (Math.abs(Math.cos(a))), (float) Math.abs(Math
           .sin(a)), (float) (Math.cos(a) * Math.sin(a)));
       norm.normalize();
       twistStrip.setNormal(v, norm);
       twistStrip.setNormal(v + 1, norm);
     }
     return twistStrip;
   }
   // create Appearance for Twist Strip
   //
   // this method creates the default Appearance for the
   // twist strip. The commented line of code containting
   // the setCullFace will fix the problem of half of the
   // Twist Strip disappearing.
   Appearance createAppearance() {
     Appearance twistAppear = new Appearance();
     PolygonAttributes polyAttrib = new PolygonAttributes();
     polyAttrib.setCullFace(PolygonAttributes.CULL_NONE);
     polyAttrib.setBackFaceNormalFlip(true);
     twistAppear.setPolygonAttributes(polyAttrib);
     Material material = new Material();
     twistAppear.setMaterial(material);
     return twistAppear;
   }
 } // end of class Twist
 /////////////////////////////////////////////////
 //
 // create scene graph branch group
 //
 public BranchGroup createSceneGraph() {
   BranchGroup contentRoot = new BranchGroup();
   // Create the transform group node and initialize it to the
   // identity. Add it to the root of the subgraph.
   TransformGroup objSpin = new TransformGroup();
   objSpin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   contentRoot.addChild(objSpin);
   Shape3D twist = new Twist();
   objSpin.addChild(twist);
   Alpha rotationAlpha = new Alpha(-1, 16000);
   RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
       objSpin);
   // a bounding sphere specifies a region a behavior is active
   // create a sphere centered at the origin with radius of 1.5
   BoundingSphere bounds = new BoundingSphere();
   bounds.setRadius(1.5);
   rotator.setSchedulingBounds(bounds);
   objSpin.addChild(rotator);
   DirectionalLight lightD = new DirectionalLight();
   lightD.setInfluencingBounds(bounds);
   contentRoot.addChild(lightD);
   Background background = new Background();
   background.setColor(1.0f, 1.0f, 1.0f);
   background.setApplicationBounds(bounds);
   contentRoot.addChild(background);
   // Let Java 3D perform optimizations on this scene graph.
   // contentRoot.rupile();
   return contentRoot;
 } // end of CreateSceneGraph method of LitTwistApp
 // Create a simple scene and attach it to the virtual universe
 public LitTwistApp() {
   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 LitTwistApp constructor
 //  The following allows this to be run as an application
 //  as well as an applet
 public static void main(String[] args) {
   System.out.println("LitTwistApp - Java 3D");
   System.out.println("A demonstration of lights.");
   Frame frame = new MainFrame(new LitTwistApp(), 256, 256);
 } // end of main method of TwistApp

} // end of class LitTwistApp


      </source>
   
  
 
  



VolRend

Yoyo Line

   <source lang="java">

/*

* YoyoLineApp.java 1.0 98/11/23
* 
* Copyright (c) 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.
*/

/*

* Getting Started with the Java 3D API written in Java 3D
* 
* YoyoLineApp.java demonstrates using Appearance attributes to display only the
* lines from a more complex geometry.
*/

import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import javax.media.j3d.Alpha; import javax.media.j3d.Appearance; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Geometry; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TriangleFanArray; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.universe.SimpleUniverse; public class YoyoLineApp extends Applet {

 /////////////////////////////////////////////////
 //
 // create scene graph branch group
 //
 public class Yoyo extends Shape3D {
   ////////////////////////////////////////////
   //
   // create Shape3D with geometry and appearance
   // the geometry is created in method yoyoGeometry
   // the appearance is created in method yoyoAppearance
   //
   public Yoyo() {
     this.setGeometry(yoyoGeometry());
     this.setAppearance(yoyoAppearance());
   } // end of Yoyo constructor
   ////////////////////////////////////////////
   //
   // create yoyo geometry
   // four triangle fans represent the yoyo
   // strip indicies_______________
   //   0 0N+0 to 1N+0 ( 0 to N )
   //   1 1N+1 to 2N+1
   //   2 2N+2 to 3N+2
   //   3 3N+4 to 4N+3
   //
   private Geometry yoyoGeometry() {
     TriangleFanArray tfa;
     int N = 17;
     int totalN = 4 * (N + 1);
     Point3f coords[] = new Point3f[totalN];
     int stripCounts[] = { N + 1, N + 1, N + 1, N + 1 };
     float r = 0.6f;
     float w = 0.4f;
     int n;
     double a;
     float x, y;
     // set the central points for four triangle fan strips
     coords[0 * (N + 1)] = new Point3f(0.0f, 0.0f, w);
     coords[1 * (N + 1)] = new Point3f(0.0f, 0.0f, 0.0f);
     coords[2 * (N + 1)] = new Point3f(0.0f, 0.0f, 0.0f);
     coords[3 * (N + 1)] = new Point3f(0.0f, 0.0f, -w);
     for (a = 0, n = 0; n < N; a = 2.0 * Math.PI / (N - 1) * ++n) {
       x = (float) (r * Math.cos(a));
       y = (float) (r * Math.sin(a));
       coords[0 * (N + 1) + n + 1] = new Point3f(x, y, w);
       coords[1 * (N + 1) + N - n] = new Point3f(x, y, w);
       coords[2 * (N + 1) + n + 1] = new Point3f(x, y, -w);
       coords[3 * (N + 1) + N - n] = new Point3f(x, y, -w);
     }
     tfa = new TriangleFanArray(totalN, TriangleFanArray.COORDINATES,
         stripCounts);
     tfa.setCoordinates(0, coords);
     return tfa;
   } // end of method yoyoGeometry in class Yoyo
   ////////////////////////////////////////////
   //
   // create yoyo appearance
   //
   private Appearance yoyoAppearance() {
     Appearance appearance = new Appearance();
     PolygonAttributes polyAttrib = new PolygonAttributes();
     polyAttrib.setPolygonMode(PolygonAttributes.POLYGON_LINE);
     appearance.setPolygonAttributes(polyAttrib);
     return appearance;
   } // end of method yoyoAppearance of class Yoyo
 } // end of class Yoyo
 /////////////////////////////////////////////////
 //
 // create scene graph branch group
 //
 public BranchGroup createSceneGraph() {
   BranchGroup objRoot = new BranchGroup();
   // 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 objSpin = new TransformGroup();
   objSpin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   objRoot.addChild(objSpin);
   objSpin.addChild(new Yoyo());
   // Create a new Behavior object that will perform the desired
   // operation on the specified transform object and add it into
   // the scene graph.
   Transform3D yAxis = new Transform3D();
   Alpha rotationAlpha = new Alpha(-1, 4000);
   RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
       objSpin);
   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
       100.0);
   rotator.setSchedulingBounds(bounds);
   objSpin.addChild(rotator);
   // Let Java 3D perform optimizations on this scene graph.
   objRoot.rupile();
   return objRoot;
 } // end of CreateSceneGraph method of YoyoLineApp
 // Create a simple scene and attach it to the virtual universe
 public YoyoLineApp() {
   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 YoyoLineApp constructor
 //  The following allows this to be run as an application
 //  as well as an applet
 public static void main(String[] args) {
   Frame frame = new MainFrame(new YoyoLineApp(), 256, 256);
 } // end of main method of YoyoLineApp

} // end of class YoyoLineApp


      </source>