Problems with Camera and the actual correct rotations of it in the start

Started by
7 comments, last by Skyy 15 years ago
Hello everybody. First, I'm sorry if this belongs to the math section, I wans't entirely sure but here I go... My scenario is this: I'm feeding my program with XML data so I can easily modify things outside compile time BUT my problem is since math isn't my strongest side is to get the camera to face the wanted direction in the beginning. Input to the camera: - Position the camera supposed to be lookking at (vector) - Position the camera is in (vector) Camera starts off on "facing"(?) the negative Z axis of the world in the given position and I need to turn the camera to face the "point of interest", so to say. I'm not interested in the "use gluLookAt"-style approaches. I'm interested in the math behind this and I'm kind of struggling with this. So what I'm after is help on how to calculate the X and Y rotations required to be facing at the given point of interest. Any help would be appreciated. Thank you.
Advertisement
Quote:Original post by Skyy
Hello everybody.

First, I'm sorry if this belongs to the math section, I wans't entirely sure but here I go...

My scenario is this:
I'm feeding my program with XML data so I can easily modify things outside compile time BUT my problem is since math isn't my strongest side is to get the camera to face the wanted direction in the beginning.

Input to the camera:
- Position the camera supposed to be lookking at (vector)
- Position the camera is in (vector)

Camera starts off on "facing"(?) the negative Z axis of the world in the given position and I need to turn the camera to face the "point of interest", so to say. I'm not interested in the "use gluLookAt"-style approaches. I'm interested in the math behind this and I'm kind of struggling with this. So what I'm after is help on how to calculate the X and Y rotations required to be facing at the given point of interest.

Any help would be appreciated.
To calculate the x and y rotations that will align the camera with the target point, you'll want to perform a Cartesian-to-spherical coordinate conversion. The input will be the vector from the camera position to the target position, and the output will be x and y rotation angles that you can then use to orient the camera (e.g. via glRotate*()).

Post back if you have questions or need more details.
I'll just cut and paste from my code since it's easier. I probably stole it from some book anyway:
   D3DXMATRIX V;   D3DXVECTOR3 clRight;   // Generate right vector   D3DXVec3Cross(&clRight, &clUp, &clFace);   float fX = -D3DXVec3Dot(&clRight, &clPos);   float fY = -D3DXVec3Dot(&clUp, &clPos);   float fZ = -D3DXVec3Dot(&clFace, &clPos);   V(0,0) = clRight.x;  V(0, 1) = clUp.x;    V(0, 2) = clFace.x;  V(0, 3) = 0.0f;   V(1,0) = clRight.y;  V(1, 1) = clUp.y;    V(1, 2) = clFace.y;  V(1, 3) = 0.0f;   V(2,0) = clRight.z;  V(2, 1) = clUp.z;    V(2, 2) = clFace.z;  V(2, 3) = 0.0f;   V(3,0) = fX;         V(3, 1) = fY;        V(3, 2) = fZ;        V(3, 3) = 1.0f;   m_pDevice->SetTransform(D3DTS_VIEW, &V);


So basically you start out with the clUp and clFace unit vectors and you get the rest from there. You can get clFace from subtracting your look at position from you camera position and normalizing it. As for clUp you need to kind of figure that one out because it's the top of the screen and that can be any direction. Let’s say however you want to roughly align it with the Y axis and you have clFace already. You could get clUp and clRight from:

   D3DXVECTOR3 clYAxis(0.0f,1.0f,0.0f);   D3DXVec3Cross(&clTemp,  &clYAxis,  &clFace);   D3DXVec3Normalize(&clRight, &clTemp);   D3DXVec3Cross(&clUp, &clFace,&clRight);


And then feed it into the rest of the code. This is all in DirectX with a left handed coordinate system but you can recode it for whatever. Also there is the degenerate case where you are looking straight up or down, but it's not hard to handle.
Quote:Original post by polypterus
I'll just cut and paste from my code since it's easier. I probably stole it from some book anyway:
   D3DXMATRIX V;   D3DXVECTOR3 clRight;   // Generate right vector   D3DXVec3Cross(&clRight, &clUp, &clFace);   float fX = -D3DXVec3Dot(&clRight, &clPos);   float fY = -D3DXVec3Dot(&clUp, &clPos);   float fZ = -D3DXVec3Dot(&clFace, &clPos);   V(0,0) = clRight.x;  V(0, 1) = clUp.x;    V(0, 2) = clFace.x;  V(0, 3) = 0.0f;   V(1,0) = clRight.y;  V(1, 1) = clUp.y;    V(1, 2) = clFace.y;  V(1, 3) = 0.0f;   V(2,0) = clRight.z;  V(2, 1) = clUp.z;    V(2, 2) = clFace.z;  V(2, 3) = 0.0f;   V(3,0) = fX;         V(3, 1) = fY;        V(3, 2) = fZ;        V(3, 3) = 1.0f;   m_pDevice->SetTransform(D3DTS_VIEW, &V);


