I needed my Camera to rotate around an Object, so I searched the Internet for a good solution.
It seemed that many had the same issue, but there were few good explenations or examples.
For this reason I decided to share my Code.
I have written a class that controls the Camera. You can define a Point or Object which will be focused by the Camera.
When you touch the corners of the screen/window with your cursor, the camera moves around the object.
By scrolling you can zoom in and out.
Hope you guys like it…
package mygame;
import com.jme3.input.InputManager;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.math.Matrix3f;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Node;
import com.jme3.system.AppSettings;
/**
* StrategyCam
* Implements an AnalogListener that rotates the camera around a given object or Coordinate (Vector3f)
* when you touch the corners of the screen with your cursor.
*
* @author NKappler
*/
public class StrategyCam implements AnalogListener {
private Float movementSpeed = 1f; //rad per second
private AppSettings settings;
private InputManager inputManager;
private Camera cam;
private float camDistance = 10f;
private float camMinDistance = 2f;
private Vector3f camFocus = new Vector3f(0f, 0f, 0f);
private Boolean isEnabled;
private Boolean isMovingUp = false;
private Boolean isMovingDown = false;
private Boolean isMovingLeft = false;
private Boolean isMovingRight = false;
public StrategyCam(InputManager inputManager, AppSettings settings, Camera cam) {
this.inputManager = inputManager;
this.settings = settings;
this.cam = cam;
setFocus(camFocus, true);
this.isEnabled = true;
}
public void registerInput() {
inputManager.addMapping("rotateRight", new MouseAxisTrigger(MouseInput.AXIS_X, false));
inputManager.addMapping("rotateLeft", new MouseAxisTrigger(MouseInput.AXIS_X, true));
inputManager.addMapping("rotateUp", new MouseAxisTrigger(MouseInput.AXIS_Y, false));
inputManager.addMapping("rotateDown", new MouseAxisTrigger(MouseInput.AXIS_Y, true));
inputManager.addMapping("scrollUp", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));
inputManager.addMapping("scrollDown", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));
inputManager.addListener(this, "rotateRight", "rotateLeft", "rotateUp", "rotateDown", "scrollUp", "scrollDown");
}
public void onAnalog(String name, float value, float tpf) {
if (!isEnabled) return;
Vector2f cursorPosition = inputManager.getCursorPosition();
if (name.equals("rotateRight")) {
if (!isMovingRight && (cursorPosition.x >= settings.getWidth() - 2)) {
isMovingRight = true;
} else if (isMovingLeft && (cursorPosition.x > 3)) {
isMovingLeft = false;
}
}
else if (name.equals("rotateLeft")) {
if (isMovingRight && (cursorPosition.x < settings.getWidth() - 2)) {
isMovingRight = false;
} else if (!isMovingLeft && (cursorPosition.x <= 3)) {
isMovingLeft = true;
}
}
if (name.equals("rotateUp")) {
if (!isMovingUp && (cursorPosition.y >= settings.getHeight() - 2)) {
isMovingUp = true;
} else if (isMovingDown && (cursorPosition.y > 3)) {
isMovingDown = false;
}
}
else if (name.equals("rotateDown")) {
if (isMovingUp && (cursorPosition.y < settings.getHeight() - 2)) {
isMovingUp = false;
} else if (!isMovingDown && (cursorPosition.y <= 3)) {
isMovingDown = true;
}
}
if (name.equals("scrollUp")) {
if ((camDistance-3) >= camMinDistance) {
camDistance -= 3;
refresh();
}
}
if (name.equals("scrollDown")) {
camDistance += 3;
refresh();
}
}
private Matrix3f rotateHorizontal(float tpf) {
Matrix3f M = new Matrix3f();
M.fromAngleAxis(movementSpeed * tpf, Vector3f.UNIT_Y);
return M;
}
private Matrix3f rotateVertical(float tpf) {
Matrix3f M = new Matrix3f();
M.fromAngleAxis(movementSpeed * tpf, cam.getLeft());
return M;
}
public void moveCam(float tpf) {
if (!isEnabled) {
return;
}
if (!(isMovingDown || isMovingLeft || isMovingRight || isMovingUp)) {
return;
}
Vector3f camDirection = cam.getDirection().normalize();
Vector3f camPosition = cam.getLocation();
if (isMovingRight) {
camDirection = rotateHorizontal(tpf).mult(camDirection).normalize();
camPosition = camFocus.add(camDirection.negate().mult(camDistance));
} else if (isMovingLeft) {
camDirection = rotateHorizontal(tpf).invertLocal().mult(camDirection).normalize();
camPosition = camFocus.add(camDirection.negate().mult(camDistance));
}
if (isMovingUp && (camDirection.y > -0.98f)) {
camDirection = rotateVertical(tpf).mult(camDirection).normalize();
camPosition = camFocus.add(camDirection.negate().mult(camDistance));
} else if (isMovingDown && (camDirection.y < 0.98f)) {
camDirection = rotateVertical(tpf).invertLocal().mult(camDirection).normalize();
camPosition = camFocus.add(camDirection.negate().mult(camDistance));
}
cam.setLocation(camPosition);
cam.lookAtDirection(camDirection, Vector3f.UNIT_Y);
}
public void setFocus(Vector3f focus, boolean centered) {
camFocus = focus;
if (centered) {
cam.setLocation(new Vector3f(camFocus.x, camFocus.y, camFocus.y + camDistance));
} else {
cam.lookAt(camFocus, Vector3f.UNIT_Y);
cam.setLocation(camFocus.add(cam.getDirection().negate().mult(camDistance)));
}
}
public void setFocus(Node focus, boolean centered) {
camFocus = focus.getWorldTranslation();
if (centered) {
cam.setLocation(new Vector3f(camFocus.x, camFocus.y, camFocus.y + camDistance));
} else {
cam.lookAt(camFocus, Vector3f.UNIT_Y);
cam.setLocation(camFocus.add(cam.getDirection().negate().mult(camDistance)));
}
}
private void refresh() {
setFocus(camFocus, false);
if (camDistance - camMinDistance <= 3) {
movementSpeed = .5f;
}
else if (camDistance - camMinDistance > 10) {
movementSpeed = 2f;
} else {
movementSpeed = 1f;
}
}
}