I have my own SimpleCanvasImpl extension with some objects in scene. For move I used FirstPersonHandler (WASD and mouse moving). It looks like this (I missed irelevant code):
public class MyCanvas extends SimpleCanvasImpl {
private FirstPersonHandler moveHandler;
private InputHandler input;
public void simpleSetup() {
moveHandler = new FirstPersonHandler(cam, 30f, 2f);
input = moveHandler;
}
public void simpleUpdate() {
rootNode.updateRenderState();
input.update(tpf);
}
}
And now my problem. When I press "L" key, I need to change camera direction to one defined scene Spatial and lock view direction on it. So when I press WASD keys or mouse, camera will rotate around that Spatial.
I tried ChaseCamera, but when I do this
chaseCam = new ChaseCamera(cam, selectedObject);
input = chaseCam;
camera location changed (I need only to change direction to selectedObject) and I can't rotate object 360
It sounds like you want something similar to chase camera, but without all its bells and whistles. If I understand you correctly you want:
(1) Camera to rotate about an arbitrary point
(2) Camera to always be focused on that arbitrary point
(3) Only rotate on input from user
You can easily accomplish that with a little planning, and borrowing the spherical coordinate rotation code from the chase camera class. It has everything you need, you just need to simplify. If you get stuck, post what you have and I can help you out.
I began to study ChaseCamera class and I found that provides all what I need EXCEPT one thing - rotation around all axis. First I thought problem is updateIdealAzimuth method, but when I have extended ChaseCamera and override this method I still can't rotate around all axis. Then I found worldUpVec variable, but when I change it, I still can rotate around y axis of 360 degrees only. Around x and z axis I can rotate, but only few degrees :(
But the worst thing is that I cant find a solution…
Camera location [3, 2, 3] - I want smoothly rotate with camera around Spatial to most far location [-2, -1, -2] and back
Camera location [5, 5, 1] - rotation about Spatial to [-4. -4. 0]
…
I found lot of tutorial how do something like this, but in all is y coordinate constant during camera movement. But here isn't any coord constant, all are changing.
Is there some class in jme what provide me cyrcle rotation defined by pivot and point locations? Or something else what could help me?
... and it looks good - getNewLook() method return new camera location based on target location, distance between camera and target, camera up-direction, angle what camera moved and previous camera location.
But I have one more problem with this - if position == 0 then getNewLook() method returns position near target's [0, 0, -z] local coords. And I dont know how found right position angle if I dont want change actual camera location...
public class AdvancedCamera {
private static AdvancedCamera myself;
private Camera cam;
private CameraMode currentmode = CameraMode.Free;
//Rotation Mode Variables
private float[] RotationAngles = new float[3];
private Node RotationWorld = new Node("RotationWorld");
public Node getRotationWorld() {
return RotationWorld;
}
private Node RotationCenter = new Node("RotationCenter");
private Node RotationCameraPosition = new Node("RotationCameraPosition");
Quaternion roationquat = new Quaternion();
private Vector3f WorldUp = new Vector3f(0,1,0);
private Vector3f FreeLocation = new Vector3f(0,0,0);
private boolean ignorecollision;
private Quaternion FreeQuaternion = new Quaternion();
static public enum CameraMode {ThirdPerson,FirstPerson,RotatePoint,Free}
public AdvancedCamera(Camera cam){
if(myself != null){
Console.println("Attempting to create second Camera Controller");
System.exit(100);
}
this.cam = cam;
myself = this;
RotationWorld.attachChild(RotationCenter);
RotationCenter.attachChild(RotationCameraPosition);
Box center = new Box("CenterTestBox",new Vector3f(0,0,0),1,2,1);
RotationCenter.attachChild(center);
RotationCenter.updateRenderState();
Box cambox = new Box("CamTestBox",new Vector3f(0,0,0),1,1,2);
//RotationCameraPosition.attachChild(cambox);
RotationCameraPosition.updateRenderState();
Quaternion lookatcenterrotation = new Quaternion();
lookatcenterrotation.fromAngles(FastMath.HALF_PI,FastMath.HALF_PI,0);
RotationCameraPosition.setLocalRotation(lookatcenterrotation);
RotationCameraPosition.addController(new Controller(){
private static final long serialVersionUID = 1L;
Vector3f axis = new Vector3f(0,1,0);
float anglep = 0 ;
float angley = 0 ;
//Rotation Code
public void SetRotationCenter(Vector3f center){
Console.println("Rotation Center now at " + center);
RotationCenter.setLocalTranslation(center);
}
public void SetRotationAngles(float pitch,float yaw,float roll){
RotationAngles[0] = yaw;
RotationAngles[1] = roll;
RotationAngles[2] = pitch;
roationquat.fromAngles(RotationAngles);
RotationCenter.setLocalRotation(roationquat);
Console.println("Rotation now at " + pitch + " " + yaw + " " + roll);
Console.println("Rotation now at " + roationquat);
}
public void SetRotationDistance(float distance){
RotationCameraPosition.setLocalTranslation(0,distance,0);
Console.println("Rotation Distane now at " + RotationCameraPosition.getLocalTranslation());
}
public Vector3f GetRotationCenter() {
return RotationCenter.getLocalTranslation();
}
// Freecam mode
public Vector3f getFreeLocation() {
return FreeLocation;
}
public void setFreeLocation(Vector3f freeLocation) {
FreeLocation = freeLocation;
}
public Quaternion getFreeQuaternion() {
return FreeQuaternion;
}
public void setFreeQuaternion(Quaternion freeQuaternion) {
FreeQuaternion = freeQuaternion;
}
public static AdvancedCamera Get(){
return myself;
}
public void SetMode(CameraMode mode){
Console.println("Changing CameraMode to " + mode.name());
currentmode = mode;
}
public void Update(){
switch(currentmode){
case Free :{
cam.setLocation(FreeLocation);
cam.setAxes(FreeQuaternion);
break;
}
case RotatePoint :{
RotationWorld.updateGeometricState(1,true);
Vector3f worldvec = new Vector3f(0,1,0);
//RotationCameraPosition.lookAt(RotationCenter.getWorldTranslation(),worldvec);
cam.setFrame(RotationCameraPosition.getWorldTranslation(),RotationCameraPosition.getWorldRotation());
// System.out.println(RotationCameraPosition.getWorldTranslation());
break;
}
}
}