Rotate camera around point

Hi I would like to rotate the camera around a point but cannot see how this might be done.



As far as I can tell the camera is not attached to a node so I am stuck (I could calculate the position of the camera but rotating a node would be much simpler). How should I do this?



Thanks

Check out camera.lookAt :slight_smile:

well the ChaseCam can follow and rotate around a spatial. Might be worth looking at how the rotating is implemented there. I would guess you would just do cam.lookAt(point), and then orbit around using sin/cos.

1 Like
Check out camera.lookAt


this is only half the solution, and unfortunately it is the half I already understand. My problem is positioning the camera somewhere on the sphere of rotation if you will, of course I know the mathematics of a sphere but I don't want to have to do this, it would be much simpler to attach the camera to some sort of node, give it an offset and point the camera at the node, I can then just rotate and translate the node easily and the camera will follow nicely.

Problem is I don't think that there is a camera node. So I wondered if there were simple solutions I don't know of.

well the ChaseCam can follow and rotate around a spatial. Might be worth looking at how the rotating is implemented there..


Looked already and well... have you looked at it? I have no idea what it is doing lol, it seems like a complicated solution for a simple problem to me, well maybe not complicated but laborious and long winded.

I would guess you would just do cam.lookAt(point), and then orbit around using sin/cos


But we have all these nice OpenGL bindings for doing things like this, plus I prefer vectors and matrices to trig and theta for doing things like this.

I suppose there is no simple solution then, this is what I propose...

I am going to rotate the camera as if it was a static point, then I am going to get its facing using cam.getDirection() (assuming it is normalised) then I am going to multiply the resulting vector by a scalar (ie the offset in world units) then I will add this vector to a vector describing the centre of rotation (which is dynamic) and then I am going to set the cameras position using cam.setLocation(location) where location is the result of the previous step. That should work.

Thanks for replies

For those interested…



[java]

public void onAnalog(String name, float value, float tpf) {

if (name.equals("MOUSE_AXIS_LEFT")) {

if (leftMousePressed) {

rotateCamera(value, tpf, mainApp.getCamera().getUp());

}

} else if (name.equals("MOUSE_AXIS_RIGHT")) {

if (leftMousePressed) {

rotateCamera(-value, tpf, mainApp.getCamera().getUp());

}

} else if (name.equals("MOUSE_AXIS_UP")) {

if (leftMousePressed) {

rotateCamera(-value, tpf, mainApp.getCamera().getLeft());

}

} else if (name.equals("MOUSE_AXIS_DOWN")) {

if (leftMousePressed) {

rotateCamera(value, tpf, mainApp.getCamera().getLeft());

}

}

}



protected void rotateCamera(float value, float tpf, Vector3f axis){

float rotationSpeed = 1000;



Matrix3f mat = new Matrix3f();

mat.fromAngleNormalAxis(rotationSpeed * value * tpf, axis);



Vector3f upDir = mainApp.getCamera().getUp();

Vector3f leftDir = mainApp.getCamera().getLeft();

Vector3f dir = mainApp.getCamera().getDirection();



mat.mult(upDir, upDir);

mat.mult(leftDir, leftDir);

mat.mult(dir, dir);



Quaternion q = new Quaternion();

q.fromAxes(leftDir, upDir, dir);

q.normalizeLocal();



mainApp.getCamera().setAxes(q);



dir = mainApp.getCamera().getDirection();

dir = dir.mult(20.0f);

Vector3f invDir = new Vector3f(-dir.x, -dir.y, -dir.z);

Vector3f position = invDir.add(centre);

mainApp.getCamera().setLocation(position);

}

[/java]

2 Likes

whats centre?

@nightwolf911 said:
whats centre?


Most likely the point of pivot

I hope not cz that is exactly my problem… is how to get that pivot point (from camera lookAt)

I imagine that the camera is a chaseCam?



If so then…



[java]

chaseCam = new ChaseCamera(sceneCam, someSpatial);

[/java]



Keep a reference to “someSpatial” and get that spatial’s location.

