Revamped camera handling. We now have a camera handler through which all camera
manipulations pass. It can then ensure that the camera remains within zoom and pan boundaries and is generally in the right place. It also handles camera paths, which adjust the camera through the handler. The input handler now has no camera logic but simply wires up camera manipulations to input mechanisms which is much cleaner. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3752 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -51,8 +51,7 @@ import com.jme.light.PointLight;
|
||||
import com.jme.math.Vector3f;
|
||||
import com.jme.util.Timer;
|
||||
|
||||
import com.threerings.jme.camera.CameraPath;
|
||||
import com.threerings.jme.camera.GodViewHandler;
|
||||
import com.threerings.jme.camera.CameraHandler;
|
||||
|
||||
/**
|
||||
* Defines a basic application framework providing integration with the
|
||||
@@ -181,27 +180,6 @@ public class JmeApp
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the camera moving along a path which will be updated every tick
|
||||
* until it is complete.
|
||||
*/
|
||||
public void moveCamera (CameraPath path)
|
||||
{
|
||||
if (_campath != null) {
|
||||
_campath.abort();
|
||||
}
|
||||
_campath = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the camera is currently animating along a path, false if
|
||||
* it is not.
|
||||
*/
|
||||
public boolean cameraIsMoving ()
|
||||
{
|
||||
return (_campath != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the application to stop the main loop, cleanup and exit.
|
||||
*/
|
||||
@@ -293,16 +271,26 @@ public class JmeApp
|
||||
*/
|
||||
protected void initInput ()
|
||||
{
|
||||
_input = createInputHandler(_camera, _properties.getRenderer());
|
||||
_camhand = createCameraHandler(_camera);
|
||||
_input = createInputHandler(_camhand, _properties.getRenderer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the input handler used to control our camera and manage
|
||||
* non-UI keyboard input.
|
||||
* Creates the camera handler which provides various camera manipulation
|
||||
* functionality.
|
||||
*/
|
||||
protected InputHandler createInputHandler (Camera camera, String api)
|
||||
protected CameraHandler createCameraHandler (Camera camera)
|
||||
{
|
||||
return new GodViewHandler(camera, api);
|
||||
return new CameraHandler(camera);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the input handler used to control our camera and manage non-UI
|
||||
* keyboard input.
|
||||
*/
|
||||
protected InputHandler createInputHandler (CameraHandler camhand, String api)
|
||||
{
|
||||
return new InputHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -416,12 +404,8 @@ public class JmeApp
|
||||
float timePerFrame = _timer.getTimePerFrame();
|
||||
_root.updateGeometricState(timePerFrame, true);
|
||||
|
||||
// if there's a camera path, update that as well
|
||||
if (_campath != null) {
|
||||
if (_campath.tick(timePerFrame)) {
|
||||
_campath = null;
|
||||
}
|
||||
}
|
||||
// update the camera handler
|
||||
_camhand.update(timePerFrame);
|
||||
|
||||
// update our stats display if we have one
|
||||
if (_stats != null) {
|
||||
@@ -538,7 +522,7 @@ public class JmeApp
|
||||
protected PropertiesIO _properties;
|
||||
protected DisplaySystem _display;
|
||||
protected Camera _camera;
|
||||
protected CameraPath _campath;
|
||||
protected CameraHandler _camhand;
|
||||
|
||||
protected InputHandler _input;
|
||||
protected BRootNode _rnode;
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.camera;
|
||||
|
||||
import com.jme.math.FastMath;
|
||||
import com.jme.math.Matrix3f;
|
||||
import com.jme.math.Vector3f;
|
||||
import com.jme.renderer.Camera;
|
||||
|
||||
/**
|
||||
* Provides various useful mechanisms for manipulating the camera.
|
||||
*/
|
||||
public class CameraHandler
|
||||
{
|
||||
/**
|
||||
* Creates a new camera handler. The camera begins life at the origin,
|
||||
* facing in the negative z direction (pointing at the ground).
|
||||
*/
|
||||
public CameraHandler (Camera camera)
|
||||
{
|
||||
camera.setDirection(new Vector3f(0, 0, -1));
|
||||
camera.setLeft(new Vector3f(-1, 0, 0));
|
||||
camera.setUp(new Vector3f(0, 1, 0));
|
||||
camera.update();
|
||||
_camera = camera;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures limits on the camera tilt.
|
||||
*/
|
||||
public void setTiltLimits (float minAngle, float maxAngle)
|
||||
{
|
||||
_minTilt = minAngle;
|
||||
_maxTilt = maxAngle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures limits on the distance the camera can be panned.
|
||||
*/
|
||||
public void setPanLimits (float minX, float minY, float maxX, float maxY)
|
||||
{
|
||||
_minX = minX;
|
||||
_minY = minY;
|
||||
_maxX = maxX;
|
||||
_maxY = maxY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the camera moving along a path which will be updated every tick
|
||||
* until it is complete.
|
||||
*/
|
||||
public void moveCamera (CameraPath path)
|
||||
{
|
||||
if (_campath != null) {
|
||||
_campath.abort();
|
||||
}
|
||||
_campath = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the camera is currently animating along a path, false if
|
||||
* it is not.
|
||||
*/
|
||||
public boolean cameraIsMoving ()
|
||||
{
|
||||
return (_campath != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called by the {@link JmeApp} on every frame to allow the handler
|
||||
* to update the camera as necessary.
|
||||
*/
|
||||
public void update (float frameTime)
|
||||
{
|
||||
if (_campath != null) {
|
||||
if (_campath.tick(frameTime)) {
|
||||
_campath = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the camera being manipulated by this handler.
|
||||
*/
|
||||
public Camera getCamera ()
|
||||
{
|
||||
return _camera;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the camera's location. The specified location will be bounded
|
||||
* within the current pan and zoom limits.
|
||||
*/
|
||||
public void setLocation (Vector3f location)
|
||||
{
|
||||
_camera.setLocation(bound(location));
|
||||
_camera.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pans the camera the specified distance in the x and y directions. These
|
||||
* distances will be multiplied by the current "view" x and y axes and
|
||||
* added to the camera's position.
|
||||
*/
|
||||
public void panCamera (float x, float y)
|
||||
{
|
||||
Vector3f loc = _camera.getLocation();
|
||||
loc.addLocal(_rxdir.mult(x, _temp));
|
||||
loc.addLocal(_rydir.mult(y, _temp));
|
||||
setLocation(loc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zooms the camera in (distance < 0) and out (distance > 0) by the
|
||||
* specified amount. The distance is multiplied by the camera's current
|
||||
* direction and added to its current position, which is then bounded into
|
||||
* the pan and zoom volume.
|
||||
*/
|
||||
public void zoomCamera (float distance)
|
||||
{
|
||||
Vector3f loc = _camera.getLocation();
|
||||
loc.subtractLocal(_camera.getDirection().mult(distance, _temp));
|
||||
setLocation(loc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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. Additionally zooms the camera in (deltaZoom < 0) or out
|
||||
* (deltaZoom > 0) along its direction of view by the specified amount.
|
||||
*/
|
||||
public void rotateCamera (
|
||||
Vector3f spot, Vector3f axis, float deltaAngle, float deltaZoom)
|
||||
{
|
||||
// get a vector from the camera's current position to the point around
|
||||
// which we're going to orbit
|
||||
Vector3f direction = _camera.getLocation().subtract(spot);
|
||||
|
||||
// create a rotation matrix
|
||||
_rotm.fromAxisAngle(axis, deltaAngle);
|
||||
|
||||
// rotate the direction 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());
|
||||
|
||||
// if we're rotating around the ground normal, we need to update our
|
||||
// notion of side-to-side and forward for panning
|
||||
if (axis == _groundNormal) {
|
||||
_rotm.mult(_rxdir, _rxdir);
|
||||
_rotm.mult(_rydir, _rydir);
|
||||
}
|
||||
|
||||
// finally move the camera to its new location, zooming in or out in
|
||||
// the process
|
||||
float scale = 1 + (deltaZoom / direction.length());
|
||||
direction.scaleAdd(scale, spot);
|
||||
setLocation(direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Swings the camera perpendicular to the ground normal, around the point
|
||||
* on the ground at which it is looking.
|
||||
*/
|
||||
public void orbitCamera (float deltaAngle)
|
||||
{
|
||||
rotateCamera(getGroundPoint(), _groundNormal, deltaAngle, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Swings the camera perpendicular to its left vector around the point on
|
||||
* the ground at which it is looking.
|
||||
*/
|
||||
public void tiltCamera (float deltaAngle)
|
||||
{
|
||||
rotateCamera(getGroundPoint(), _camera.getLeft(), deltaAngle, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the point on the ground (z = 0) at which the camera is looking.
|
||||
*/
|
||||
public Vector3f getGroundPoint ()
|
||||
{
|
||||
float dist = -1f * _groundNormal.dot(_camera.getLocation()) /
|
||||
_groundNormal.dot(_camera.getDirection());
|
||||
return _camera.getLocation().add(_camera.getDirection().mult(dist));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ground normal. Z is the default ground plane and the normal
|
||||
* points in the positive z direction.
|
||||
*/
|
||||
public Vector3f getGroundNormal ()
|
||||
{
|
||||
return _groundNormal;
|
||||
}
|
||||
|
||||
protected Vector3f bound (Vector3f loc)
|
||||
{
|
||||
loc.x = Math.max(Math.min(loc.x, _maxX), _minX);
|
||||
loc.y = Math.max(Math.min(loc.y, _maxY), _minY);
|
||||
loc.z = Math.max(Math.min(loc.z, _maxZ), _minZ);
|
||||
return loc;
|
||||
}
|
||||
|
||||
protected Camera _camera;
|
||||
protected CameraPath _campath;
|
||||
protected Matrix3f _rotm = new Matrix3f();
|
||||
protected Vector3f _temp = new Vector3f();
|
||||
|
||||
protected float _minX = Float.MIN_VALUE, _maxX = Float.MAX_VALUE;
|
||||
protected float _minY = Float.MIN_VALUE, _maxY = Float.MAX_VALUE;
|
||||
protected float _minZ = Float.MIN_VALUE, _maxZ = Float.MAX_VALUE;
|
||||
protected float _minTilt = Float.MIN_VALUE, _maxTilt = Float.MAX_VALUE;
|
||||
|
||||
protected Vector3f _rxdir = new Vector3f(1, 0, 0);
|
||||
protected Vector3f _rydir = new Vector3f(0, 1, 0);
|
||||
|
||||
protected static final Vector3f _xdir = new Vector3f(1, 0, 0);
|
||||
protected static final Vector3f _ydir = new Vector3f(0, 1, 0);
|
||||
|
||||
protected static final Vector3f _groundNormal = new Vector3f(0, 0, 1);
|
||||
}
|
||||
@@ -45,10 +45,10 @@ public abstract class CameraPath
|
||||
{
|
||||
}
|
||||
|
||||
protected CameraPath (Camera camera)
|
||||
protected CameraPath (CameraHandler camhand)
|
||||
{
|
||||
_camera = camera;
|
||||
_camhand = camhand;
|
||||
}
|
||||
|
||||
protected Camera _camera;
|
||||
protected CameraHandler _camhand;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ import com.threerings.jme.Log;
|
||||
|
||||
/**
|
||||
* Sets up camera controls for moving around from a top-down perspective,
|
||||
* suitable for strategy games and their ilk. The "ground" is assumed to
|
||||
* be the XY plane.
|
||||
* suitable for strategy games and their ilk. The "ground" is assumed to be the
|
||||
* XY plane.
|
||||
*/
|
||||
public class GodViewHandler extends InputHandler
|
||||
{
|
||||
@@ -31,108 +31,11 @@ public class GodViewHandler extends InputHandler
|
||||
* @param cam The camera to move with this handler.
|
||||
* @param api The API from which to create a KeyBindingManager.
|
||||
*/
|
||||
public GodViewHandler (Camera cam, String api)
|
||||
public GodViewHandler (CameraHandler camhand, String api)
|
||||
{
|
||||
_camera = cam;
|
||||
_camhand = camhand;
|
||||
setKeyBindings(api);
|
||||
addActions(cam);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the minimum and maximum z-axis elevation allowed for the
|
||||
* camera.
|
||||
*/
|
||||
public void setZoomLimits (float minZ, float maxZ)
|
||||
{
|
||||
_minZ = minZ;
|
||||
_maxZ = maxZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures limits on the camera roll.
|
||||
*/
|
||||
public void setRollLimits (float minAngle, float maxAngle)
|
||||
{
|
||||
_minRoll = minAngle;
|
||||
_maxRoll = maxAngle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures limits on the distance the camera can be panned.
|
||||
*/
|
||||
public void setPanLimits (float minX, float minY, float maxX, float maxY)
|
||||
{
|
||||
_minX = minX;
|
||||
_minY = minY;
|
||||
_maxX = maxX;
|
||||
_maxY = maxY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the rotational velocity of the camera, which is used to
|
||||
* smoothly slide the camera to its new position following a call to
|
||||
* {@link #rotateCamera}.
|
||||
*/
|
||||
public void setRotateVelocity (float radiansPerSecond)
|
||||
{
|
||||
_rotateVelocity = radiansPerSecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swings the camera around the point on the ground at which it is
|
||||
* "looking", by the requested angle (in radians). The camera does not
|
||||
* jump by the specified angle but rather smoothly rotates there.
|
||||
*/
|
||||
public void rotateCamera (float deltaAngle)
|
||||
{
|
||||
_rotateDelta += deltaAngle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the camera is still rotating due to a previous call
|
||||
* to {@link #rotateCamera}.
|
||||
*/
|
||||
public boolean isRotating ()
|
||||
{
|
||||
return _rotateDelta != 0;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void update (float time)
|
||||
{
|
||||
super.update(time);
|
||||
|
||||
float deltaAngle = 0;
|
||||
if (_rotateDelta < 0) {
|
||||
deltaAngle = Math.min(time * _rotateVelocity, -_rotateDelta);
|
||||
} else if (_rotateDelta > 0) {
|
||||
deltaAngle = Math.max(-1f * time * _rotateVelocity, -_rotateDelta);
|
||||
}
|
||||
if (deltaAngle != 0) {
|
||||
_rotateDelta += deltaAngle;
|
||||
rotateCamera(_groundNormal, deltaAngle);
|
||||
}
|
||||
addActions();
|
||||
}
|
||||
|
||||
protected void setKeyBindings (String api)
|
||||
@@ -153,184 +56,101 @@ public class GodViewHandler extends InputHandler
|
||||
keyboard.set("turnRight", KeyInput.KEY_RIGHT);
|
||||
keyboard.set("turnLeft", KeyInput.KEY_LEFT);
|
||||
|
||||
// the key bindings for the roll actions
|
||||
keyboard.set("rollForward", KeyInput.KEY_HOME);
|
||||
keyboard.set("rollBack", KeyInput.KEY_END);
|
||||
// the key bindings for the tilt actions
|
||||
keyboard.set("tiltForward", KeyInput.KEY_HOME);
|
||||
keyboard.set("tiltBack", KeyInput.KEY_END);
|
||||
|
||||
keyboard.set("screenshot", KeyInput.KEY_F12);
|
||||
}
|
||||
|
||||
protected void addActions (Camera cam)
|
||||
protected void addActions ()
|
||||
{
|
||||
addAction(new KeyScreenShotAction(), "screenshot", false);
|
||||
|
||||
addPanActions(cam);
|
||||
addZoomActions(cam);
|
||||
addOrbitActions(cam);
|
||||
addRollActions(cam);
|
||||
addPanActions();
|
||||
addZoomActions();
|
||||
addOrbitActions();
|
||||
addTiltActions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds actions for panning the camera around the scene.
|
||||
*/
|
||||
protected void addPanActions (Camera cam)
|
||||
protected void addPanActions ()
|
||||
{
|
||||
CameraAction forward = new CameraAction(cam, 0.5f) {
|
||||
InputAction forward = new InputAction() {
|
||||
public void performAction (InputActionEvent evt) {
|
||||
Vector3f loc = _camera.getLocation();
|
||||
loc.addLocal(_rydir.mult(speed * evt.getTime(), _temp));
|
||||
_camera.setLocation(boundPan(loc));
|
||||
_camera.update();
|
||||
_camhand.panCamera(0, speed * evt.getTime());
|
||||
}
|
||||
};
|
||||
forward.setSpeed(0.5f);
|
||||
addAction(forward, "forward", true);
|
||||
|
||||
CameraAction backward = new CameraAction(cam, 0.5f) {
|
||||
InputAction backward = new InputAction() {
|
||||
public void performAction (InputActionEvent evt) {
|
||||
Vector3f loc = _camera.getLocation();
|
||||
loc.subtractLocal(_rydir.mult(speed * evt.getTime(), _temp));
|
||||
_camera.setLocation(boundPan(loc));
|
||||
_camera.update();
|
||||
_camhand.panCamera(0, -speed * evt.getTime());
|
||||
}
|
||||
};
|
||||
backward.setSpeed(0.5f);
|
||||
addAction(backward, "backward", true);
|
||||
|
||||
CameraAction left = new CameraAction(cam, 0.5f) {
|
||||
InputAction left = new InputAction() {
|
||||
public void performAction (InputActionEvent evt) {
|
||||
Vector3f loc = _camera.getLocation();
|
||||
loc.subtractLocal(_rxdir.mult(speed * evt.getTime(), _temp));
|
||||
_camera.setLocation(boundPan(loc));
|
||||
_camera.update();
|
||||
_camhand.panCamera(-speed * evt.getTime(), 0);
|
||||
}
|
||||
};
|
||||
left.setSpeed(0.5f);
|
||||
addAction(left, "left", true);
|
||||
|
||||
CameraAction right = new CameraAction(cam, 0.5f) {
|
||||
InputAction right = new InputAction() {
|
||||
public void performAction (InputActionEvent evt) {
|
||||
Vector3f loc = _camera.getLocation();
|
||||
loc.addLocal(_rxdir.mult(speed * evt.getTime(), _temp));
|
||||
_camera.setLocation(boundPan(loc));
|
||||
_camera.update();
|
||||
_camhand.panCamera(speed * evt.getTime(), 0);
|
||||
}
|
||||
};
|
||||
right.setSpeed(0.5f);
|
||||
addAction(right, "right", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds actions for zooming the camaera in and out.
|
||||
*/
|
||||
protected void addZoomActions (Camera cam)
|
||||
protected void addZoomActions ()
|
||||
{
|
||||
CameraAction zoomIn = new CameraAction(cam, 0.5f) {
|
||||
InputAction zoomIn = new InputAction() {
|
||||
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(boundPan(loc));
|
||||
_camera.update();
|
||||
}
|
||||
_camhand.zoomCamera(-speed * evt.getTime());
|
||||
}
|
||||
};
|
||||
zoomIn.setSpeed(0.5f);
|
||||
addAction(zoomIn, "zoomIn", true);
|
||||
|
||||
CameraAction zoomOut = new CameraAction(cam, 0.5f) {
|
||||
InputAction zoomOut = new InputAction() {
|
||||
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(boundPan(loc));
|
||||
_camera.update();
|
||||
}
|
||||
_camhand.zoomCamera(speed * evt.getTime());
|
||||
}
|
||||
};
|
||||
zoomOut.setSpeed(0.5f);
|
||||
addAction(zoomOut, "zoomOut", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds actions for orbiting the camera around the viewpoint.
|
||||
*/
|
||||
protected void addOrbitActions (Camera cam)
|
||||
protected void addOrbitActions ()
|
||||
{
|
||||
addAction(new OrbitAction(-FastMath.PI / 2), "turnRight", true);
|
||||
addAction(new OrbitAction(FastMath.PI / 2), "turnLeft", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds actions for rolling the camera around the yaw axis.
|
||||
* Adds actions for tilting the camera (rotating around the yaw axis).
|
||||
*/
|
||||
protected void addRollActions (Camera cam)
|
||||
protected void addTiltActions ()
|
||||
{
|
||||
addAction(new RollAction(-FastMath.PI / 2), "rollForward", true);
|
||||
addAction(new RollAction(FastMath.PI / 2), "rollBack", true);
|
||||
addAction(new TiltAction(-FastMath.PI / 2), "tiltForward", true);
|
||||
addAction(new TiltAction(FastMath.PI / 2), "tiltBack", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
if (around == _groundNormal) {
|
||||
_rotm.mult(_rxdir, _rxdir);
|
||||
_rotm.mult(_rydir, _rydir);
|
||||
}
|
||||
|
||||
// and move the camera to its new location
|
||||
_camera.setLocation(boundPan(center.add(direction)));
|
||||
|
||||
_camera.update();
|
||||
}
|
||||
|
||||
protected static Vector3f groundPoint (Camera camera)
|
||||
{
|
||||
float dist = -1f * _groundNormal.dot(camera.getLocation()) /
|
||||
_groundNormal.dot(camera.getDirection());
|
||||
return camera.getLocation().add(camera.getDirection().mult(dist));
|
||||
}
|
||||
|
||||
protected Vector3f boundPan (Vector3f loc)
|
||||
{
|
||||
loc.x = Math.max(Math.min(loc.x, _maxX), _minX);
|
||||
loc.y = Math.max(Math.min(loc.y, _maxY), _minY);
|
||||
return loc;
|
||||
}
|
||||
|
||||
protected abstract class CameraAction extends KeyInputAction
|
||||
{
|
||||
public CameraAction (Camera camera, float speed)
|
||||
{
|
||||
_camera = camera;
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
/** The camera to manipulate. */
|
||||
protected Camera _camera;
|
||||
|
||||
/** A temporary vector. */
|
||||
protected Vector3f _temp = new Vector3f();
|
||||
}
|
||||
|
||||
protected class OrbitAction extends KeyInputAction
|
||||
protected class OrbitAction extends InputAction
|
||||
{
|
||||
public OrbitAction (float radPerSec)
|
||||
{
|
||||
@@ -339,42 +159,26 @@ public class GodViewHandler extends InputHandler
|
||||
|
||||
public void performAction (InputActionEvent evt)
|
||||
{
|
||||
rotateCamera(_groundNormal, _radPerSec * evt.getTime());
|
||||
_camhand.orbitCamera(_radPerSec * evt.getTime());
|
||||
}
|
||||
|
||||
protected float _radPerSec;
|
||||
}
|
||||
|
||||
protected class RollAction extends KeyInputAction
|
||||
protected class TiltAction extends InputAction
|
||||
{
|
||||
public RollAction (float radPerSec)
|
||||
public TiltAction (float radPerSec)
|
||||
{
|
||||
_radPerSec = radPerSec;
|
||||
}
|
||||
|
||||
public void performAction (InputActionEvent evt)
|
||||
{
|
||||
rotateCamera(_camera.getLeft(), _radPerSec * evt.getTime());
|
||||
_camhand.tiltCamera(_radPerSec * evt.getTime());
|
||||
}
|
||||
|
||||
protected float _radPerSec;
|
||||
}
|
||||
|
||||
protected Camera _camera;
|
||||
protected Matrix3f _rotm = new Matrix3f();
|
||||
|
||||
protected float _rotateVelocity = FastMath.PI, _rotateDelta;
|
||||
|
||||
protected float _minX = Float.MIN_VALUE, _maxX = Float.MAX_VALUE;
|
||||
protected float _minY = Float.MIN_VALUE, _maxY = Float.MAX_VALUE;
|
||||
protected float _minZ = Float.MIN_VALUE, _maxZ = Float.MAX_VALUE;
|
||||
protected float _minRoll = Float.MIN_VALUE, _maxRoll = Float.MAX_VALUE;
|
||||
|
||||
protected Vector3f _rxdir = new Vector3f(1, 0, 0);
|
||||
protected Vector3f _rydir = new Vector3f(0, 1, 0);
|
||||
|
||||
protected static final Vector3f _xdir = new Vector3f(1, 0, 0);
|
||||
protected static final Vector3f _ydir = new Vector3f(0, 1, 0);
|
||||
|
||||
protected static final Vector3f _groundNormal = new Vector3f(0, 0, 1);
|
||||
protected CameraHandler _camhand;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
package com.threerings.jme.camera;
|
||||
|
||||
import com.jme.math.FastMath;
|
||||
import com.jme.math.Matrix3f;
|
||||
import com.jme.math.Vector3f;
|
||||
import com.jme.renderer.Camera;
|
||||
|
||||
@@ -48,10 +47,10 @@ public class SwingPath extends CameraPath
|
||||
* @param zoom the distance to zoom along the camera's view axis (negative
|
||||
* = in, positive = out).
|
||||
*/
|
||||
public SwingPath (Camera camera, Vector3f spot, Vector3f axis,
|
||||
public SwingPath (CameraHandler camhand, Vector3f spot, Vector3f axis,
|
||||
float angle, float angvel, float zoom)
|
||||
{
|
||||
super(camera);
|
||||
super(camhand);
|
||||
|
||||
if (angle == 0) {
|
||||
Log.warning("Requested to swing camera through zero degrees " +
|
||||
@@ -97,25 +96,8 @@ public class SwingPath extends CameraPath
|
||||
done = true;
|
||||
}
|
||||
|
||||
// get a vector from the camera's position to the point around which
|
||||
// we're going to orbit
|
||||
Vector3f camloc = _camera.getLocation();
|
||||
Vector3f direction = camloc.subtract(_spot);
|
||||
|
||||
// create a rotation matrix
|
||||
_rotm.fromAxisAngle(_axis, 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());
|
||||
|
||||
// and move the camera to its new location (accounting for the zoom)
|
||||
float scale = 1 + (deltaZoom / direction.length());
|
||||
direction.scaleAdd(scale, _spot);
|
||||
_camera.setLocation(direction);
|
||||
_camera.update();
|
||||
// have the camera handler do the necessary rotating and zooming
|
||||
_camhand.rotateCamera(_spot, _axis, deltaAngle, deltaZoom);
|
||||
|
||||
return done;
|
||||
}
|
||||
@@ -123,5 +105,4 @@ public class SwingPath extends CameraPath
|
||||
protected Vector3f _spot, _axis;
|
||||
protected float _angle, _angvel, _rotated;
|
||||
protected float _zoom, _zoomvel, _zoomed;
|
||||
protected Matrix3f _rotm = new Matrix3f();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user