

import javax.media.j3d.*;
import javax.vecmath.*;
import java.awt.*;
import java.awt.event.*;

public class Virtual6DOF implements InputDevice {

    private Vector3f position = new Vector3f();
    private Transform3D newTransform = new Transform3D();
    private TransformGroup outsideTG; 
    
    Sensor sensors[] = new Sensor[1];

    private int processingMode;
    private SensorRead sensorRead = new SensorRead();

    public Virtual6DOF() {
        processingMode = InputDevice.BLOCKING;
        sensors[0] = new Sensor(this);
    }
    //this constructor allows the 6DOF to control and outside
    //TransformGroup as in the such as the virtual head used
    //in the VirtualViewModel example
    
    public Virtual6DOF(TransformGroup outsideTG) {
        System.out.println("2nd constructor");
        this.outsideTG = outsideTG;
        processingMode = InputDevice.BLOCKING;
        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() );
      sensorRead.set(newTransform);
      sensors[0].setNextSensorRead(sensorRead);
      //update the virtual head here
      outsideTG.setTransform(newTransform);
     // System.out.println("newTransform: " + newTransform.toString());
     // System.out.println("pollAndProcessInput(): ");
     }

    public void processStreamInput() {
    }


    public void setNominalPositionAndOrientation() {

        sensorRead.setTime( System.currentTimeMillis() );
        sensorRead.set( new Transform3D());
        sensors[0].setNextSensorRead( sensorRead );
  
    }
 
public void setRotationX() {
        sensorRead.get(newTransform);
        Transform3D t = new Transform3D();
        t.rotX(Math.PI/36);
        newTransform.mul(t);
    }
    
    public void setRotationY() {
        sensorRead.get(newTransform);
        Transform3D t = new Transform3D();
        t.rotY(Math.PI/36);
        newTransform.mul(t);
    }
    
    public void setRotationZ() {
        sensorRead.get(newTransform);
        Transform3D t = new Transform3D();
        t.rotZ(Math.PI/36);
        newTransform.mul(t);
    } 
   
 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");
         }
    }

}