no its not a chaseCam, it’s my regular main camera “cam”. I do not want to rotate around a spatial, but be able to orbit around whatever the camera is looking it (say a ray or whatever is the first thing it collides with)

1 Like
@nightwolf911 said:
(say a ray or whatever is the first thing it collides with)


Ahah! Useful information. (You cannot rotate around a "ray"... at least not in the sense that you mean... but you _can_ rotate around a point.)

So find the collision and rotate around that... you have a "specific point" in that case.

What's the problem again?

I think that is exactly what I was looking for, I’ll read up more about rays and collision. thanks for the hint guys

so I am getting the pivotPoint by using the first collision from a camera ray.



the method above does not work for me as I tested it by defining the centre as new Vector3f (2,2,2) and it does not rotate around it (but rotates weirdly somewhere completely different)



as for my previous code that used to orbit around the center, I modified it to the following:



(it does not orbit right as well :S)

[java]

Quaternion tempQuat = new Quaternion();

Quaternion camRot = new Quaternion();



Vector3f camPos = cam.getLocation();



if(camPos.x == 0.0 && camPos.y == 0.0)

{

logger.info(“Orbitting request denied - can’t orbit aorund center”);

}

else {



tempQuat.fromAngles(0, 0, tpf + 0.01f).multLocal(camPos);



camRot.lookAt(pivotPoint.subtract(camPos), new Vector3f(Vector3f.UNIT_Z));



cam.setLocation(pivotPoint.add(camPos));

cam.setRotation(camRot);

}



[/java]

In order to orbit all you need to do is:



Vector3f(1,0,0) offset; adjust 1 to whatever you want the radius of your sphere to be. Use whatever axis works best for you.



Quaternion rot; whatever your current rotation is. Adjust it however you like.



setLocation(centerPoint.add(rot.rotate(offset)))

(Note not addLocal).





Use the ray picking to find the collision point, use that as center.

[java]

Vector3f pivotPoint = results.getClosestCollision().getContactPoint(); // ok so far

Vector3f camPos = cam.getLocation(); // So now we have current position and center

Quaternion rot = new Quaternion(); // Should really cache this somewhere to avoid creating a new object each frame

rot.fromAngles(0, 0, tpf + 0.01f).multLocal(camPos); // This is where it goes wrong

cam.setLocation(pivotPoint.add(rot.mult(new Vector3f(1,0,0), Vector3f.UNIT_Z)));

[/java]



Try something along these lines:



[java]

Vector3f pivotPoint = results.getClosestCollision().getContactPoint(); // ok so far

Vector3f camPos = cam.getLocation(); // So now we have current position and center

Quaternion rot = new Quaternion(); // Should really cache this somewhere to avoid creating a new object each frame

rot.fromAngles(0,0,tpf+0.01f);

Vector3f difference = camPos.subtract(pivotPoint);

rot.multLocal(difference);

cam.setLocation(pivotPoint.add(difference));

cam.lookAt(pivotPoint);

[/java]



No guarantees the code works as I just typed it into the website and all function names are from memory - you should be able to pull the algorithm out of it though.

2 Likes
@nightwolf911 said:
Do you mean lke this?

[java] Vector3f pivotPoint = results.getClosestCollision().getContactPoint();

Vector3f camPos = cam.getLocation();
Quaternion rot = new Quaternion();
rot.fromAngles(0, 0, tpf + 0.01f).multLocal(camPos);

cam.setLocation(pivotPoint.add(rot.mult(new Vector3f(1,0,0), Vector3f.UNIT_Z)));
[/java]

that didn't work :S


You'd have to get the camera position relative to the pivot point, rotate it, _then_ add it back to the pivot point.

Edit: Didn't notice someone else had responded in more detail.
1 Like

just one more quick question, if I want to rotate negatively:



[java]rot.fromAngles(0,0,tpf-0.01f);[/java]



this makes the rotation not smooth (obviously because I am subtracting tpf) - how can I orbit in tht other way around?



thanks

dont subtract, multiply.



-0.01f*tpf

1 Like

duhhh… my bad!!!



Thanks!!!