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
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.
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]
whats centre?
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)
@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.
@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.
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
duhhh… my bad!!!
Thanks!!!