pouët.net

Camera rotation based on Camera.view > target vector

category: general [glöplog]
Here it's a newbie questions.

I have a Camera object, with a target, and I'm trying to get the rotationX, rotationY, rotationZ of the camera (which is later used on the raster loop) from the Camera.view > Camera.target vector.

This is more or less what I have so far (yes, you can laugh):

Code:var vector : Point3D = new Point3D(); vector.add(this); // view vector vector.sub(target); vector.normalise(); rotationX = Math.atan2(vector.y, vector.z); rotationY = -Math.atan2(vector.z, vector.x) + NumberUtils.deg2rad(90); rotationZ = Math.atan2(vector.y, vector.x);


But I'm not getting too far, it's hard to control what's going on... Any ideas?
added on the 2009-01-16 19:11:42 by mrdoob mrdoob
hum? if you take the dot-product of the camera vector and target vector you get the cosine-angle between them. im not sure if that's what you're out after?
added on the 2009-01-16 19:36:17 by rudi rudi
maybe if u tell why you need these rotationx rotationy it will be simplier...
added on the 2009-01-16 19:38:17 by Tigrou Tigrou
trace, with rotationx and rotationy (if these are width and height in the screen), you should make the scene look in the direction of the camera. Then the rotation z is just the roll
added on the 2009-01-16 19:46:33 by texel texel
rydi is right but why do you need the rotation angles at all? usually you set up a camera matrix and then work with that matrix instead of individual rotation angles ?!

added on the 2009-01-16 19:48:15 by xyz xyz
hermes, the rotation matrix is the same as rotating by angles... I suppose trace want to do it with angles because his engine is based in rotations... so he doesn't have to make the matrix multiplier
added on the 2009-01-16 19:49:40 by texel texel
trace: you can read about Camera matrix.

Also, about the cameras based in 2 vertex (eye and target). The vector of it doesn't contain all the camera information, you don't have the roll. The roll should be stored elsewhere. (Also, you don't have the fov and any other camera properties)

added on the 2009-01-16 19:52:45 by texel texel
cheap CPU-wise....is intelligent ! why burn cycles for unneeded math ? ( directX suxx btw ;) )
texel: no, the rotation matrix is usually used to rotate around two or three vectors if one counts the up-vector as the latter one.
added on the 2009-01-16 19:54:28 by rudi rudi
dont forget to perspective project your 3d-coordinates before rasterization. that's not a bad thing to do. :)
added on the 2009-01-16 19:57:01 by rudi rudi
rydi, sorry, I wrote it not very good... What I wanted to say is that with a rotation matrix you can do the same as doing 3 rotations at the same time.
added on the 2009-01-16 19:59:55 by texel texel
cocoon, I believe he is coding in Flash, so no DX
added on the 2009-01-16 20:00:43 by texel texel
Code:vector = (target-this)^0 rotation_y = atan2(vector.x, vector.z) rotation_x = atan2(|vector.xz|, vector.y) rotation_z = 0


i keep forgetting which way atan2 takes its parameters, which handed the coordinates are etc but with enough permuting you should get it right :)
added on the 2009-01-16 20:00:56 by 216 216
the up vector is just like (0,0,1); you can tweak these values.
to get the camera working you can try this code...

Code: void Camera(Vector &pos, Vector &tar, Vector &up) { Vector n = eye - tar; Vector u = crossproduct(up, n); u.Normalize(); n.Normalize(); Vector v = crossproduct(n, u); //create the viewmatrix float viewmatrix[16] = { u.X, v.X, n.X, 0.0f, u.Y, v.Y, n.Y, 0.0f, u.Z, v.Z, n.Z, 0.0f, -(pos * u), -(pos * v), -(pos * n), 1.0f } //multiply matrix with all vertices or something.. }
added on the 2009-01-16 20:06:00 by rudi rudi
multiplying the matrix with your object/world-space vectors you can just make a function that does this for you:

//nv is the new translated vector and can be rasterized after the perspective projection transform.

Vector nv;
float *m = &viewmatrix;

//usually you lookup vector-coords via face/triangle-indeces before transformation, but here are the matrix->vector multiplier:

for (int i=0; i<object->num_vertices; i++)
{
Vector *v = object->get_vertex(i);
nv.x = m[0] * v->x + m[1] * v->y + m[2] * v->z;
nv.y = m[3] * v->x + m[4] * v->y + m[5] * v->z;
nv.z = m[6] * v->x + m[7] * v->y + m[8] * v->z;

//perspective transform (3d->2d screencoordinates)

//rasterize with new coords
}
added on the 2009-01-16 20:30:15 by rudi rudi
bah the last code was messy and probably wrong too, here's a new one:

anyway, you get the idea... just tweak the values until it works :P

Code: //nv is the new translated vector and can be rasterized after the perspective projection transform. Vector nv; float *m = &viewmatrix; //usually you lookup vector-coords via face/triangle-indeces before transformation, but here are the matrix->vector multiplier: for (int i=0; i<object->num_vertices; i++) { Vector *v = object->get_vertex(i); nv.x = m[0] * v->x + m[1] * v->y + m[2] * v->z; nv.y = m[4] * v->x + m[5] * v->y + m[6] * v->z; nv.z = m[8] * v->x + m[9] * v->y + m[10] * v->z; nv.w = m[12] * v->x + m[13] * v->y + m[14] * v->z; //perspective transform (3d->2d screencoordinates) //rasterize with new coords }
added on the 2009-01-16 20:34:01 by rudi rudi
Just to clear things up, this is the projection code I have. I think it's the called euler angles transformation.. or something, I'm really bad for names... It was just faster than matrix transformations (all this is for flash/actionscript).

Code:x1 = (point.x * mesh.scaleX) * mesh.cosZ - (point.y * mesh.scaleY) * mesh.sinZ; y1 = (point.y * mesh.scaleY) * mesh.cosZ + (point.x * mesh.scaleX) * mesh.sinZ; x2 = x1 * mesh.cosY - (point.z * mesh.scaleZ) * mesh.sinY; z1 = (point.z * mesh.scaleZ) * mesh.cosY + x1 * mesh.sinY; y2 = y1 * mesh.cosX - z1 * mesh.sinX; z2 = z1 * mesh.cosX + y1 * mesh.sinX; x2 += mesh.x; y2 += mesh.y; z2 += mesh.z; x2 -= camera.x; y2 -= camera.y; z2 -= camera.z; x3 = x2 * camera.cosZ - y2 * camera.sinZ; y3 = y2 * camera.cosZ + x2 * camera.sinZ; z3 = z2 * camera.cosY + x3 * camera.sinY; x4 = x3 * camera.cosY - z2 * camera.sinY; y4 = y3 * camera.cosX - z3 * camera.sinX; z4 = z3 * camera.cosX + y3 * camera.sinX; point.sz = camera.focus / (camera.focus + ( camera.z - z4 )); point.sx = camera.target.x + x4 * point.sz; point.sy = camera.target.y - y4 * point.sz;


216 reply looks more like what I was after. I'm going to play a bit with that. Thanks everyone!
added on the 2009-01-16 21:42:52 by mrdoob mrdoob
forget about atan2 btw ;)

