Jump to content

  • Log In with Google      Sign In   
  • Create Account

Problem with matrix math for camera


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
7 replies to this topic

#1 Synthetix   Members   -  Reputation: 190

Like
0Likes
Like

Posted 02 July 2012 - 04:25 AM

I've been struggling with getting the matrix math down for translating and rotating a camera through 3D space. I've got an OpenGL program that places the camera in the middle of a box at 0,0,0. I want to be able to both translate and rotate (first person shooter-style) through the box using the keyboard. I've got it working except I can't translate/rotate and keep the coordinates the same for both (only one or the other). For example, I can move through the box just fine (using the WSAD keys), but if I rotate my view to the left by 90 degrees, "forward" now goes to the right.

The problem is, I multiply the modelview matrix by the translation matrix first, and then by the rotation matrix. This works except that by rotating the scene 90 degrees, it throws the translation coordinates off by 90 degrees! In other words, translation occurs under the assumption that the scene has not been rotated.

I only need to rotate the scene on the Y axis, Wolfenstein/Doom style. Here is my code so far:

mat4x4 mat_model,mat_tran,mat_rot,mat_temp;

mat4x4_identity(mat_model);
mat4x4_identity(mat_tran);
mat4x4_identity(mat_rot);
mat4x4_identity(mat_temp);

//create translation matrix
mat4x4_translate(mat_tran, strafe, 0.0, dolly);

//create rotation matrix
mat4x4_rotate_Y(mat_rot,mat_temp,-rot_y);

//apply the matrices to the modelview matrix
mat4x4_mul(mat_temp,mat_tran,mat_rot);
mat4x4_dup(mat_model,mat_temp);



What am I missing?

Sponsor:

#2 Goran Milovanovic   Members   -  Reputation: 1104

Like
0Likes
Like

Posted 02 July 2012 - 04:32 PM

I can move through the box just fine (using the WSAD keys), but if I rotate my view to the left by 90 degrees, "forward" now goes to the right.


"Forward" should modify a direction vector in local coordinates, which can then be transformed by the rotation matrix to generate the approprite translation vector.

+---------------------------------------------------------------------+

| Game Dev video tutorials  ->   http://www.youtube.com/goranmilovano |
+---------------------------------------------------------------------+

#3 Synthetix   Members   -  Reputation: 190

Like
0Likes
Like

Posted 02 July 2012 - 09:20 PM

"Forward" should modify a direction vector in local coordinates, which can then be transformed by the rotation matrix to generate the approprite translation vector.


Thanks. I tried that, but now the scene only rotates around the origin (0,0,0). Actually, this gives the same result as pre-multiplying the rotation/translation matrices.

Let me just confirm: the "eye point" is the X,Y (assuming Z-up) coordinates of the camera, looking down, correct? And the "look at" point, or the camera's orientation, is the eye point vector multiplied by the rotation matrix, yes?

I'm sorry I can't be more helpful. I am really having a hard time grasping this.

Edited by Synthetix, 02 July 2012 - 09:45 PM.


#4 Goran Milovanovic   Members   -  Reputation: 1104

Like
0Likes
Like

Posted 03 July 2012 - 11:33 PM

Thanks. I tried that, but now the scene only rotates around the origin (0,0,0). Actually, this gives the same result as pre-multiplying the rotation/translation matrices.


It sounds like you're not translating other objects in the scene. You have to transform everything in your scene to create the illusion of a "camera" moving through space. Typically, you would have a 4x4 transform matrix that describes orientation/translation of the camera. You would also have a 4x4 matrix for every object in the scene. Then, to create the illusion of a camera moving through space, you have to transform the matrix of each and every object, by the inverse matrix of the camera.

Why inverse? -> In the real world, you would have an actual camera that you would rotate left (if you wanted to see the portion of the scene on the left). However, in the OpenGL world, in order to look left, you have to "rotate the world" to the right, creating the illusion of a camera that is rotating to the left.

I don't know if you had the chance to research this in more depth, but I think this page should still be helpful: http://www.opengl.org/wiki/Viewing_and_Transformations

