Hi all,
Per has been so kind as to give me the code to his ThirdPerson spherical camera in his marble game. I polished it up a bit and made it into a fully fledged system with a test and stuff.
Anyways, heres the code:
KeySphericalCameraZoom
package com.jme.input.action;
/**
*
* Zoom in and out of the spherical camera system
*
* @author Ahmed
* @version: $Id: KeySphericalCameraZoom.java, Dec 7, 2004 4:44:57 PM
*/
public class KeySphericalCameraZoom extends KeyInputAction {
// a reference to the camera handler
private SphericalCameraManager camHandler;
// the new goal
private float newGoal;
/**
* Constructor for the <code>KeySphericalCameraZoom</code>
* KeyInputAction. It zooms out the camera by a set amount.
* @param camH
*/
public KeySphericalCameraZoom(SphericalCameraManager camH) {
this.camHandler = camH;
}
/**
* Set the new zoom on the camera in absolute values
* @param goal
*/
public void setNewZoomGoal(float goal) {
newGoal = goal;
}
/**
* Get the zoom on the camera in absolute values
* @return
*/
public float getNewZoomGoal() {
return newGoal;
}
/**
* Zoom in and out of the camera thing.
*/
public void performAction(InputActionEvent evt) {
camHandler.setGoalDistance(newGoal);
}
}
KeySphericalCameraDown
/*
* Copyright (c) 2003-2004, jMonkeyEngine - Mojo Monkey Coding
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the Mojo Monkey Coding, jME, jMonkey Engine, nor the
* names of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.jme.input.action;
import com.jme.input.action.InputActionEvent;
import com.jme.input.action.KeyInputAction;
import com.jme.input.action.SphericalCameraManager;
/**
* <code>KeySphericalCameraDown</code> changes the phi value
* of the <code>SphericalCameraManager</code>
*
* @author Ahmed
* @version: $Id: KeySphericalCameraDown.java, Dec 5, 2004 3:15:55 PM
*/
public class KeySphericalCameraDown extends KeyInputAction {
// a reference to the cam manager
private SphericalCameraManager camHandler;
/**
* Constructor takes a reference to the cam manager so
* that it can change its values
* @param manager
*/
public KeySphericalCameraDown(SphericalCameraManager manager) {
this.camHandler = manager;
setAllowsRepeats(true);
setSpeed(1);
}
/**
* When the key is pressed, change the phi value
*/
public void performAction(InputActionEvent event) {
float phi = camHandler.getPhiGoal();
phi += event.getTime() * getSpeed();
camHandler.setPhiGoal(phi);
}
}
KeySphericalCameraUp
/*
* Copyright (c) 2003-2004, jMonkeyEngine - Mojo Monkey Coding All rights
* reserved. Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. Redistributions in binary
* form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided
* with the distribution. Neither the name of the Mojo Monkey Coding, jME,
* jMonkey Engine, nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written
* permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme.input.action;
import com.jme.input.action.InputActionEvent;
import com.jme.input.action.KeyInputAction;
import com.jme.input.action.SphericalCameraManager;
/**
* <code>KeySphericalCameraUp</code> changes the phi value of the
* <code>SphericalCameraManager</code>
*
* @author Ahmed
* @version: $Id: KeySphericalCameraUp.java, Dec 5, 2004 3:14:29 PM
*/
public class KeySphericalCameraUp extends KeyInputAction {
// a reference to the cam manager
private SphericalCameraManager camHandler;
/**
* Constructor takes a reference to the cam manager so that it can change
* its values
*
* @param manager
*/
public KeySphericalCameraUp(SphericalCameraManager manager) {
this.camHandler = manager;
setAllowsRepeats(true);
setSpeed(1);
}
/**
* When the key is pressed, change the phi value
*/
public void performAction(InputActionEvent event) {
float phi = camHandler.getPhiGoal();
phi += event.getTime() * getSpeed();
camHandler.setPhiGoal(phi);
}
}
KeySphericalCameraLeft
/*
* Copyright (c) 2003-2004, jMonkeyEngine - Mojo Monkey Coding All rights
* reserved. Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. Redistributions in binary
* form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided
* with the distribution. Neither the name of the Mojo Monkey Coding, jME,
* jMonkey Engine, nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written
* permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme.input.action;
import com.jme.input.action.InputActionEvent;
import com.jme.input.action.KeyInputAction;
import com.jme.input.action.SphericalCameraManager;
/**
* <code>KeySphericalCameraLeft</code> changes the theta value of the
* <code>SphericalCameraManager</code>
*
* @author Ahmed
* @version: $Id: KeySphericalCameraLeft.java, Dec 5, 2004 3:10:16 PM
*/
public class KeySphericalCameraLeft extends KeyInputAction {
// a reference to the cam manager
private SphericalCameraManager camHandler;
/**
* Constructor takes a reference to the cam manager so that it can change
* its values
*
* @param manager
*/
public KeySphericalCameraLeft(SphericalCameraManager manager) {
this.camHandler = manager;
setAllowsRepeats(true);
setSpeed(1);
}
/**
* When the key is pressed, change the theta value
*/
public void performAction(InputActionEvent event) {
float theta = camHandler.getThetaGoal();
theta -= event.getTime() * getSpeed();
camHandler.setThetaGoal(theta);
}
}
KeySphericalCameraRight
/*
* Copyright (c) 2003-2004, jMonkeyEngine - Mojo Monkey Coding All rights
* reserved. Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. Redistributions in binary
* form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided
* with the distribution. Neither the name of the Mojo Monkey Coding, jME,
* jMonkey Engine, nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written
* permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme.input.action;
import com.jme.input.action.InputActionEvent;
import com.jme.input.action.KeyInputAction;
import com.jme.input.action.SphericalCameraManager;
/**
* <code>KeySphericalCameraRight</code> changes the theta value of the
* <code>SphericalCameraManager</code>
*
* @author Ahmed
* @version: $Id: KeySphericalCameraRight.java, Dec 5, 2004 3:13:22 PM
*/
public class KeySphericalCameraRight extends KeyInputAction {
// a reference to the cam manager
private SphericalCameraManager camHandler;
/**
* Constructor takes a reference to the cam manager so that it can change
* its values
*
* @param manager
*/
public KeySphericalCameraRight(SphericalCameraManager manager) {
this.camHandler = manager;
setAllowsRepeats(true);
setSpeed(1);
}
/**
* When the key is pressed, change the theta value
*/
public void performAction(InputActionEvent event) {
float theta = camHandler.getThetaGoal();
theta += event.getTime() * getSpeed();
camHandler.setThetaGoal(theta);
}
}
SphericalCameraManager
package com.jme.input.action;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.scene.Spatial;
/**
* A class that converts spherical coordinates to caesterian coordinates.
*
* @author Ahmed
* @version: $Id: SphericalCameraManager.java, Dec 4, 2004 7:45:59 PM
*/
public class SphericalCameraManager {
// The maximum phi that it can be
public static final float MAX_PHI = 179F * FastMath.DEG_TO_RAD;
public static final float MIN_PHI = 1.0F * FastMath.DEG_TO_RAD;
// some references to objects declared outside
private Camera cam;
private Spatial target;
// theta, phi and the goalDistance are part of the spherical
// coordinates.
//
// http://www.math.montana.edu/frankw/ccp/multiworld/multipleIVP/spherical/body.htm
//
// explains it pretty well
private float theta;
private float phi;
private float goalDistance;
// add some displacement to the target so its not
// always centered
private Vector3f displacement;
// some vector3fs that will be used in the
// update cycle. Created once so that no furthur
// object instatiation takes place.
private Vector3f cameraPos;
private Vector3f cameraGoalPos;
private Vector3f targetPos;
private Vector3f dirVec;
private Vector3f upVec;
private Vector3f leftVec;
// the same with floats, but not as severly
private float distance;
private float thetaDelta;
private float phiDelta;
private float x;
private float y;
private float z;
/**
* Constructor for the Spherical Camera manager. The first three are the
* spherical coordinates and the last is the camera on which this class will
* act on.
*
* @param theta
* @param phi
* @param distance
* @param cam
*/
public SphericalCameraManager(float theta,
float phi,
float distance,
Camera cam) {
this.theta = theta;
this.phi = phi;
this.distance = distance;
this.theta = theta;
this.phi = phi;
goalDistance = distance;
this.cam = cam;
cameraPos = new Vector3f();
cameraGoalPos = new Vector3f();
targetPos = new Vector3f();
dirVec = new Vector3f();
upVec = new Vector3f();
}
/**
* Set the target aiming spot
*
* @param target
*/
public void setTarget(Spatial target) {
this.target = target;
}
/**
* Get the target aiming spot
*
* @return
*/
public Spatial getTarget() {
return target;
}
/**
* Set the distance the camera should stay away from the object
*
* @param goal
*/
public void setGoalDistance(float goal) {
goalDistance = goal;
}
/**
* Get the distance the camera should stay away from the object
*
* @return
*/
public float getGoalDistance() {
return goalDistance;
}
/**
* Set the Theta (Horizontal angle) of the sphere coordinates
*
* @param th
*/
public void setThetaGoal(float th) {
theta = th;
}
/**
* Get the Theta (Horizontal angle) of the sphere coordinates
*
* @return
*/
public float getThetaGoal() {
return theta;
}
/**
* Set the Phi (the yaw) of the sphere coordinates
*
* @param phi
*/
public void setPhiGoal(float phi) {
if (this.phi > MAX_PHI) {
this.phi = MAX_PHI;
} else if (this.phi < MIN_PHI) {
this.phi = MIN_PHI;
}
}
/**
* Get the Phi (yaw) of the sphere coordinates
*
* @return
*/
public float getPhiGoal() {
return phi;
}
/**
* Set the displacement of the target
*
* @param dis
*/
public void setDisplacement(Vector3f dis) {
this.displacement = dis;
}
/**
* Get the displacement of the target
*
* @return
*/
public Vector3f getDisplacement() {
return displacement;
}
/**
* Convert the spherical into caesterian and set it to the camera. Also make
* the camera look directly at the object
*
* @param interpolation
*/
public void update(float interpolation) {
// set the target position as the current
// position of our reference spatial
targetPos.x = target.getLocalTranslation().x;
targetPos.y = target.getLocalTranslation().y;
targetPos.z = target.getLocalTranslation().z;
// also add some displacement if there is any
targetPos.add(displacement);
// set the position of the camera as to where it
// actually is
cameraPos.x = cam.getLocation().x;
cameraPos.y = cam.getLocation().y;
cameraPos.z = cam.getLocation().z;
// add the detal distance between itself
// and the goal distance
distance += (goalDistance - distance);
// convert spherical coordinates to caesterian
// although do em wrong! but it still works...
z = distance * FastMath.cos(theta) * FastMath.sin(phi);
x = distance * FastMath.sin(theta) * FastMath.sin(phi);
y = distance * FastMath.cos(phi);
// add the camera's goal position to its position
// so we get an absolute target
cameraGoalPos.x = x + targetPos.x;
cameraGoalPos.y = y + targetPos.y;
cameraGoalPos.z = z + targetPos.z;
// set the position of the camera to what it should be
// either interpolate or just set it to the position
// depending on the interpolation number
if (interpolation != 0) {
cameraPos.interpolate(cameraGoalPos, interpolation);
} else {
cameraPos.x = cameraGoalPos.x;
cameraPos.y = cameraGoalPos.y;
cameraPos.z = cameraGoalPos.z;
}
cam.setLocation(cameraPos);
// look at the target
lookAtTarget();
}
// look at the target by using a simple algorithm
private void lookAtTarget() {
dirVec.x = 0.0f;
dirVec.y = 0.0f;
dirVec.z = 0.0f;
// find the distance between the target and the camera, then
// normalise it
dirVec.set(targetPos).subtractLocal(cameraPos).normalizeLocal();
// obtain the UP vector of the camera
upVec.x = cam.getUp().x;
upVec.y = cam.getUp().y;
upVec.z = cam.getUp().z;
// find the left by doing a cross product between
// the up and the direction. Normalise to obtain
// a direction
leftVec = upVec.cross(dirVec).normalizeLocal();
// now find the proper up by doing the cross product
// between the direction and the left and normalise
// to obtain a direction
upVec = dirVec.cross(leftVec).normalizeLocal();
// set the axis of the camera as that.
cam.setAxes(leftVec, upVec, dirVec);
cam.onFrameChange();
}
}
SphericalMouseLook
package com.jme.input.action;
import com.jme.input.Mouse;
import com.jme.input.MouseInput;
import com.jme.input.RelativeMouse;
import com.jme.input.action.InputActionEvent;
import com.jme.input.action.MouseInputAction;
/**
* A MouseInputAction that performs tracks an object based on certain
* parameters. Phi (how high in the sphere are we). Theta (horizontal) and the
* distance (the radius of the circle). It will track
*
* @author Ahmed
* @version: $Id: SphericalMouseLook.java, Dec 4, 2004 7:45:59 PM
*/
public class SphericalMouseLook implements MouseInputAction {
// how to track the object. Ie. axis lock
public static final int SML_TRACK_HORIZONTALLY = 0;
public static final int SML_TRACK_VERTICALLY = 1;
public static final int SML_TRACK_HORIZONTALLY_AND_VERTICALLY = 2;
public static final int SML_TRACK_SPEED_ACCURATE = 4;
public static final int SML_TRACK_SPEED_INTERPOLATE = 5;
// which axis to lock
private int axisLock;
// how to position the camera
private int positionMode;
// is the mouse wheel responsible for zoom?
private boolean wheelZoom;
// some standard values about speed that can be changed
private float speed = 1;
private float trackingSpeed = 0;
private float wheelSpeed = 0.2f;
// some references to pre determined objects
private RelativeMouse mouse;
private SphericalCameraManager camHandler;
private MouseInput input;
// mojo?! a key in the mouse input?
private String key;
// action keys to associate a camera movement with the
// press of a key. This is immitated by the movement of a
// mouse
private KeySphericalCameraLeft left;
private KeySphericalCameraRight right;
private KeySphericalCameraDown down;
private KeySphericalCameraUp up;
private KeySphericalCameraZoom zoom;
// the input action event that will be triggered when
// the mouse moves. Only the time will be set
private InputActionEvent event;
/**
* A constructor that creates the MouseAction. It takes a predefined
* SphericalCameraManager as an argument for processing.
*
* @param mouse
* @param camHandler
*/
public SphericalMouseLook(Mouse mouse, SphericalCameraManager camHandler) {
this.mouse = (RelativeMouse) mouse;
this.camHandler = camHandler;
input = mouse.getMouseInput();
axisLock = SphericalMouseLook.SML_TRACK_HORIZONTALLY;
// initialise the keyInput actions
left = new KeySphericalCameraLeft(camHandler);
right = new KeySphericalCameraRight(camHandler);
up = new KeySphericalCameraUp(camHandler);
down = new KeySphericalCameraDown(camHandler);
zoom = new KeySphericalCameraZoom(camHandler);
// initialise the event
event = new InputActionEvent();
}
/**
* Perform the required action which is to incriment theta by the given
* amount moved by the mouse. Then update the SphericalCameraManager to
* convert theta and phi to caesterian coordinates
*/
public void performAction(InputActionEvent evt) {
int inputXDelta = input.getXDelta();
int inputYDelta = input.getYDelta();
float time = evt.getTime();
event.setTime(time * getSpeed() * 5);
// get theta and phi
float thetaGoal = camHandler.getThetaGoal();
float phiGoal = camHandler.getPhiGoal();
// update theta and phi according to which
// axis is meant to be locked to
if (axisLock == SphericalMouseLook.SML_TRACK_HORIZONTALLY) {
// check to see which way the mouse has moved
// and perform the correct action
if (inputXDelta > 0) {
right.performAction(event);
} else if (inputXDelta < 0) {
left.performAction(event);
}
} else if (axisLock == SphericalMouseLook.SML_TRACK_VERTICALLY) {
// check to see which way the mouse has moved
// and perform the correct action
if (inputYDelta == 1) {
up.performAction(event);
} else if (inputYDelta < 0) {
down.performAction(event);
}
//phiGoal += (float) input.getYDelta() * time;
} else if (axisLock == SphericalMouseLook.SML_TRACK_HORIZONTALLY_AND_VERTICALLY) {
// check to see which way the mouse has moved
// and perform the correct action
if (inputXDelta == 1) {
right.performAction(event);
} else if (inputXDelta < 0) {
left.performAction(event);
}
// check to see which way the mouse has moved
// and perform the correct action
if (inputYDelta == 1) {
up.performAction(event);
} else if (inputYDelta < 0) {
down.performAction(event);
}
// check to see if the wheel zoom is enabled or
// not
if (wheelZoom == true) {
// set the camera's zoom by settings its distance
float zoomValue = camHandler.getGoalDistance() - (input.getWheelDelta() * wheelSpeed);
zoom.setNewZoomGoal(zoomValue);
zoom.performAction(event);
}
}
}
/**
* Set the speed of movement
*/
public void setSpeed(float speed) {
this.speed = speed;
}
/**
* Get the Speed of movement
*/
public float getSpeed() {
return speed;
}
/**
* How fast should the camera react. A typical value is 10
*
* @param speed
*/
public void setTrackingSpeed(float speed) {
this.trackingSpeed = speed;
}
/**
* How fast is the camera tracking the movement
*
* @return
*/
public float getTrackingSPeed() {
return trackingSpeed;
}
/**
* Set the mouse input for this action
*/
public void setMouse(Mouse mouse) {
if (mouse instanceof RelativeMouse) {
this.mouse = (RelativeMouse) mouse;
} else {
throw new ClassCastException(
"The Mouse Supplied in SphericalMouseLock is not of RelativeMouse type");
}
}
/**
* Get the mouse of this inputAction;
*
* @return
*/
public RelativeMouse getMouse() {
return mouse;
}
/**
* Which axis to lock to
*
* @param mode
*/
public void setAxisLock(int mode) {
axisLock = mode;
}
/**
* Which axis (if any) have been locked to
*
* @return
*/
public int getAxisLock() {
return axisLock;
}
/**
* Set the wheel lock. If true, the wheel zoom is enabled if false, wheel
* zoom is disabled.
*
* @param locked
*/
public void setWheelZoomEnabled(boolean locked) {
wheelZoom = locked;
}
/**
* Get the wheel zoom status
*
* @return
*/
public boolean getWheelZoomEnabled() {
return wheelZoom;
}
/**
* Set the wheel speed for the zoom
* @param speed
*/
public void setWheelSpeed(float speed) {
this.wheelSpeed = speed;
}
/**
* Get the wheel speed for the zoom
* @return
*/
public float getWheelSpeed() {
return wheelSpeed;
}
/**
* Set to which way the camera behaves. Valid values are: <br>
* SphericalMouseLock.SML_TRACK_SPEED_ACCURATE <br>
* and <br>
* SphericalMouseLock.SML_TRACK_SPEED_ACCURATE
*
* @param mode
*/
public void setCameraPositionMode(int mode) {
positionMode = mode;
}
/**
* Get to which mode the camera positions itself
*
* @return
*/
public float getCameraPositionMode() {
return positionMode;
}
public SphericalCameraManager getSphericalCameraManager() {
return camHandler;
}
public void setSphericalCameraManager(SphericalCameraManager man) {
camHandler = man;
}
/**
* Mojo? A key in a mouse action?
*/
public void setKey(String key) {
this.key = key;
}
/**
* Dont get it!
*/
public String getKey() {
return key;
}
}
ThirdPersonHandler
package com.jme.input;
import com.jme.app.AbstractGame;
import com.jme.input.InputHandler;
import com.jme.input.InputSystem;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.RelativeMouse;
import com.jme.input.action.KeyExitAction;
import com.jme.input.action.KeySphericalCameraDown;
import com.jme.input.action.KeySphericalCameraLeft;
import com.jme.input.action.KeySphericalCameraRight;
import com.jme.input.action.KeySphericalCameraUp;
import com.jme.input.action.SphericalCameraManager;
import com.jme.input.action.SphericalMouseLook;
import com.jme.math.FastMath;
import com.jme.renderer.Camera;
import com.jme.scene.Spatial;
/**
* A Simple, extendable ThirdPersonHandler.
*
* @author Ahmed
* @version: $Id: ThirdPersonHandler.java, Dec 4, 2004 8:44:00 PM
*/
public class ThirdPersonHandler extends InputHandler {
// the keyboard manager
private KeyBindingManager keyboard;
// the relative mouse
private RelativeMouse mouse;
// the spherical mouse look input action
private SphericalMouseLook sml;
// the cameraManager
private SphericalCameraManager camH;
// the actions
private KeySphericalCameraLeft left;
private KeySphericalCameraRight right;
private KeySphericalCameraUp up;
private KeySphericalCameraDown down;
/**
* Constructor to initialise the ThirdPersonHandler
*
* @param app
* the application to which this input belongs to
* @param cam
* the camera
* @param spat
* the spatial to follow
* @param distance
* the distance to keep away from the spatial
* @param renderer
* the name of the renderer
*/
public ThirdPersonHandler(AbstractGame app,
Camera cam,
Spatial spat,
float distance,
String renderer) {
InputSystem.createInputSystem(renderer);
setKeyBindings(app);
setMouse();
setActions(app, spat, distance, cam);
}
/**
* Sets the "Exit" key input action
*
* @param app
*/
private void setKeyBindings(AbstractGame app) {
keyboard = KeyBindingManager.getKeyBindingManager();
keyboard.setKeyInput(InputSystem.getKeyInput());
keyboard.set("exit", KeyInput.KEY_ESCAPE);
keyboard.set("left", KeyInput.KEY_A);
keyboard.set("right", KeyInput.KEY_D);
keyboard.set("up", KeyInput.KEY_W);
keyboard.set("down", KeyInput.KEY_S);
setKeyBindingManager(keyboard);
}
/**
* Creates the mouse needed for the spherical mouse look
*/
private void setMouse() {
mouse = new RelativeMouse("Mouse Input");
mouse.setMouseInput(InputSystem.getMouseInput());
this.setMouse(mouse);
}
/**
* Set the actions
*
* @param app
* @param spat
* @param distance
*/
private void setActions(AbstractGame app, Spatial spat, float distance, Camera cam) {
// exit
KeyExitAction exit = new KeyExitAction(app);
exit.setKey("exit");
addAction(exit);
// the camera manager
camH = new SphericalCameraManager(0, 90 * FastMath.DEG_TO_RAD, distance, cam);
camH.setTarget(spat);
// left key
left = new KeySphericalCameraLeft(camH);
left.setKey("left");
addAction(left);
// right key
right = new KeySphericalCameraRight(camH);
right.setKey("right");
addAction(right);
// up Key
up = new KeySphericalCameraUp(camH);
up.setKey("up");
addAction(up);
// down key
down = new KeySphericalCameraDown(camH);
down.setKey("down");
addAction(down);
// mouse look
sml = new SphericalMouseLook(mouse, camH);
addAction(sml);
}
public void setGeneralSpeed(float speed) {
left.setSpeed(speed);
right.setSpeed(speed);
up.setSpeed(speed);
down.setSpeed(speed);
sml.setSpeed(speed);
}
/**
* super.update(time) and update the SphericalCameraManager too
*/
public void update(float time) {
super.update(time);
// update the camera handler according to the
// mode set
if (sml.getCameraPositionMode() == SphericalMouseLook.SML_TRACK_SPEED_INTERPOLATE) {
camH.update(time * sml.getTrackingSPeed());
} else if (sml.getCameraPositionMode() == SphericalMouseLook.SML_TRACK_SPEED_ACCURATE) {
camH.update(0);
}
}
/**
* Get the SphericalMouseLook of this inputHandler
*
* @return
*/
public SphericalMouseLook getSphericalMouseLook() {
return sml;
}
}
Phewwwf, after all that, the test:
TestSphericalCamera
/*
* Copyright (c) 2003-2004, jMonkeyEngine - Mojo Monkey Coding All rights
* reserved. Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. Redistributions in binary
* form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided
* with the distribution. Neither the name of the Mojo Monkey Coding, jME,
* jMonkey Engine, nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written
* permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jmetest.input;
import java.net.URL;
import com.jme.app.SimpleGame;
import com.jme.image.Texture;
import com.jme.input.ThirdPersonHandler;
import com.jme.input.action.SphericalMouseLook;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.util.TextureManager;
/**
* @author Ahmed
* @version: $Id: TestSphericalCamera.java, Dec 4, 2004 7:45:59 PM
*/
public class TestSphericalCamera extends SimpleGame {
protected void simpleInitGame() {
rootNode = new Node("Root Node");
Box box = new Box("Simple Box", new Vector3f(0, 0, 0), 1, 1, 1);
box.getLocalTranslation().z = -25;
rootNode.attachChild(box);
URL imgURL = TestSphericalCamera.class.getClassLoader()
.getResource("jmetest/data/images/Monkey.jpg");
TextureState mnkyTS = display.getRenderer().createTextureState();
mnkyTS.setEnabled(true);
mnkyTS.setTexture(TextureManager.loadTexture(imgURL,
Texture.FM_LINEAR,
Texture.MM_LINEAR_LINEAR,
true));
box.setRenderState(mnkyTS);
Box box2 = new Box("Simple Box 2", new Vector3f(0, -5, 0), 50, 2, 50);
box2.setSolidColor(new ColorRGBA(0, 1, 1, 0.5f));
rootNode.attachChild(box2);
ZBufferState zEnabled = display.getRenderer().createZBufferState();
zEnabled.setEnabled(true);
rootNode.setRenderState(zEnabled);
input = new ThirdPersonHandler(this, display.getRenderer().getCamera(),
box, 15, properties.getRenderer());
ThirdPersonHandler tph = (ThirdPersonHandler) input;
tph.getSphericalMouseLook()
.setAxisLock(SphericalMouseLook.SML_TRACK_HORIZONTALLY);
tph
.getSphericalMouseLook()
.setCameraPositionMode(SphericalMouseLook.SML_TRACK_SPEED_ACCURATE);
rootNode.updateGeometricState(0.0f, true);
rootNode.updateRenderState();
}
protected void reinit() {
}
protected void cleanup() {
}
public static void main(String[] args) {
TestSphericalCamera app = new TestSphericalCamera();
app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
app.start();
}
}
Tired after all that copy/pasting! DP