SLOW!
Cameras are serious business. I'm trying to figure out how to do a decent camera for ages.
added on the 2009-01-16 22:25:22 by xernobyl xernobyl
Slow doesn't matter if you only calculate angles say once per frame. The problem is that as previously mentioned two vertices don't contain all the information necessary for the world->camera space transform (roll is missing), so of course it's hard to control the behaviour of the camera when it has an undefined property.

You can maintain roll separately, but you have to invent that behaviour yourself. In the end you'll find it's much easier to think of camera space as three vectors moving around in world space. One points in the direction the camera is viewing, one points "up" (from the camera's perspective), always at a right angle to the first, and the third is perpendicular to the direction and the up vector. Translation from world space to camera space is then a straightforward change from one orthonormal basis to another.

So, take your camera position C, your target position T and an "up" vector u. This gives you:

Origin of camera space expressed in world space coordinates: C
Normalised direction vector: cz = (T - C)/dist(T, C)
Up vector: cy = u
Third vector/axis: cx = cz x cy (cross product)

With cx, cy and cz being column vectors, the camera matrix is then M = [ cx cy cz ]. Because M is orthonormal (all columns are vectors of length one and all are perpendicular), its inverse, M^-1, is equal to its transpose M^T, and then the translation of any point P from world to camera space is simply:

f( P ) = M^T * (P - C)

No sin or cos necessary, and no angles required. You also eliminate the headaches caused by the order in which you do the three separate rotations. On top of that, in code form, the above expression is much simpler than the code you pasted.

For a target camera, you still need some way to determine cy, but with this approach you only have to think of it as asking "from the observer's perspective, which direction is up?" Give any unambiguous answer like "up is as directly towards the sky as possible" or "up is towards this other point that I'm moving around along with the camera" or "up is as close as possible to what it was in the previous frame", and you'll always be able to construct a solution from that.

The same applies to your objects, actually. The whole thing gets soooo much simpler if they're described as meshes in local object spaces. You'll even find that the transformation from object to world to camera space reduces to a single matrix multiplication giving you the most FPS for your MHz.
added on the 2009-01-16 23:16:24 by doomdoom doomdoom
Well, using atan or atan2 won't affect much to performance... as I would be doing it only twice per camera movement position change. Is not that it's going to be done for each vertex/frame...
added on the 2009-01-16 23:16:27 by mrdoob mrdoob
Thanks a lot for the explanation "Christmas Device", it's all starting to make much more sense to my average mind. It also helped some raycasting tests I did recently.

I got the feeling I'll be moving my engine to matrix mode in the end. But this will be after I get this project I'm working on sorted out.
added on the 2009-01-16 23:27:54 by mrdoob mrdoob
Matrices ftw (beware of normals and lighting).
added on the 2009-01-17 01:58:32 by bdk bdk
alternatively, trace, pick up this thingy:

http://www.amazon.com/exec/obidos/ASIN/1556229119/

has all the basics in rather clear/pragmatic way.

dunno how far you wanna go with all this..
added on the 2009-01-17 05:18:32 by superplek superplek
I really thing the best way to learn is with rotations first, and then understand how it relates to matrices.

If you want, I can draw the rotation based way, to be easy to understand. With some illustrations it would be very easy.

Then, about matrices, I'm not sure if trace have knowledge of how matrices works, not sure if he studied it or not. Since matrices are powerful tools, it is interesting to learn it. But, just in the end, matrix multiplication are just a compact way to write a lot of sums/multiplies, and nothing more.

I believe it is really important to know what is being done in the background, and not just to implement a matrix multiplier and then some few formulas you got from a book without having an idea of what it does.
added on the 2009-01-17 05:44:38 by texel texel

login