📄 wandviewbehavior.java
字号:
else { center.set(transformCenter) ; } // Construct origin-based rotation about axis. aa4d.set(axis, currSpeed * frameTime) ; t3d.set(aa4d) ; // Apply the rotation to the view platform. transformAboutCenter(viewPlatformToVworld, center, t3d) ; targetTG.setTransform(viewPlatformToVworld) ; // Apply the rotation to trackerToVworld. transformAboutCenter(trackerToVworld, center, t3d) ; if (readAction6D == ECHO) { // Transform sensor echo to compensate for the new view // platform movement. transformAboutCenter(sensorToVworld, center, t3d) ; updateEcho(s, sensorToVworld) ; } } } /** * Implements a 6DOF sensor button listener that scales the view platform. * The center of scaling can be the sensor hotspot or a fixed location in * virtual world coordinates. * * @see #setButtonAction6D * @see #setTransformCenterSource * @see #setTransformCenter * @see #setScaleSpeed * @see #setAccelerationTime */ public class ScaleListener6D extends ListenerBase { private double direction ; private long buttonDownTime ; private Point3d center = new Point3d() ; private Transform3D t3d = new Transform3D() ; protected void endAction(Sensor s) { super.endAction(s) ; conditionViewScale(viewPlatformToVworld) ; } /** * Construct a new scale button listener for a 6DOF sensor. * * @param reverse if true, scale the view platform smaller; otherwise, * scale the view platform larger */ public ScaleListener6D(boolean reverse) { if (reverse) direction = -1.0 ; else direction = 1.0 ; } public void pressed(SensorEvent e) { initAction(e.getSensor()) ; buttonDownTime = e.getTime() ; } public void dragged(SensorEvent e) { long time = e.getTime() ; long lastTime = e.getLastTime() ; double scale, exp, transTime ; double frameTime = 1.0 ; if (scaleTimeBase == PER_SECOND) frameTime = (time - lastTime) / 1e9 ; // Compute speed based on acceleration interval. transTime = (time - buttonDownTime) / 1e9 ; if (transTime <= accelerationTime) { exp = (transTime / accelerationTime) * frameTime * direction ; } else { exp = frameTime * direction ; } scale = Math.pow(scaleSpeed, exp) ; // To avoid echo frame lag, compute sensorToVworld based on // computed trackerToVworld. getSensorToVworld() isn't current // for this frame. Sensor s = e.getSensor() ; s.getRead(sensorToTracker) ; sensorToVworld.mul(trackerToVworld, sensorToTracker) ; // Get the scale center. if (transformCenterSource == HOTSPOT) { s.getHotspot(center) ; sensorToVworld.transform(center) ; } else { center.set(transformCenter) ; } // Apply the scale to the view platform. t3d.set(scale) ; transformAboutCenter(viewPlatformToVworld, center, t3d) ; // Incremental scaling at the extremes can lead to numerical // instability, so catch BadTransformException to prevent the // behavior thread from being killed. Using a cumulative scale // matrix avoids this problem to a better extent, but causes the // 6DOF sensor hotspot center to jitter excessively. try { targetTG.setTransform(viewPlatformToVworld) ; } catch (BadTransformException bt) { conditionViewScale(viewPlatformToVworld) ; } // Apply the scale to trackerToVworld. transformAboutCenter(trackerToVworld, center, t3d) ; if (readAction6D == ECHO) { // Scale sensor echo to compensate for the new view // platform scale. transformAboutCenter(sensorToVworld, center, t3d) ; updateEcho(s, sensorToVworld) ; } } } /** * Implements a 6DOF sensor read listener that updates the orientation and * position of the sensor's echo in the virtual world. * * @see #setEchoType * @see #setEchoSize * @see #setReadAction6D * @see SensorGnomonEcho * @see SensorBeamEcho */ public class EchoReadListener6D implements SensorReadListener { private Transform3D sensorToVworld = new Transform3D() ; public void read(SensorEvent e) { Sensor s = e.getSensor() ; view.getSensorToVworld(s, sensorToVworld) ; updateEcho(s, sensorToVworld) ; } } /** * Implements a 2D valuator listener that rotates the view platform. The * X and Y values from the valuator should have a continuous range from * -1.0 to +1.0, although the rotation speed can be scaled to compensate * for a different range. The X and Y values are found in the sensor's * read matrix at the indices specified by * <code>setMatrixIndices2D</code>, with defaults of 3 and 7 respectively. * <p> * The rotation direction is controlled by the direction the 2D valuator * is pushed, and the rotation speed is scaled by the magnitude of the 2D * valuator read values. * <p> * This listener will work in conjunction with a 6DOF sensor if supplied * in the constructor. If a 6DOF sensor is provided and * <code>setRotationCoords</code> has been called with the value * <code>SENSOR</code>, then the rotation is applied in the 6DOF sensor's * coordinate system; otherwise the rotation is applied either in head * coordinates or in view platform coordinates. If a 6DOF sensor is * provided and <code>setTransformCenterSource</code> has been called with * the value <code>HOTSPOT</code>, then rotation is about the 6DOF * sensor's hotspot; otherwise, the rotation center is the value set by * <code>setTransformCenter</code>. * * @see #setReadAction2D * @see #setButtonAction2D * @see #setRotationCoords * @see #setTransformCenterSource * @see #setTransformCenter * @see #setRotationSpeed * @see #setThreshold2D * @see #setMatrixIndices2D */ public class RotationListener2D extends ListenerBase { private Sensor sensor2D, sensor6D ; private double[] m = new double[16] ; private Vector3d axis = new Vector3d() ; private Point3d center = new Point3d() ; private Transform3D t3d = new Transform3D() ; private AxisAngle4d aa4d = new AxisAngle4d() ; private Transform3D sensor2DRead = new Transform3D() ; private Transform3D headToVworld = new Transform3D() ; private double speedScaled ; protected void initAction(Sensor s) { super.initAction(s) ; if (rotationCoords == HEAD) { view.setUserHeadToVworldEnable(true) ; } if (s != null && readAction6D == ECHO) { // Disable the 6DOF echo. It will be updated in this action. eventAgent.removeSensorReadListener(s, echoReadListener6D) ; } } protected void endAction(Sensor s) { super.endAction(s) ; viewPlatformToVworld.normalize() ; targetTG.setTransform(viewPlatformToVworld) ; if (rotationCoords == HEAD) { view.setUserHeadToVworldEnable(false) ; } if (s != null && readAction6D == ECHO) { eventAgent.addSensorReadListener(s, echoReadListener6D) ; } } /** * Construct an instance of this class with the specified sensors. * * @param sensor2D the 2D valuator whose X and Y values drive the * rotation * @param sensor6D the 6DOF sensor to use if the rotation coordinate * system is set to <code>SENSOR</code> or the rotation center source * is <code>HOTSPOT</code>; may be <code>null</code> */ public RotationListener2D(Sensor sensor2D, Sensor sensor6D) { this.sensor2D = sensor2D ; this.sensor6D = sensor6D ; if (rotationUnits == DEGREES) speedScaled = rotationSpeed * Math.PI / 180.0 ; else speedScaled = rotationSpeed ; } public void read(SensorEvent e) { sensor2D.getRead(sensor2DRead) ; sensor2DRead.get(m) ; if (m[x2D] > threshold2D || m[x2D] < -threshold2D || m[y2D] > threshold2D || m[y2D] < -threshold2D) { // Initialize action on threshold crossing. if (!isActive()) initAction(sensor6D) ; // m[x2D] is the X valuator value and m[y2D] is the Y valuator // value. Use these to construct the rotation axis. double length = Math.sqrt(m[x2D]*m[x2D] + m[y2D]*m[y2D]) ; double iLength = 1.0/length ; axis.set(m[y2D]*iLength, -m[x2D]*iLength, 0.0) ; if (sensor6D != null) { // To avoid echo frame lag, compute sensorToVworld based // on computed trackerToVworld. getSensorToVworld() isn't // current for this frame. sensor6D.getRead(sensorToTracker) ; sensorToVworld.mul(trackerToVworld, sensorToTracker) ; } // Transform rotation axis into target coordinate system. if (sensor6D != null && rotationCoords == SENSOR) { if (nominalSensorRotation != null) nominalSensorRotation.transform(axis) ; sensorToVworld.transform(axis) ; } else if (rotationCoords == HEAD) { view.getUserHeadToVworld(headToVworld) ; headToVworld.transform(axis) ; } else { viewPlatformToVworld.transform(axis) ; } // Get the rotation center. if (transformCenterSource == HOTSPOT && sensor6D != null) { sensor6D.getHotspot(center) ; sensorToVworld.transform(center) ; } else { center.set(transformCenter) ; } double frameTime = 1.0 ; if (rotationTimeBase == PER_SECOND) frameTime = (e.getTime() - e.getLastTime()) / 1e9 ; // Construct origin-based rotation about axis. aa4d.set(axis, speedScaled * frameTime * length) ; t3d.set(aa4d) ; // Apply the rotation to the view platform. transformAboutCenter(viewPlatformToVworld, center, t3d) ; targetTG.setTransform(viewPlatformToVworld) ; if (sensor6D != null) { // Apply the rotation to trackerToVworld. transformAboutCenter(trackerToVworld, center, t3d) ; } if (sensor6D != null && readAction6D == ECHO) { // Transform sensor echo to compensate for the new view // platform movement. transformAboutCenter(sensorToVworld, center, t3d) ; updateEcho(sensor6D, sensorToVworld) ; } } else { // Initialize action on next threshold crossing. if (isActive()) endAction(sensor6D) ; } } public void pressed(SensorEvent e) { initAction(sensor6D) ; } public void released(SensorEvent e) { if (isActive()) endAction(sensor6D) ; } public void dragged(SensorEvent e) { read(e) ; } } /** * Implements a 2D valuator listener that translates the view platform. * The X and Y values from the valuator should have a continuous range * from -1.0 to +1.0, although the translation speed can be scaled to * compensate for a different range. The X and Y values are found in the * sensor's read matrix at the indices specified by * <code>setMatrixIndices2D</code>, with defaults of 3 and 7 respectively. * <p> * The translation direction is controlled by the direction the 2D * valuator is pushed, and the speed is the translation speed scaled by * the fast speed factor and the magnitude of the 2D valuator reads. * <p> * This listener will work in conjunction with a 6DOF sensor if supplied * in the constructor. If a 6DOF sensor is prov
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -