Mega Code Archive

 
Categories / Java / 3D Graphics
 

Simple Universe

/*  * @(#)HelloUniverse.java 1.17 02/10/21 13:58:47  *   * 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.Button; import java.awt.Canvas; import java.awt.Color; import java.awt.Dimension; import java.awt.Frame; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GridLayout; import java.awt.Panel; import java.awt.Point; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.AffineTransform; import java.util.Enumeration; import javax.media.j3d.Alpha; import javax.media.j3d.Behavior; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.InputDevice; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Sensor; import javax.media.j3d.SensorRead; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.WakeupOnElapsedFrames; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.SimpleUniverse; public class HelloUniverse extends Applet {   private SimpleUniverse u = null;   public BranchGroup createSceneGraph() {     BranchGroup objRoot = new BranchGroup();     TransformGroup objTrans = new TransformGroup();     objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);     objRoot.addChild(objTrans);     objTrans.addChild(new ColorCube(0.2));     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);     BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),         100.0);     rotator.setSchedulingBounds(bounds);     objTrans.addChild(rotator);     return objRoot;   }   public HelloUniverse() {   }   public void init() {     // These are the string arguments given to the VirtualInputDevice     // constructor. These are settable parameters. Look in the     // VirtualInputDevice constructor for a complete list.     String[] args = new String[10];     args[0] = "printvalues";     args[1] = "true";     args[2] = "yscreeninitloc";     args[3] = "50";     args[4] = null;     InputDevice device = new VirtualInputDevice(args);     // now create the HelloUniverse Canvas     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);     // The InputDevice must be initialized before registering it     // with the PhysicalEnvironment object.     device.initialize();     // Register the VirtualInputDevice with Java 3D     u.getViewer().getPhysicalEnvironment().addInputDevice(device);     TransformGroup viewTrans = u.getViewingPlatform()         .getViewPlatformTransform();     SensorBehavior s = new SensorBehavior(viewTrans, device.getSensor(0));     s.setSchedulingBounds(new BoundingSphere(new Point3d(0.0, 0.0, 0.0),         Float.MAX_VALUE));     scene.addChild(s);     u.addBranchGraph(scene);   }   public void destroy() {     u.cleanup();   }   public static void main(String[] args) {     new MainFrame(new HelloUniverse(), 350, 350);   } } class VirtualInputDevice implements InputDevice {   private Vector3f position = new Vector3f();   private Transform3D newTransform = new Transform3D();   Sensor sensors[] = new Sensor[1];   // The wheel controls control the view platform orientation   private RotationControls rotControls;   // The button position controls control the view platform position   private PositionControls positionControls;   private Transform3D rotTransX = new Transform3D();   private Transform3D rotTransY = new Transform3D();   private Transform3D rotTransZ = new Transform3D();   private Vector3f initPos = new Vector3f();   private int processingMode;   private SensorRead sensorRead = new SensorRead();   // These are the settable parameters.   private boolean printvalues;   private int xscreeninitloc;   private int yscreeninitloc;   private int xscreensize;   private int yscreensize;   private float xobjinitloc;   private float yobjinitloc;   private float zobjinitloc;   private float xaxisrotinit;   private float yaxisrotinit;   private float zaxisrotinit;   /*    * Create a device, and use the string arguments in args to construct the    * device with user preferences.    */   public VirtualInputDevice(String[] args) {     // default user-definable values     printvalues = false;     xscreeninitloc = 400;     yscreeninitloc = 0;     xscreensize = 400;     yscreensize = 200;     xobjinitloc = 0.0f;     yobjinitloc = 0.0f;     zobjinitloc = 2.2f;     xaxisrotinit = 0.0f;     yaxisrotinit = 0.0f;     zaxisrotinit = 0.0f;     for (int i = 0; i < args.length; i += 2) {       if (args[i] == null)         break;       else if (args[i] == "printvalues")         printvalues = (Boolean.valueOf(args[i + 1])).booleanValue();       else if (args[i] == "xscreeninitloc")         xscreeninitloc = (Integer.valueOf(args[i + 1])).intValue();       else if (args[i] == "yscreeninitloc")         yscreeninitloc = (Integer.valueOf(args[i + 1])).intValue();       else if (args[i] == "xscreensize")         xscreensize = (Integer.valueOf(args[i + 1])).intValue();       else if (args[i] == "yscreensize")         yscreensize = (Integer.valueOf(args[i + 1])).intValue();       else if (args[i] == "xobjinitloc")         xobjinitloc = (Float.valueOf(args[i + 1])).floatValue();       else if (args[i] == "yobjinitloc")         yobjinitloc = (Float.valueOf(args[i + 1])).floatValue();       else if (args[i] == "zobjinitloc")         zobjinitloc = (Integer.valueOf(args[i + 1])).floatValue();     }     if (printvalues == true) {       System.out.println("Initial values for VirtualInputDevice:");       System.out.println("xscreeninitloc = " + xscreeninitloc);       System.out.println("yscreeninitloc = " + yscreeninitloc);       System.out.println("xscreeninitsize = " + xscreensize);       System.out.println("yscreeninitsize = " + yscreensize);       System.out.println("xobjinitloc = " + xobjinitloc);       System.out.println("yobjinitloc = " + yobjinitloc);       System.out.println("zobjinitloc = " + zobjinitloc);       System.out.println("xaxisrotinit = " + xaxisrotinit);       System.out.println("yaxisrotinit = " + yaxisrotinit);       System.out.println("zaxisrotinit = " + zaxisrotinit);     }     // initialize the InputDevice GUI     Frame deviceFrame = new Frame();     deviceFrame.setSize(xscreensize, yscreensize);     deviceFrame.setLocation(xscreeninitloc, yscreeninitloc);     deviceFrame.setTitle("Virtual Input Device");     ButtonPositionControls positionControls;     // initialize position with initial x, y, and z position     positionControls = new ButtonPositionControls(xobjinitloc, yobjinitloc,         zobjinitloc);     WheelControls rotControls;     // initialize rotations with initial angles in radians)     rotControls = new WheelControls(xaxisrotinit, yaxisrotinit,         zaxisrotinit);     positionControls.setDevice(this);     Panel devicePanel = new Panel();     devicePanel.setLayout(new BorderLayout());     devicePanel.add("East", positionControls);     devicePanel.add("West", rotControls);     deviceFrame.add(devicePanel);     deviceFrame.pack();     deviceFrame.setVisible(true);     initPos.set(xobjinitloc, yobjinitloc, zobjinitloc);     this.positionControls = positionControls;     this.rotControls = rotControls;     // default processing mode     processingMode = InputDevice.DEMAND_DRIVEN;     sensors[0] = new Sensor(this);   }   public void close() {   }   public int getProcessingMode() {     return processingMode;   }   public int getSensorCount() {     return sensors.length;   }   public Sensor getSensor(int sensorIndex) {     return sensors[sensorIndex];   }   public boolean initialize() {     return true;   }   public void pollAndProcessInput() {     sensorRead.setTime(System.currentTimeMillis());     rotTransX.rotX(-rotControls.getXAngle());     rotTransY.rotY(-rotControls.getYAngle());     rotTransZ.rotZ(-rotControls.getZAngle());     positionControls.getPosition(position);     newTransform.set(position);     newTransform.mul(rotTransX);     newTransform.mul(rotTransY);     newTransform.mul(rotTransZ);     sensorRead.set(newTransform);     sensors[0].setNextSensorRead(sensorRead);   }   public void processStreamInput() {   }   public void setNominalPositionAndOrientation() {     sensorRead.setTime(System.currentTimeMillis());     rotTransX.rotX(xaxisrotinit);     rotTransY.rotY(yaxisrotinit);     rotTransZ.rotZ(zaxisrotinit);     position.set(initPos);     newTransform.set(position);     newTransform.mul(rotTransX);     newTransform.mul(rotTransY);     newTransform.mul(rotTransZ);     sensorRead.set(newTransform);     sensors[0].setNextSensorRead(sensorRead);     rotControls.reset();     positionControls.setPosition(initPos);   }   public void setProcessingMode(int mode) {     // A typical driver might implement only one of these modes, and     // throw an exception when there is an attempt to switch modes.     // However, this example allows one to use any processing mode.     switch (mode) {     case InputDevice.DEMAND_DRIVEN:     case InputDevice.NON_BLOCKING:     case InputDevice.BLOCKING:       processingMode = mode;       break;     default:       throw new IllegalArgumentException("Processing mode must "           + "be one of DEMAND_DRIVEN, NON_BLOCKING, or BLOCKING");     }   } } class SensorBehavior extends Behavior {   private WakeupOnElapsedFrames conditions = new WakeupOnElapsedFrames(0);   private TransformGroup transformGroup;   private Sensor sensor;   private Transform3D transform = new Transform3D();   public SensorBehavior(TransformGroup tg, Sensor sensor) {     transformGroup = tg;     this.sensor = sensor;   }   public void initialize() {     wakeupOn(conditions);   }   public void processStimulus(Enumeration criteria) {     sensor.getRead(transform);     transformGroup.setTransform(transform);     wakeupOn(conditions);   } } //Classes that implement this interface must be a //subclass of java.awt.Component interface PositionControls {   /**    * Get the position    */   public void getPosition(Vector3f pos);   /**    * Set the position    */   public void setPosition(Vector3f pos);   /**    * Increment added to position each time mouse is pressed or if the mouse is    * held down each time the Sensor is read    */   public void setStepRate(float stepRate); } //Classes that implement this interface must be a subclass //of java.awt.Component interface RotationControls {   /**    * Get the angle of Rotation around the X Axis    */   public abstract float getXAngle();   /**    * Get the angle or Rotation around the Y Axis    */   public abstract float getYAngle();   /**    * Get the angle or Rotation around the Z Axis    */   public abstract float getZAngle();   /**    * Reset angles to original angle.    */   public abstract void reset(); } class WheelControls extends Canvas implements RotationControls,     MouseMotionListener, MouseListener {   private final static int NONE = 0;   private final static int SLIDE_Y = 1;   private final static int SLIDE_X = 2;   private final static int SLIDE_Z = 3;   private int mode = NONE;   private Dimension size;   private int thickness;   private int diameter;   private int space;   private int pipSize;   private int pipOffset; // Amount pip is below wheel   private int margin; // Margin between edge of Canvas and   // controls   private Polygon yPip;   private Rectangle yBackClip;   private Polygon xPip;   private Rectangle xBackClip;   private Polygon zPip;   private Rectangle yArea;   private Rectangle xArea;   private Rectangle zArea;   private Point oldMousePos = new Point();   float yAngle = 0.0f;   float xAngle = 0.0f;   float zAngle = 0.0f;   float yOrigAngle;   float xOrigAngle;   float zOrigAngle;   float angleStep = (float) Math.PI / 30.0f;   public WheelControls() {     this(0.0f, 0.0f, 0.0f);   }   public WheelControls(float rotX, float rotY, float rotZ) {     size = new Dimension(200, 200);     xAngle = constrainAngle(rotX);     yAngle = constrainAngle(rotY);     zAngle = constrainAngle(rotZ);     yOrigAngle = yAngle;     xOrigAngle = xAngle;     zOrigAngle = zAngle;     setSizes();     yPip = new Polygon();     yPip.addPoint(0, 0);     yPip.addPoint(-pipSize / 2, pipSize);     yPip.addPoint(pipSize / 2, pipSize);     xPip = new Polygon();     xPip.addPoint(0, 0);     xPip.addPoint(pipSize, -pipSize / 2);     xPip.addPoint(pipSize, pipSize / 2);     zPip = new Polygon();     zPip.addPoint(diameter / 2, pipOffset);     zPip.addPoint(diameter / 2 - pipSize / 2, pipOffset - pipSize);     zPip.addPoint(diameter / 2 + pipSize / 2, pipOffset - pipSize);     addMouseListener(this);     addMouseMotionListener(this);   }   private void setSizes() {     margin = 10;     int width = size.width - margin * 2;     thickness = width * 7 / 100;     diameter = width * 70 / 100;     space = width * 10 / 100;     pipSize = width * 7 / 100;     pipOffset = thickness / 2;   }   public void paint(Graphics g) {     Graphics2D g2 = (Graphics2D) g;     g.drawOval(margin, margin, diameter, diameter);     zArea = new Rectangle(margin, margin, diameter, diameter);     drawZPip(g2, zAngle);     g.drawRect(margin, margin + diameter + space, diameter, thickness); // Y                                       // Wheel     yArea = new Rectangle(margin, margin + diameter + space, margin         + diameter, thickness + pipOffset);     yBackClip = new Rectangle(margin - thickness, margin + diameter + space         + thickness, margin + diameter + thickness * 2, thickness);     drawYPip(g2, yAngle);     g.drawRect(margin + diameter + space, margin, thickness, diameter); // X                                       // Wheel     xArea = new Rectangle(margin + diameter + space, margin, thickness         + pipOffset, margin + diameter);     xBackClip = new Rectangle(margin + diameter + space + thickness, margin         - thickness, thickness, margin + diameter + thickness * 2);     drawXPip(g2, xAngle);   }   public float getXAngle() {     return xAngle;   }   public float getYAngle() {     return yAngle;   }   public float getZAngle() {     return zAngle;   }   public void reset() {     // Overwrite the old pip     drawYPip((Graphics2D) (this.getGraphics()), yAngle);     yAngle = yOrigAngle;     // Draw the new Pip     drawYPip((Graphics2D) (this.getGraphics()), yAngle);     // Overwrite the old pip     drawXPip((Graphics2D) (this.getGraphics()), xAngle);     xAngle = xOrigAngle;     // Draw the new Pip     drawXPip((Graphics2D) (this.getGraphics()), xAngle);     drawZPip((Graphics2D) (this.getGraphics()), zAngle);     zAngle = zOrigAngle;     drawZPip((Graphics2D) (this.getGraphics()), zAngle);     oldMousePos.setLocation(0, 0);   }   private void drawXPip(Graphics2D g2, float angle) {     AffineTransform trans = new AffineTransform();     int y;     int xOrig = margin + diameter + space;     int yOrig = margin;     Color origColor = g2.getColor();     if (angle <= Math.PI) {       y = yOrig           + diameter           - (int) ((Math.abs(angle - Math.PI / 2) / (Math.PI / 2))               * diameter / 2);     } else       y = yOrig           + (int) ((Math.abs((angle - Math.PI * 1.5)) / (Math.PI / 2))               * diameter / 2);     if (angle < Math.PI / 2 || angle > Math.PI * 1.5)       g2.setColor(Color.red); // Infront of wheel     else {       g2.setColor(Color.black); // Behind Wheel       g2.setClip(xBackClip);     }     g2.setXORMode(getBackground());     trans.setToTranslation(xOrig + pipOffset, y);     g2.setTransform(trans);     g2.fillPolygon(xPip);     // Reset graphics context     trans.setToIdentity();     g2.setTransform(trans);     g2.setColor(origColor);     g2.setPaintMode();   }   private void drawYPip(Graphics2D g2, float angle) {     AffineTransform trans = new AffineTransform();     int x;     int xOrig = margin;     int yOrig = margin + diameter + space;     Color origColor = g2.getColor();     if (angle <= Math.PI) {       x = xOrig           + diameter           - (int) ((Math.abs(angle - Math.PI / 2) / (Math.PI / 2))               * diameter / 2);     } else       x = xOrig           + (int) ((Math.abs((angle - Math.PI * 1.5)) / (Math.PI / 2))               * diameter / 2);     if (angle < Math.PI / 2 || angle > Math.PI * 1.5)       g2.setColor(Color.red); // Infront on wheel     else {       g2.setColor(Color.black); // Behind Wheel       g2.setClip(yBackClip);     }     g2.setXORMode(getBackground());     trans.setToTranslation(x, yOrig + pipOffset);     g2.setTransform(trans);     g2.fillPolygon(yPip);     // Reset graphics context     trans.setToIdentity();     g2.setTransform(trans);     g2.setColor(origColor);     g2.setPaintMode();   }   private void drawZPip(Graphics2D g2, float zAngle) {     AffineTransform trans = new AffineTransform();     Color origColor = g2.getColor();     trans.translate(margin, margin);     trans.rotate(zAngle, diameter / 2, diameter / 2);     g2.setXORMode(getBackground());     g2.setTransform(trans);     g2.setColor(Color.red);     g2.fillPolygon(zPip);     // Reset graphics context     trans.setToIdentity();     g2.setTransform(trans);     g2.setColor(origColor);     g2.setPaintMode();   }   public Dimension getPreferredSize() {     return size;   }   public void setSize(Dimension d) {     // Set size to smallest dimension     if (d.width < d.height)       size.width = size.height = d.width;     else       size.width = size.height = d.height;     setSizes();   }   public void mouseClicked(MouseEvent e) {   }   public void mouseEntered(MouseEvent e) {   }   public void mouseExited(MouseEvent e) {   }   public void mousePressed(MouseEvent e) {     if (yArea.contains(e.getPoint())) {       mode = SLIDE_Y;       oldMousePos = e.getPoint();     } else if (xArea.contains(e.getPoint())) {       mode = SLIDE_X;       oldMousePos = e.getPoint();     } else if (zArea.contains(e.getPoint())) {       mode = SLIDE_Z;       oldMousePos = e.getPoint();     }   }   public void mouseReleased(MouseEvent e) {     mode = NONE;   }   public void mouseDragged(MouseEvent e) {     Point pos = e.getPoint();     int diffX = pos.x - oldMousePos.x;     int diffY = pos.y - oldMousePos.y;     switch (mode) {     case NONE:       break;     case SLIDE_Y:       // Overwrite the old pip       drawYPip((Graphics2D) ((Canvas) e.getSource()).getGraphics(),           yAngle);       if (diffX < 0)         yAngle -= angleStep;       else if (diffX > 0)         yAngle += angleStep;       yAngle = constrainAngle(yAngle);       // Draw the new Pip       drawYPip((Graphics2D) ((Canvas) e.getSource()).getGraphics(),           yAngle);       oldMousePos = pos;       break;     case SLIDE_X:       // Overwrite the old pip       drawXPip((Graphics2D) ((Canvas) e.getSource()).getGraphics(),           xAngle);       if (diffY < 0)         xAngle -= angleStep;       else if (diffY > 0)         xAngle += angleStep;       xAngle = constrainAngle(xAngle);       // Draw the new Pip       drawXPip((Graphics2D) ((Canvas) e.getSource()).getGraphics(),           xAngle);       oldMousePos = pos;       break;     case SLIDE_Z:       drawZPip((Graphics2D) ((Canvas) e.getSource()).getGraphics(),           zAngle);       if (diffX < 0)         zAngle -= angleStep;       else if (diffX > 0)         zAngle += angleStep;       zAngle = constrainAngle(zAngle);       drawZPip((Graphics2D) ((Canvas) e.getSource()).getGraphics(),           zAngle);       oldMousePos = pos;       break;     default:       throw (new RuntimeException("Internal Error"));     }   }   public void mouseMoved(MouseEvent e) {   }   /**    * Constrain angle to be 0 <angle <2PI    */   private float constrainAngle(float angle) {     if (angle > (float) Math.PI * 2)       return angle - (float) Math.PI * 2;     if (angle < 0.0f)       return angle + (float) Math.PI * 2;     return angle;   } } class ButtonPositionControls extends Panel implements PositionControls,     MouseListener {   private final static int STILL = 0;   private final static int MOVING_UP = 1;   private final static int MOVING_DOWN = 2;   private final static int MOVING_LEFT = 3;   private final static int MOVING_RIGHT = 4;   private final static int MOVING_FORWARD = 5;   private final static int MOVING_BACK = 6;   // initial mode   private int mode = STILL;   Vector3f position = new Vector3f();   Vector3f orig_position = new Vector3f();   private Button leftB = new Button("Move Left");   private Button rightB = new Button("Move Right");   private Button upB = new Button("Move Up");   private Button downB = new Button("Move Down");   private Button forwardB = new Button("Move Forward");   private Button backwardB = new Button("Move Back");   private Button reset = new Button("Reset");   private InputDevice device;   private float step_rate = 0.0023f; // movement rate per millisecond   private long time_last_state_change = System.currentTimeMillis();   // the constructor arguments are the intitial X, Y, and Z positions   public ButtonPositionControls(float x, float y, float z) {     // up, down, right, and left movement buttons     Panel panPanel = new Panel();     panPanel.setLayout(new BorderLayout());     panPanel.add("North", upB);     panPanel.add("East", rightB);     panPanel.add("South", downB);     panPanel.add("West", leftB);     // forward, backward, and reset buttons     Panel p = new Panel();     p.setLayout(new GridLayout(0, 1, 0, 0));     p.add(forwardB);     p.add(backwardB);     p.add(reset);     // set the initial position     position.x = x;     position.y = y;     position.z = z;     orig_position.set(position);     // add a mouse listener to each button     upB.addMouseListener(this);     downB.addMouseListener(this);     leftB.addMouseListener(this);     rightB.addMouseListener(this);     forwardB.addMouseListener(this);     backwardB.addMouseListener(this);     reset.addMouseListener(this);     this.setLayout(new BorderLayout());     add("East", p);     add("West", panPanel);   }   public void setDevice(InputDevice device) {     this.device = device;   }   public void getPosition(Vector3f pos) {     calculateMotion();     pos.set(position);   }   public void setPosition(Vector3f pos) {     position.set(pos);   }   public void setStepRate(float stepRate) {     step_rate = stepRate;   }   private void calculateMotion() {     long current_time = System.currentTimeMillis();     long elapsed_time = current_time - time_last_state_change;     switch (mode) {     case STILL:       break;     case MOVING_LEFT:       position.x = orig_position.x - step_rate * elapsed_time;       break;     case MOVING_RIGHT:       position.x = orig_position.x + step_rate * elapsed_time;       break;     case MOVING_UP:       position.y = orig_position.y + step_rate * elapsed_time;       break;     case MOVING_DOWN:       position.y = orig_position.y - step_rate * elapsed_time;       break;     case MOVING_FORWARD:       position.z = orig_position.z - step_rate * elapsed_time;       break;     case MOVING_BACK:       position.z = orig_position.z + step_rate * elapsed_time;       break;     default:       throw (new RuntimeException("Unknown motion"));     }   }   public void mouseClicked(MouseEvent e) {   }   public void mouseEntered(MouseEvent e) {   }   public void mouseExited(MouseEvent e) {   }   public void mousePressed(MouseEvent e) {     if (e.getSource() == leftB && mode != MOVING_LEFT) {       time_last_state_change = System.currentTimeMillis();       mode = MOVING_LEFT;       orig_position.set(position);     } else if (e.getSource() == rightB && mode != MOVING_RIGHT) {       time_last_state_change = System.currentTimeMillis();       mode = MOVING_RIGHT;       orig_position.set(position);     } else if (e.getSource() == upB && mode != MOVING_UP) {       time_last_state_change = System.currentTimeMillis();       mode = MOVING_UP;       orig_position.set(position);     } else if (e.getSource() == downB && mode != MOVING_DOWN) {       time_last_state_change = System.currentTimeMillis();       mode = MOVING_DOWN;       orig_position.set(position);     } else if (e.getSource() == forwardB && mode != MOVING_FORWARD) {       time_last_state_change = System.currentTimeMillis();       mode = MOVING_FORWARD;       orig_position.set(position);     } else if (e.getSource() == backwardB && mode != MOVING_BACK) {       time_last_state_change = System.currentTimeMillis();       mode = MOVING_BACK;       orig_position.set(position);     } else if (e.getSource() == reset) {       device.setNominalPositionAndOrientation();     }   }   public void mouseReleased(MouseEvent e) {     mode = STILL;   } }