diff --git a/src/java/com/threerings/jme/input/GodViewHandler.java b/src/java/com/threerings/jme/input/GodViewHandler.java index 0f7da8b2e..3be18a9bb 100644 --- a/src/java/com/threerings/jme/input/GodViewHandler.java +++ b/src/java/com/threerings/jme/input/GodViewHandler.java @@ -17,6 +17,7 @@ import com.jme.input.action.*; import com.jme.input.action.InputActionEvent; import com.threerings.jme.JmeApp; +import com.threerings.jme.Log; /** * Sets up camera controls for moving around from a top-down perspective, @@ -34,11 +35,43 @@ public class GodViewHandler extends InputHandler */ public GodViewHandler (JmeApp app, Camera cam, String api) { + _camera = cam; setKeyBindings(api); setMouse(cam); setActions(cam, app); } + /** + * Configures the minimum and maximum z-axis elevation allowed for the + * camera. + */ + public void setZoomLimits (float minZ, float maxZ) + { + _minZ = minZ; + _maxZ = maxZ; + } + + /** + * Sets the camera zoom level to a value between zero (zoomed in + * maximally) and 1 (zoomed out maximally). Zoom limits must have + * already been set up via a call to {@link #setZoomLimits}. + */ + public void setZoomLevel (float level) + { + Log.info("Zoom " + level + " " + _camera.getLocation()); + level = Math.max(0f, Math.min(level, 1f)); + _camera.getLocation().z = _minZ + (_maxZ - _minZ) * level; + _camera.update(); + } + + /** + * Returns the current camera zoom level. + */ + public float getZoomLevel () + { + return (_camera.getLocation().z - _minZ) / (_maxZ - _minZ); + } + protected void setKeyBindings (String api) { KeyBindingManager keyboard = KeyBindingManager.getKeyBindingManager(); @@ -53,6 +86,8 @@ public class GodViewHandler extends InputHandler keyboard.set("zoomOut", KeyInput.KEY_DOWN); keyboard.set("turnRight", KeyInput.KEY_RIGHT); keyboard.set("turnLeft", KeyInput.KEY_LEFT); + keyboard.set("rollForward", KeyInput.KEY_HOME); + keyboard.set("rollBack", KeyInput.KEY_END); keyboard.set("screenshot", KeyInput.KEY_F12); keyboard.set("exit", KeyInput.KEY_ESCAPE); @@ -111,7 +146,7 @@ public class GodViewHandler extends InputHandler CameraAction left = new CameraAction(cam, 0.5f) { public void performAction (InputActionEvent evt) { Vector3f loc = _camera.getLocation(); - loc.addLocal(_rxdir.mult(speed * evt.getTime(), _temp)); + loc.subtractLocal(_rxdir.mult(speed * evt.getTime(), _temp)); _camera.setLocation(loc); _camera.update(); } @@ -122,7 +157,7 @@ public class GodViewHandler extends InputHandler CameraAction right = new CameraAction(cam, 0.5f) { public void performAction (InputActionEvent evt) { Vector3f loc = _camera.getLocation(); - loc.subtractLocal(_rxdir.mult(speed * evt.getTime(), _temp)); + loc.addLocal(_rxdir.mult(speed * evt.getTime(), _temp)); _camera.setLocation(loc); _camera.update(); } @@ -130,48 +165,82 @@ public class GodViewHandler extends InputHandler right.setKey("right"); addAction(right); - KeyForwardAction zoomIn = new KeyForwardAction(cam, 0.5f); + CameraAction zoomIn = new CameraAction(cam, 0.5f) { + public void performAction (InputActionEvent evt) { + Vector3f loc = _camera.getLocation(); + if (loc.z > _minZ) { + _camera.getDirection().mult(speed * evt.getTime(), _temp); + loc.addLocal(_temp); + _camera.setLocation(loc); + _camera.update(); + } + } + }; zoomIn.setKey("zoomIn"); addAction(zoomIn); - KeyBackwardAction zoomOut = new KeyBackwardAction(cam, 0.5f); + + CameraAction zoomOut = new CameraAction(cam, 0.5f) { + public void performAction (InputActionEvent evt) { + Vector3f loc = _camera.getLocation(); + if (loc.z < _maxZ) { + _camera.getDirection().mult(speed * evt.getTime(), _temp); + loc.subtractLocal(_temp); + _camera.setLocation(loc); + _camera.update(); + } + } + }; zoomOut.setKey("zoomOut"); addAction(zoomOut); -// CameraAction lookUp = new CameraAction(cam, 0.5f) { -// public void performAction (InputActionEvent evt) { -// _incr.fromAxisAngle(_camera.getLeft(), -// -FastMath.PI * evt.getTime() / 2); -// _incr.mult(_camera.getLeft(), _camera.getLeft()); -// _incr.mult(_camera.getDirection(), _camera.getDirection()); -// _incr.mult(_camera.getUp(), _camera.getUp()); -// _camera.update(); -// } -// private Matrix3f _incr = new Matrix3f(); -// }; -// lookUp.setKey("lookUp"); -// addAction(lookUp); - -// CameraAction lookDown = new CameraAction(cam, 0.5f) { -// public void performAction (InputActionEvent evt) { -// _incr.fromAxisAngle(_camera.getLeft(), -// FastMath.PI * evt.getTime() / 2); -// _incr.mult(_camera.getLeft(), _camera.getLeft()); -// _incr.mult(_camera.getDirection(), _camera.getDirection()); -// _incr.mult(_camera.getUp(), _camera.getUp()); -// _camera.update(); -// } -// private Matrix3f _incr = new Matrix3f(); -// }; -// lookDown.setKey("lookDown"); -// addAction(lookDown); - - CameraAction orbitRight = new OrbitAction(cam, -FastMath.PI / 2); + OrbitAction orbitRight = new OrbitAction(-FastMath.PI / 2); orbitRight.setKey("turnRight"); addAction(orbitRight); - CameraAction orbitLeft = new OrbitAction(cam, FastMath.PI / 2); + OrbitAction orbitLeft = new OrbitAction(FastMath.PI / 2); orbitLeft.setKey("turnLeft"); addAction(orbitLeft); + + RollAction rollForward = new RollAction(-FastMath.PI / 2); + rollForward.setKey("rollForward"); + addAction(rollForward); + + RollAction rollBack = new RollAction(FastMath.PI / 2); + rollBack.setKey("rollBack"); + addAction(rollBack); + } + + /** + * Locates the point on the ground at which the camera is "looking" + * and rotates the camera from that point around the specified vector + * by the specified angle. + */ + protected void rotateCamera (Vector3f around, float deltaAngle) + { + // locate the point at which the camera is "pointing" on + // the ground plane + Vector3f camloc = _camera.getLocation(); + Vector3f center = groundPoint(_camera); + + // get a vector from the camera's position to the point + // around which we're going to orbit + Vector3f direction = camloc.subtract(center); + + // create a rotation matrix + _rotm.fromAxisAngle(around, deltaAngle); + + // rotate the center to camera vector and the camera itself + _rotm.mult(direction, direction); + _rotm.mult(_camera.getUp(), _camera.getUp()); + _rotm.mult(_camera.getLeft(), _camera.getLeft()); + _rotm.mult(_camera.getDirection(), _camera.getDirection()); + _rotm.mult(_rxdir, _rxdir); + _rotm.mult(_rydir, _rydir); + + // and move the camera to its new location + _camera.setLocation(center.add(direction)); + + _camera.update(); } protected static Vector3f groundPoint (Camera camera) @@ -196,48 +265,40 @@ public class GodViewHandler extends InputHandler protected Vector3f _temp = new Vector3f(); } - protected class OrbitAction extends CameraAction + protected class OrbitAction extends KeyInputAction { - public OrbitAction (Camera camera, float radPerSec) + public OrbitAction (float radPerSec) { - super(camera, 0f); _radPerSec = radPerSec; } public void performAction (InputActionEvent evt) { - // locate the point at which the camera is "pointing" on - // the ground plane - Vector3f camloc = _camera.getLocation(); - Vector3f center = groundPoint(_camera); - - // get a vector from the camera's position to the point - // around which we're going to orbit - Vector3f direction = camloc.subtract(center); - - // compute the amount we wish to orbit - float deltaA = _radPerSec * evt.getTime(); - // create a rotation matrix - _rotm.fromAxisAngle(_groundNormal, deltaA); - - // rotate the center to camera vector and the camera itself - _rotm.mult(direction, direction); - _rotm.mult(_camera.getUp(), _camera.getUp()); - _rotm.mult(_camera.getLeft(), _camera.getLeft()); - _rotm.mult(_camera.getDirection(), _camera.getDirection()); - _rotm.mult(_rxdir, _rxdir); - _rotm.mult(_rydir, _rydir); - - // and move the camera to its new location - _camera.setLocation(center.add(direction)); - - _camera.update(); + rotateCamera(_groundNormal, _radPerSec * evt.getTime()); } protected float _radPerSec; - protected Matrix3f _rotm = new Matrix3f(); } + protected class RollAction extends KeyInputAction + { + public RollAction (float radPerSec) + { + _radPerSec = radPerSec; + } + + public void performAction (InputActionEvent evt) + { + rotateCamera(_camera.getLeft(), _radPerSec * evt.getTime()); + } + + protected float _radPerSec; + } + + protected Camera _camera; + protected Matrix3f _rotm = new Matrix3f(); + + protected float _minZ = Float.MIN_VALUE, _maxZ = Float.MAX_VALUE; protected static final Vector3f _xdir = new Vector3f(1, 0, 0); protected static final Vector3f _ydir = new Vector3f(0, 1, 0);