So basically you start out with the clUp and clFace unit vectors and you get the rest from there. You can get clFace from subtracting your look at position from you camera position and normalizing it. As for clUp you need to kind of figure that one out because it's the top of the screen and that can be any direction. Let’s say however you want to roughly align it with the Y axis and you have clFace already. You could get clUp and clRight from:

   D3DXVECTOR3 clYAxis(0.0f,1.0f,0.0f);   D3DXVec3Cross(&clTemp,  &clYAxis,  &clFace);   D3DXVec3Normalize(&clRight, &clTemp);   D3DXVec3Cross(&clUp, &clFace,&clRight);


And then feed it into the rest of the code. This is all in DirectX with a left handed coordinate system but you can recode it for whatever. Also there is the degenerate case where you are looking straight up or down, but it's not hard to handle.
I got the impression that the OP was looking for a solution *other* than the usual 'look-at' approach (specifically, one based on yaw and pitch rotations). I could have misinterpreted though.
Quote:I got the impression that the OP was looking for a solution *other* than the usual 'look-at' approach (specifically, one based on yaw and pitch rotations). I could have misinterpreted though.


Hmmm, Yeah I guess you are right. I read it wrong at first. I thought he just didn't want to use the function.
Quote:Original post by Skyy

Camera starts off on "facing"(?) the negative Z axis of the world in the given position and I need to turn the camera to face the "point of interest", so to say. I'm not interested in the "use gluLookAt"-style approaches. I'm interested in the math behind this and I'm kind of struggling with this. So what I'm after is help on how to calculate the X and Y rotations required to be facing at the given point of interest.



Functions like gluLookAt and D3DXMatrixLookAtLH do it much like polypterus described. For any matrix that represents a position and orientation (AKA a world matrix) contains 4 3-component vectors in either the rows or columns of the matrix (depending on whether you're using column-major or row-major matrices). These vectors are the up vector, the right vector, the forward vector, and the translation vector. If you invert this matrix (which you can do by transposing if the matrix is orthogonal), you get a view matrix that performs the inverse of the the translation/rotation.

So for a basic implementation you might do this:

-Ask for position, up, forward, right vectors
-Pack those into appropriate columns/rows if a matrix
-Invert the matrix
-Return the matrix

One change we can make is that we only need the two of the 3 orientation vectors, since we can calculate the third by using a cross product (since the 3 vectors are all perpendicular to each other). That gives us this:

-Ask for position, up, and forward vectors
-Calculate right vector by crossing forward x up for right-handed coordinates, or up x forward for left-handed
-Pack the vectors in a matrix
-Invert
-Return

A further optimization would be to skip the matrix inverse by taking advantage of the fact that the resulting world matrix is orthogonal. Since it's orthogonal, the inverse is just the transpose. This also means that if we simply transpose the vectors as we're packing it into the matrix, we end up with a proper view matrix. This is what polypterus's code does.

Anyway that's how those functions work. They do not work by calculating equivalent rotations about the major axes (known as euler angles), or by calculating a rotation about an arbitrary axis. These are both unnecessary, since you already have direction vectors which means you can just directly pack them into a matrix anyway.
Ok then how about something like this?

temp1 = normalize( vector(pos.x,0,pos.z) )temp2 = normalize( vector(pos.x,pos.y,pos.z) )yrot = atan2( dot( vector(0,1,0), cross( temp1, vector(0,0,-1) ) ),  dot( temp1, vector(0,0,-1) ) )xrot = acos( dot(temp1,temp2) )


Then you do a y rotation of yrot followed by and X rotation of xrot. Not sure about the signs though. Might be –yrot or –xrot or some such. I think this works but I'm not 100% on it.

Edit: Wait I think I messed something up on the X Rotation.
temp1 = normalize( vector(pos.x,0,pos.z) )temp2 = normalize( vector(pos.x,pos.y,pos.z) )yrot = atan2( dot( vector(0,1,0), cross( temp1, vector(0,0,-1) ) ),  dot( temp1, vector(0,0,-1) ) )xrot = acos( dot(temp2,vector(0,1,0) ) - PI/2


Maybe this fixes it. Again check the signs.
Cool guys, and yes, I was kind of going for the "math" approach of it. Need to polish it up alot. I just get completely destroyed when it comes to moving around with my camera and figuring out where to point the bugger.

I'll try out the things and let you guys know what's going on. Cheers mates!

This topic is closed to new replies.

Advertisement