Let me just confirm: the "eye point" is the X,Y (assuming Z-up) coordinates of the camera, looking down, correct? And the "look at" point, or the camera's orientation, is the eye point vector multiplied by the rotation matrix, yes


In the context of gluLookAt? Both the "eye point" and the "look at point" should be vectors in object/world space coordinates.

+---------------------------------------------------------------------+

| Game Dev video tutorials  ->   http://www.youtube.com/goranmilovano |
+---------------------------------------------------------------------+

#5 Synthetix   Members   -  Reputation: 190

Like
0Likes
Like

Posted 05 July 2012 - 04:21 AM

Okay, I can grab both the camera's current position vector and direction (the direction it's pointing) vector from the modelview matrix. Assuming I have this data on each loop iteration, how do I get the camera to rotate around its current position as opposed to 0,0,0? I have been reading a lot of tutorials that say you have to rotate the direction vector by the rotation matrix used to rotate the scene so when you apply the translation, it goes in the correct direction. I think I understand that part perfectly well, as I'm able to derive the forward/back direction vector from the modelview matrix, normalize it, and add it to the translation matrix along with the speed value. I do the same for the strafe vector, which is the cross product of the fwd/back vector and the Y direction (currently -1.0).

Example:

//calculate strafe vector using cross product of Z and Y
vec4 direction_strafe;
vec4_cross(direction_strafe,direction_move,(vec4){0.0,-1.0,0.0,0.0});

camera_position[z] += (direction_move[z] * speed); //WS keys (fwd/back)
camera_position[x] += (direction_strafe[x] * speed); //AD keys (strafe)

//construct translation matrix
mat4x4 translate;
mat4x4_translate(translate, camera_position[x], 0.0, camera_position[z]); //Y is 0.0 since we never go up/down

I then multiply the translation matrix by the rotation matrix and drop the result into the modelview matrix. Problem is, when I rotate the scene, it is always rotating around 0,0,0 so when I move around, the camera always rotates around the world's origin and not its own.

Edited by Synthetix, 05 July 2012 - 04:56 AM.


#6 dpadam450   Members   -  Reputation: 923

Like
0Likes
Like

Posted 05 July 2012 - 10:51 AM

direction_move should be calculated by using the sin/cos of the camera angle. Looks like you have a cross product calculating it?

#7 Synthetix   Members   -  Reputation: 190

Like
0Likes
Like

Posted 06 July 2012 - 04:45 AM

direction_move should be calculated by using the sin/cos of the camera angle. Looks like you have a cross product calculating it?


I'm calculating the strafe vector using the cross product of the foward (Z) direction and the up (Y) direction. So, the strafe vector is basically 90 degrees from the forward vector. I then add this to the translation matrix when the user presses one of the WSAD move keys, and then multiply the modelview matrix with it before rendering the scene.

I'm using a rotation matrix which contains the rotation angle when the user rotates the camera view left/right on the Y/up axis.

All of this works perfectly for either movement or rotation only, but I can't get the two working together! Posted Image

#8 scniton   Members   -  Reputation: 252

Like
0Likes
Like

Posted 13 July 2012 - 09:10 AM

Did you look at Goran Milovanovic's second post about using the inverse?

You've defined your camera transformation as:
Translate * Rotation
Which means your view matrix should be:
Rotation' * Translation' (i.e. the inverse)

So modifying your original code:

[source lang="cpp"]mat4x4 invTran_mat, invRot_mat, temp_mat, modelView_mat;mat4x4_identity(temp_mat);mat4x4_identity(invTran_mat);// Inverse of your original rotation matrixmat4x4_rotate_Y(invRot_mat, temp_mat, rot_y);// Inverse of your original translation matrixmat4x4_translate(invTran_mat, -strafe, 0.0, -dolly);//apply the matrices to the model matrixmat4x4_mul(temp_mat, invRot_mat, invTran_mat);mat4x4_mul(modelView_mat, temp_mat, model_mat);[/source]

Edited by scniton, 13 July 2012 - 09:14 AM.

Stop twiddling your bits and use them already!




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS