javax.media.j3d.Sensor Maven / Gradle / Ivy
Show all versions of java3d-core Show documentation
/*
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package javax.media.j3d;
import javax.vecmath.Matrix3d;
import javax.vecmath.Point3d;
/**
* The Sensor Class encapsulates an object that provides real-time
* data. Examples include six-degree-of-freedom tracking, a joystick,
* or a data file being read back during a program. A sensor must be
* used in conjuction with an implementation of the InputDevice
* interface.
*
* The Sensor object provides an abstract concept of a hardware
* input device. A Sensor consists of a timestamped sequence of
* input values and the state of buttons or switches at the time
* that Java 3D sampled the value. A sensor also contains a hotspot
* offset specified in the sensor's local coordinate system. If not
* specified, the hotspot is (0.0, 0.0, 0.0).
*
* Since a typical hardware environment may contain multiple sensing
* elements, Java 3D maintains an array of sensors. Users can access
* a sensor directly from their Java code or they can assign a sensor
* to one of Java 3D's predefined 6DOF entities, such as UserHead.
*
* Using a sensor is as easy as accessing an object. Write your
* Java code to extract the associated sensor value from the array of
* sensors. You can then directly apply that value to an element in a
* scene graph or process the sensor values in whatever way necessary.
*
* Java 3D includes three special six-degrees-of-freedom (6DOF) entities.
* These include UserHead, DominantHand, and NondominantHand. You
* can assign or change which sensor drives one
* of these predefined entities. Java 3D uses the specified sensor to
* drive the 6DOF entity - most visibly the View.
*
* Java 3D does not provide raw tracker or joystick-generated data in
* a sensor. At a minimum, Java 3D normalizes the raw data using the
* registration and calibration parameters either provided by or
* provided for the end user. It additionally may filter and process
* the data to remove noise and improve latency.
* The application programmer can suppress this latter effect on a
* sensor-by-sensor basis.
*
* @see SensorRead
*/
public class Sensor {
/**
* Set predictor type to do no prediction; this is the default.
*
* @deprecated As of Java 3D version 1.4, prediction is not a
* supported feature.
*/
public static final int PREDICT_NONE = 1;
/**
* @deprecated As of Java 3D version 1.4, prediction is not a
* supported feature.
*/
public static final int PREDICT_NEXT_FRAME_TIME = 2;
/**
* Use no prediction policy; this is the default.
*
* @deprecated As of Java 3D version 1.4, prediction is not a
* supported feature.
*/
public static final int NO_PREDICTOR = 16;
/**
* @deprecated As of Java 3D version 1.4, prediction is not a
* supported feature.
*/
public static final int HEAD_PREDICTOR = 32;
/**
* @deprecated As of Java 3D version 1.4, prediction is not a
* supported feature.
*/
public static final int HAND_PREDICTOR = 64;
/**
* Default SensorRead object count (30); the number of SensorRead
* objects constructed if no count is specified.
*/
public static final int DEFAULT_SENSOR_READ_COUNT = 30;
/**
* SENSOR_READ_COUNT_BUFFER is the number of extra sensor reading
* values to store at the end of the circular list. It helps provide
* MT-safeness. This is necessary if someone asks for the last
* k sensor values and k is close to sensor read count.
* This helps avoid some synchronization statements in getRead
* and setNextSensorRead.
*/
static final int SENSOR_READ_COUNT_BUFFER = 15;
static int num_reads_so_far = 0;
// specifies whether a DEMAND_DRIVEN device has been added that
// manages this sensor
boolean demand_driven = false;
// size of the sensor read buffer
int sensorReadCount;
// Prediction policy -- unused
private int predictionPolicy = NO_PREDICTOR;
// Predictor type -- unused
private int predictorType = PREDICT_NONE;
// This sensor's associated device
InputDevice device;
SensorRead readings[];
int currentIndex;
int lastIndex;
Point3d hotspot;
int MaxSensorReadIndex;
// The count of the number of buttons associated with this sensor.
int sensorButtonCount;
// These matrices used as a temporary workspace for the local SVD
// calculations (thus minimimizing garbage collection).
Matrix3d orig_rot = new Matrix3d();
Matrix3d orig_rot_transpose = new Matrix3d();
Matrix3d temp_rot = new Matrix3d();
Matrix3d local_svd = new Matrix3d();
/**
* Constructs a Sensor object for the specified input device using
* default parameters. The default values are as follows:
*
* sensor read count : 30
* sensor button count : 0
* hot spot : (0,0,0)
* predictor : PREDICT_NONE — this attribute is unused
* prediction policy : NO_PREDICTOR — this attribute is unused
*
* @param device the Sensor's associated device.
*/
public Sensor(InputDevice device){
this(device, DEFAULT_SENSOR_READ_COUNT, 0, new Point3d(0.0, 0.0, 0.0));
}
/**
* Constructs a Sensor object for the specified input device using
* the specified number of SensorRead objects.
* Default values are used for all other parameters.
* @param device the Sensor's associated device
* @param sensorReadCount the number of SensorReads to associate with
* this sensor
*/
public Sensor(InputDevice device, int sensorReadCount){
this(device, sensorReadCount, 0, new Point3d(0.0, 0.0, 0.0));
}
/**
* Constructs a Sensor object for the specified input device using
* the specified number of SensorRead objects and number of buttons.
* Default values are used for all other parameters.
* @param device the Sensor's associated device
* @param sensorReadCount the number of SensorReads to associate with
* this sensor
* @param sensorButtonCount the number of buttons associated with each
* sensor read
*/
public Sensor(InputDevice device, int sensorReadCount,
int sensorButtonCount){
this(device, sensorReadCount, sensorButtonCount,
new Point3d(0.0,0.0, 0.0));
}
/**
* Constructs a Sensor object for the specified input device using
* the specified hotspot.
* Default values are used for all other parameters.
* @param device the Sensor's associated device
* @param hotspot the Sensor's hotspot defined in its local coordinate
* system
*/
public Sensor(InputDevice device, Point3d hotspot){
this(device, DEFAULT_SENSOR_READ_COUNT, 0, hotspot);
}
/**
* Constructs a Sensor object for the specified input device using
* the specified number of SensorRead objects and hotspot.
* Default values are used for all other parameters.
* @param device the Sensor's associated device
* @param sensorReadCount the number of SensorReads to associate with
* this sensor
* @param hotspot the Sensor's hotspot defined in its local coordinate
* system
*/
public Sensor(InputDevice device, int sensorReadCount, Point3d hotspot){
this(device, sensorReadCount, 0, hotspot);
}
/**
* Constructs a Sensor object for the specified input device using
* the specified number of SensorRead objects, number of buttons, and
* hotspot.
* Default values are used for all other parameters.
* @param device the Sensor's associated device
* @param sensorReadCount the number of SensorReads to associate with
* this sensor
* @param sensorButtonCount the number of buttons associated with each
* sensor read
* @param hotspot the Sensor's hotspot defined in its local coordinate
* system
*/
public Sensor(InputDevice device, int sensorReadCount,
int sensorButtonCount, Point3d hotspot){
this.device = device;
this.sensorReadCount = sensorReadCount;
this.MaxSensorReadIndex = sensorReadCount + SENSOR_READ_COUNT_BUFFER - 1;
this.sensorButtonCount = sensorButtonCount;
readings = new SensorRead[MaxSensorReadIndex + 1];
for(int i = 0; i < MaxSensorReadIndex + 1; i++){
readings[i] = new SensorRead(sensorButtonCount);
}
currentIndex = 0;
this.hotspot = new Point3d(hotspot);
}
// argument of 0 is last reading (ie, currentIndex), argument
// of 1 means next to last index, etc.
int previousIndex(int k){
int temp = currentIndex - k;
return(temp >= 0 ? temp : MaxSensorReadIndex + temp + 1);
}
/**
* Sets the type of predictor to use with this sensor.
* Since prediction is not implemented (and never has been), this
* attribute has no effect.
* @param predictor predictor type one of PREDICT_NONE or
* PREDICT_NEXT_FRAME_TIME
* @exception IllegalArgumentException if an invalid predictor type
* is specified.
*
* @deprecated As of Java 3D version 1.4, prediction is not a
* supported feature.
*/
public void setPredictor(int predictor){
if (predictor != PREDICT_NONE && predictor != PREDICT_NEXT_FRAME_TIME) {
throw new IllegalArgumentException(J3dI18N.getString("Sensor0"));
} else {
predictorType = predictor;
}
}
/**
* Returns the type of predictor used by this sensor.
* @return the predictor type.
*
* @deprecated As of Java 3D version 1.4, prediction is not a
* supported feature.
*/
public int getPredictor(){
return predictorType;
}
/**
* Sets the prediction policy use by this sensor.
* Since prediction is not implemented (and never has been), this
* attribute has no effect.
* @param policy prediction policy one of NO_PREDICTOR, HEAD_PREDICTOR,
* or HAND_PREDICTOR
* @exception IllegalArgumentException if an invalid prediction policy
* is specified.
*
* @deprecated As of Java 3D version 1.4, prediction is not a
* supported feature.
*/
public void setPredictionPolicy(int policy){
if (policy != NO_PREDICTOR && policy != HEAD_PREDICTOR &&
policy != HAND_PREDICTOR)
throw new IllegalArgumentException(J3dI18N.getString("Sensor1"));
else
predictionPolicy = policy;
}
/**
* Returns the prediction policy used by this sensor.
* @return the prediction policy.
*
* @deprecated As of Java 3D version 1.4, prediction is not a
* supported feature.
*/
public int getPredictionPolicy(){
return predictionPolicy;
}
/**
* Set the sensor's hotspot in this sensor's coordinate system.
* @param hotspot the sensor's new hotspot
*/
public void setHotspot(Point3d hotspot){
this.hotspot.set(hotspot);
}
/**
* Get the sensor's hotspot in this sensor's coordinate system.
* @param hotspot the variable to receive the sensor's hotspot
*/
public void getHotspot(Point3d hotspot){
hotspot.set(this.hotspot);
}
/**
* Set the sensor's associated input device.
* @param device the sensor's new device
*/
public void setDevice(InputDevice device){
this.device = device;
}
/**
* Retrieves the sensor's associated input device.
* @return the sensor's device
*/
public InputDevice getDevice(){
return device;
}
/**
* Retrieves the last sensor reading and copies that value into
* the specified argument.
*
* @param read the matrix that will receive the sensor reading
*/
public void getRead(Transform3D read) {
if(demand_driven == true)
device.pollAndProcessInput();
read.set(readings[currentIndex].read);
}
/**
* Retrieves the last sensor reading and copies that value into
* the specified argument.
*
* @param read the matrix that will receive the sensor reading
* @param deltaT this parameter is ignored
*
* @deprecated As of Java 3D version 1.4, prediction is not a
* supported feature; use getRead(Transform3D)
instead.
*/
public void getRead(Transform3D read, long deltaT){
getRead(read);
}
/**
* Extracts the most recent sensor reading and copies that value into
* the specified argument.
* @param read the matrix that will receive the most recent sensor reading
*/
public void lastRead(Transform3D read){
read.set(readings[currentIndex].read);
}
/**
* Extracts the kth-most recent sensor reading and copies that value into
* the specified argument; where 0 is the most recent sensor reading, 1 is
* the next most recent sensor reading, etc.
* @param read the matrix that will receive the most recent sensor reading
* @param kth the kth previous sensor reading
*/
public void lastRead(Transform3D read, int kth){
if(kth >= sensorReadCount) {
throw new IllegalArgumentException(J3dI18N.getString("Sensor3"));
}
read.set(readings[previousIndex(kth)].read);
}
/**
* Returns the time associated with the most recent sensor reading.
* @return the time associated with the most recent sensor reading.
*/
public long lastTime(){
return readings[currentIndex].time;
}
/**
* Returns the time associated with the kth-most recent sensor reading;
* where 0 is the most recent sensor reading, 1 is the next most recent
* sensor reading, etc.
* @return the time associated with the kth-most recent sensor reading.
*/
public long lastTime(int k){
if(k >= sensorReadCount) {
throw new IllegalArgumentException(J3dI18N.getString("Sensor4"));
}
return readings[previousIndex(k)].time;
}
/**
* Places the most recent sensor reading value for each button into
* the array parameter; will throw an ArrayIndexOutOfBoundsException
* if values.length is less than the number of buttons.
* @param values the array into which the button values will be
* placed
*/
public void lastButtons(int[] values) {
System.arraycopy(readings[currentIndex].buttonValues, 0, values,
0, sensorButtonCount);
}
/**
* Places the kth-most recent sensor reading value for each button into
* the array parameter; where k=0 is the most recent sensor reading, k=1
* is the next most recent sensor reading, etc.; will throw an
* ArrayIndexOutOfBoundsException if values.length is less than
* the number of buttons.
* @param k the time associated with the most recent sensor reading
* @param values the array into which the button values will be
* placed.
*/
public void lastButtons(int k, int[] values) {
if(k >= sensorReadCount) {
throw new IllegalArgumentException(J3dI18N.getString("Sensor5"));
}
System.arraycopy(readings[previousIndex(k)].buttonValues, 0, values,
0, sensorButtonCount);
}
/**
* Returns the number of SensorRead objects associated with
* this sensor.
* @return the number of SensorReadObjects associated with this sensor
*/
public int getSensorReadCount() {
return this.sensorReadCount;
}
/**
* Set the number of sensor read objects per Sensor. This is a
* calibration parameter that should normally be set in this
* object's constructor. Calling this method resets all of this
* sensor's values that are already in the buffer.
* It is illegal to change this value after the device has been
* added to the scheduler.
* @param count the new sensor read count
*/
public void setSensorReadCount(int count) {
sensorReadCount = count;
MaxSensorReadIndex = sensorReadCount + SENSOR_READ_COUNT_BUFFER - 1;
readings = new SensorRead[MaxSensorReadIndex + 1];
for(int i = 0; i < MaxSensorReadIndex + 1; i++){
readings[i] = new SensorRead(sensorButtonCount);
}
currentIndex = 0;
}
/**
* Returns the number of buttons associated with this sensor.
* @return the number of buttons associated with this sensor.
*/
public int getSensorButtonCount() {
return sensorButtonCount;
}
/**
* Gets the current sensor read.
* @return the current sensor read object
*/
public SensorRead getCurrentSensorRead() {
// not sure if this should return a reference or a copy
SensorRead read = new SensorRead(sensorButtonCount);
read.set(readings[currentIndex]);
return read;
}
/**
* Sets the next sensor read to the specified values; once these
* values are set via this method they become the current values
* returned by methods such as lastRead(), lastTime(), and
* lastButtons(); note that if there are no buttons associated with
* this sensor, values can just be an empty array.
* @param time the next SensorRead's associated time
* @param transform the next SensorRead's transformation
* @param values the next SensorRead's buttons' states
*/
public void setNextSensorRead(long time, Transform3D transform,
int[] values) {
int temp = currentIndex + 1;
if (temp > MaxSensorReadIndex) temp = 0;
readings[temp].setTime(time);
readings[temp].set(transform);
if(sensorButtonCount > 0)
readings[temp].setButtons(values);
currentIndex = temp;
}
/**
* Sets the next sensor read to the specified values; once these
* values are set via this method they become the current values
* returned by methods such as lastRead(), lastTime(), and
* lastButtons().
* @param read the next SensorRead's values
*/
public void setNextSensorRead(SensorRead read) {
int temp = currentIndex + 1;
if (temp > MaxSensorReadIndex) temp = 0;
readings[temp].set(read);
currentIndex = temp;
}
}