
Moving the Camera in D3DX
Hello all
I was playing around with the camera in D3DX, and, although I was able to slide it on the different axis''s, I couldn''t find out how to move it at a constant velocity on an angle. Ok... Mabe I''m being too confusing, so I''ll try to simplify.
I got the camera set up so that I can move it up and down the X, Y, and Z axis''. I also managed to rotate the camera around all of the axis''. My goal, is to have the camera move straight in the direction the camera is pointing, so that moving throughout the world isn''t restricted by moving on the 3 axis''. I tried to go through the source for both the particle and the tentacle example, but I was unable to figure out how they allowed such free movement of the camera.
Sorry if I''m not being clear...I''ll gladly explain for anyone who asks.
Till next time...
-Doddler

There are many ways to solve this, I give one here:
The above code doesn't handle rolling but you can perhaps add it yourself if you need it. The code was written to make it easier to understand, not for efficiency.
Edited by - Spellbound on 2/26/00 2:55:25 PM
Edited by - Spellbound on 2/28/00 9:19:53 AM
// Some attributes of the cameraD3DXVECTOR3 Pos;float Yaw, Pitch;float XSpeed, YSpeed, ZSpeed;// We need the orientation of the cameraD3DXVECTOR3 Front;Front.x = -sin(Yaw)*cos(Pitch);Front.y = sin(Pitch);Front.z = cos(Yaw)*cos(Pitch);D3DXVECTOR3 Right;Right.x = cos(Yaw);Right.y = 0;Right.z = sin(Yaw);D3DXVECTOR3 Up;D3DXVec3Cross(&Up, &Front, &Right);// Now we can move the cameraPos.x += XSpeed;Pos.y += YSpeed;Pos.z += ZSpeed;// Note: This is how the camera was moved before, but that is wrong.// This is more appropriate for acceleration (See below).// Pos += XSpeed*Right + YSpeed*Up + ZSpeed*Front;// The view matrixD3DXVECTOR3 Focus;D3DXMATRIX ViewMtx;Focus = Pos + Front;D3DXMatrixLookAt(&ViewMtx, &Pos, &Focus, &Up);
The above code doesn't handle rolling but you can perhaps add it yourself if you need it. The code was written to make it easier to understand, not for efficiency.
Edited by - Spellbound on 2/26/00 2:55:25 PM
Edited by - Spellbound on 2/28/00 9:19:53 AM
Ok... thanks for the help... Also, I also have another problem. How exactly would you calculate the position of an object by simply it''s velocity and direction. The point is that You would say rotate the camera about 40% left and 63% up, press forward, and you would accelerate in that direction.
Well, thank you for your time.
-Doddler
Well, thank you for your time.
-Doddler
Not sure if I understood your last question but here goes. (Hmm, I just saw my error and that is probably what confused you: The part about moving the camera is completely wrong. I post the correct way to do it here.)
The camera has the following attributes:
Each frame you compute the time that has run since last frame:
The position is updated like so:
If you want to accelerate the camera you do it like this:
Where Front, Right, and Up is computed as in my previous answer. Acc is set when the user presses the key, for example a press of the up key would set Acc.z = 1.
Edited by - Spellbound on 2/28/00 9:22:40 AM
The camera has the following attributes:
D3DXVECTOR3 Position;D3DXVECTOR3 Speed;D3DXVECTOR3 Acc;float Yaw, Pitch;
Each frame you compute the time that has run since last frame:
float DeltaTime = timeGetTime()/1000.0f - LastTime;LastTime += DeltaTime;
The position is updated like so:
Position += DeltaTime * Speed;
If you want to accelerate the camera you do it like this:
Speed += DeltaTime * (Acc.z * Front + Acc.x * Right + Acc.y * Up);
Where Front, Right, and Up is computed as in my previous answer. Acc is set when the user presses the key, for example a press of the up key would set Acc.z = 1.
Edited by - Spellbound on 2/28/00 9:22:40 AM
Thanks, Spellbound for replying. Unfortunatly, I don''t have the mathematical background (I''m just in high school
) so I don''t quite understand what your code quite does. I know I''m probably becoming annoying at this point, so I''ll try to make things as clear as possible by showing some of my current code.
This is the way I''m doing it now. Note that this is not good code in anyway.
//Note that I''m well aware that I can do this by using
//D3DXVECTOR3, but I''m doing this for now just because
//I''m just trying to get this working.. I''ll fix that later.
struct camera
{
FLOAT x, y, z; /The X, Y, and Z position
FLOAT rx, ry, rz; /The amount rotated
};
camera cam;
CGameClass::DoCameraStuff()
{
D3DXMATRIX matView;
D3DXMATRIX matViewRot;
GetUserInput();
D3DXMatrixTranslation(&matView, Cam.x, Cam.y, Cam.z );
D3DXMatrixRotationYawPitchRoll( &matViewRot, Cam.rx, Cam.ry, Cam.rz );
D3DXMatrixMultiply( &matView, &matView, &matViewRot );
m_pD3DDev->SetTransform( D3DTRANSFORMSTATE_VIEW, matView );
}
//Once again, this is really bad code to get the user input.
//I''m currently using a timer, so for now, this''ll work.
//I''ll fix this once I get My camera stuff done.
CGameClass::GetUserInput()
{
if(diks[DIK_LEFT] & 0x80)
Cam.rx-=0.1f;
if(diks[DIK_RIGHT] & 0x80)
Cam.rx+=0.1f;
if(diks[DIK_UP] & 0x80)
Cam.z++;
if(diks[DIK_DOWN] & 0x80)
Cam.z--;
if(diks[DIK_Z] & 0x80)
Cam.x++;
if(diks[DIK_X] & 0x80)
Cam.x--;
}
Any ways, as you can see, this only allows movement on the X and Z axis. What I want is free movement of the camera (note: something like that from the D3DX examples) I''m going to try to describe what I want to do using a poor mix of normal code and poorly done psudo-code.
struct camera
{
float vel;
float x, y z, rx, ry, rz;
}
camera cam;
CGameClass::DoCameraStuff()
{
D3DXMATRIX matView;
D3DXMATRIX matViewRot;
GetUserInput();
//This is what I want to do.
Move Camera in the direction that the camera is facing;
Distance forward = Velocity;
cam.vel -= 0.2;
D3DXMatrixTranslation(&matView, Cam.x, Cam.y, Cam.z );
D3DXMatrixRotationYawPitchRoll( &matViewRot, Cam.rx, Cam.ry, Cam.rz );
D3DXMatrixMultiply( &matView, &matView, &matViewRot );
m_pD3DDev->SetTransform( D3DTRANSFORMSTATE_VIEW, matView );
}
CGameClass::GetUserInput()
{
if LeftKey
cam.rx-=1;
if RightKey
cam.ry-=1;
Do the same thing for the A and Z keys;
if ForwardKey
cam.vel+=1;
}
Basically, that''s what I want to do. I''ve never done this before. I''m just in the middle of grade 11 now, so don''t really have the mathematical background to solve this problem myself. Once again, thanks everyone for your time.
-Doddler.
P.S. Sorry Spellbound, but I don''t quite understand what the code you posted does. I''m kinda confused about the use of Front and Right, and what they both do. Perhaps you can simplify, or show how I can use that with my current code... Thank you very much for your help, though.

This is the way I''m doing it now. Note that this is not good code in anyway.
//Note that I''m well aware that I can do this by using
//D3DXVECTOR3, but I''m doing this for now just because
//I''m just trying to get this working.. I''ll fix that later.
struct camera
{
FLOAT x, y, z; /The X, Y, and Z position
FLOAT rx, ry, rz; /The amount rotated
};
camera cam;
CGameClass::DoCameraStuff()
{
D3DXMATRIX matView;
D3DXMATRIX matViewRot;
GetUserInput();
D3DXMatrixTranslation(&matView, Cam.x, Cam.y, Cam.z );
D3DXMatrixRotationYawPitchRoll( &matViewRot, Cam.rx, Cam.ry, Cam.rz );
D3DXMatrixMultiply( &matView, &matView, &matViewRot );
m_pD3DDev->SetTransform( D3DTRANSFORMSTATE_VIEW, matView );
}
//Once again, this is really bad code to get the user input.
//I''m currently using a timer, so for now, this''ll work.
//I''ll fix this once I get My camera stuff done.
CGameClass::GetUserInput()
{
if(diks[DIK_LEFT] & 0x80)
Cam.rx-=0.1f;
if(diks[DIK_RIGHT] & 0x80)
Cam.rx+=0.1f;
if(diks[DIK_UP] & 0x80)
Cam.z++;
if(diks[DIK_DOWN] & 0x80)
Cam.z--;
if(diks[DIK_Z] & 0x80)
Cam.x++;
if(diks[DIK_X] & 0x80)
Cam.x--;
}
Any ways, as you can see, this only allows movement on the X and Z axis. What I want is free movement of the camera (note: something like that from the D3DX examples) I''m going to try to describe what I want to do using a poor mix of normal code and poorly done psudo-code.
struct camera
{
float vel;
float x, y z, rx, ry, rz;
}
camera cam;
CGameClass::DoCameraStuff()
{
D3DXMATRIX matView;
D3DXMATRIX matViewRot;
GetUserInput();
//This is what I want to do.
Move Camera in the direction that the camera is facing;
Distance forward = Velocity;
cam.vel -= 0.2;
D3DXMatrixTranslation(&matView, Cam.x, Cam.y, Cam.z );
D3DXMatrixRotationYawPitchRoll( &matViewRot, Cam.rx, Cam.ry, Cam.rz );
D3DXMatrixMultiply( &matView, &matView, &matViewRot );
m_pD3DDev->SetTransform( D3DTRANSFORMSTATE_VIEW, matView );
}
CGameClass::GetUserInput()
{
if LeftKey
cam.rx-=1;
if RightKey
cam.ry-=1;
Do the same thing for the A and Z keys;
if ForwardKey
cam.vel+=1;
}
Basically, that''s what I want to do. I''ve never done this before. I''m just in the middle of grade 11 now, so don''t really have the mathematical background to solve this problem myself. Once again, thanks everyone for your time.
-Doddler.
P.S. Sorry Spellbound, but I don''t quite understand what the code you posted does. I''m kinda confused about the use of Front and Right, and what they both do. Perhaps you can simplify, or show how I can use that with my current code... Thank you very much for your help, though.
Doddler, you are not getting annoying. This is a complicated problem if one doesn't have the education yet.
Have you taken any trigonometry classes yet? Or do you need to know how cos() and sin() work? I will not describe them this time, but if you ask I will.
It seems you're a little confused of the meaning with Front, Right and Up.
Lets start with a camera placed at the origo, which is the coordinates (0,0,0). The camera is oriented so that it's looking down the z axis.
I don't know if you have learned about three dimensional coodinate systems in school yet. But if you have you will most likely have been taught that when looking at a paper the x-axis is pointing to the right, the y-axis is pointing up, and the z-axis is pointing at you. This is called a right-handed cartesian system. DirectX uses a left-handed cartesian system, this means that the z-axis is reversed and is now pointing away from you.
Back to the camera: The orientation vectors for the camera as it is positioned now are:
Front = (0,0,1) (down the z-axis)
Right = (1,0,0) (to the right)
Up = (0,1,0) (pointed straigt up)
This configuration has the rotation angles yaw=0, pitch=0, and roll=0. The yaw angle spins the camera around the y-axis, the pitch angle around the x-axis and the roll angle around the z-axis.
If we constrain the roll angle to be 0, we can use these formulas to rotate the camera (These are the same as in my previous answer):
D3DXVECTOR3 Front;
Front.x = -sin(Yaw)*cos(Pitch);
Front.y = sin(Pitch);
Front.z = cos(Yaw)*cos(Pitch);
D3DXVECTOR3 Right;
Right.x = cos(Yaw);
Right.y = 0;
Right.z = sin(Yaw);
D3DXVECTOR3 Up;
D3DXVec3Cross(&Up, &Front, &Right);
I assume you know about cos() and sin() here, but D3DXVec3Cross() can be a bit difficult to understand. D3DXVec3Cross() computes the crossproduct (a.k.a vectorproduct) between two vectors. The crossproduct is a new vector that is perpendicular to both in-vectors. If you point your left-hand thumb in the direction of the first vector and your index finger in the direction of the second vector, the cross product will be in the direction of you middle finger pointed out from your palm (for a righthanded system, you use the right hand instead). The crossproduct will also have a length based on the two others but that is irrelevant right now (Ask if you want to know how to compute the length as well).
Now that we know in what direction the camera is facing, we can easily move it along these vectors. To move it forward we add a fraction of the forward vector. To move it right we add a fraction of the right vector. The same goes for the up vector.
You can do the user input function like this:
In DoCameraStuff() you have made a small error. You try to move the camera to the world. But instead you must move the world to the camera, otherwise you will get some very odd behavior from the user input. The fact that you didn't before was because you had circumvented this by moving the camera in the opposite direction of what the user wanted. (It's a common error, you are not the first to do so.
)
In my second answer above I spoke about acceleration and camera speed, but it seems that you didn't want that at all so I didn't insert it in this answer. If you add acceleration and speed as I did in the previous answer your camera will continue to move after the user has released the keys.
Still more questions? Don't be afraid to ask. My patience is infinite (Almost).
Edited by - Spellbound on 2/28/00 1:51:43 PM
Have you taken any trigonometry classes yet? Or do you need to know how cos() and sin() work? I will not describe them this time, but if you ask I will.
It seems you're a little confused of the meaning with Front, Right and Up.
Lets start with a camera placed at the origo, which is the coordinates (0,0,0). The camera is oriented so that it's looking down the z axis.
I don't know if you have learned about three dimensional coodinate systems in school yet. But if you have you will most likely have been taught that when looking at a paper the x-axis is pointing to the right, the y-axis is pointing up, and the z-axis is pointing at you. This is called a right-handed cartesian system. DirectX uses a left-handed cartesian system, this means that the z-axis is reversed and is now pointing away from you.
Back to the camera: The orientation vectors for the camera as it is positioned now are:
Front = (0,0,1) (down the z-axis)
Right = (1,0,0) (to the right)
Up = (0,1,0) (pointed straigt up)
This configuration has the rotation angles yaw=0, pitch=0, and roll=0. The yaw angle spins the camera around the y-axis, the pitch angle around the x-axis and the roll angle around the z-axis.
If we constrain the roll angle to be 0, we can use these formulas to rotate the camera (These are the same as in my previous answer):
D3DXVECTOR3 Front;
Front.x = -sin(Yaw)*cos(Pitch);
Front.y = sin(Pitch);
Front.z = cos(Yaw)*cos(Pitch);
D3DXVECTOR3 Right;
Right.x = cos(Yaw);
Right.y = 0;
Right.z = sin(Yaw);
D3DXVECTOR3 Up;
D3DXVec3Cross(&Up, &Front, &Right);
I assume you know about cos() and sin() here, but D3DXVec3Cross() can be a bit difficult to understand. D3DXVec3Cross() computes the crossproduct (a.k.a vectorproduct) between two vectors. The crossproduct is a new vector that is perpendicular to both in-vectors. If you point your left-hand thumb in the direction of the first vector and your index finger in the direction of the second vector, the cross product will be in the direction of you middle finger pointed out from your palm (for a righthanded system, you use the right hand instead). The crossproduct will also have a length based on the two others but that is irrelevant right now (Ask if you want to know how to compute the length as well).
Now that we know in what direction the camera is facing, we can easily move it along these vectors. To move it forward we add a fraction of the forward vector. To move it right we add a fraction of the right vector. The same goes for the up vector.
You can do the user input function like this:
CGameClass::GetUserInput(){ // We want to rotate about the y-axis if(diks[DIK_LEFT] & 0x80) Cam.ry+=0.1f; if(diks[DIK_RIGHT] & 0x80) Cam.ry-=0.1f; // since you don't use pitch I have simplified even more D3DXVECTOR3 Front; Front.x = -sin(Cam.ry); Front.y = 0; Front.z = cos(Cam.ry); D3DXVECTOR3 Right; Right.x = cos(Cam.ry); Right.y = 0; Right.z = sin(Cam.ry); // To move the camera forward me add the front vector if(diks[DIK_UP] & 0x80) { Cam.x += Front.x; Cam.y += Front.y; Cam.z += Front.z; } // To move backward subtract the front vector if(diks[DIK_DOWN] & 0x80) { // need some code } // To move left we subtract the right vector if(diks[DIK_Z] & 0x80) { Cam.x -= Right.x; Cam.y -= Right.y; Cam.z -= Right.z; } // Guess how we move right... if(diks[DIK_X] & 0x80) { // Need some code }}
In DoCameraStuff() you have made a small error. You try to move the camera to the world. But instead you must move the world to the camera, otherwise you will get some very odd behavior from the user input. The fact that you didn't before was because you had circumvented this by moving the camera in the opposite direction of what the user wanted. (It's a common error, you are not the first to do so.

CGameClass::DoCameraStuff(){D3DXMATRIX matView;D3DXMATRIX matViewRot;GetUserInput();// Move the world and camera to origoD3DXMatrixTranslation(&matView, -Cam.x, -Cam.y, -Cam.z );// Rotate world and camera so that the camera is directed down the z-axisD3DXMatrixRotationYawPitchRoll( &matViewRot, -Cam.rx, -Cam.ry, -Cam.rz );D3DXMatrixMultiply( &matView, &matView, &matViewRot );m_pD3DDev->SetTransform( D3DTRANSFORMSTATE_VIEW, matView );}
In my second answer above I spoke about acceleration and camera speed, but it seems that you didn't want that at all so I didn't insert it in this answer. If you add acceleration and speed as I did in the previous answer your camera will continue to move after the user has released the keys.
Still more questions? Don't be afraid to ask. My patience is infinite (Almost).

Edited by - Spellbound on 2/28/00 1:51:43 PM
Thank you! 
You''ve been a great help! To answer your first question, I have done some trigonometry. The thing is though, is that I''m not sure exactly what sin, cos, and tan are. I have been taught how to use them, but it''s hard to understand what your doing when you don''t know where the numbers are comming from.
On the topic of the Camera stuff, I looked over the code until I understood what it did. Then I used it in my app, and I got some odd results. Since it''s really hard to explain what happens, I uploaded my code to members.xoom.com/Doddler/Project.zip - It''s only 202k, so it shouldn''t be that big of a hassle. It comes with everything but the exe, which can easily be compiled. I know that this is a pain in the butt, but it''s probably better than posting my code on the forum. My code is horibly messy, and unorganized, but it''ll have to do.
You''ve been a great help! Thanks for replying.
-Doddler

You''ve been a great help! To answer your first question, I have done some trigonometry. The thing is though, is that I''m not sure exactly what sin, cos, and tan are. I have been taught how to use them, but it''s hard to understand what your doing when you don''t know where the numbers are comming from.
On the topic of the Camera stuff, I looked over the code until I understood what it did. Then I used it in my app, and I got some odd results. Since it''s really hard to explain what happens, I uploaded my code to members.xoom.com/Doddler/Project.zip - It''s only 202k, so it shouldn''t be that big of a hassle. It comes with everything but the exe, which can easily be compiled. I know that this is a pain in the butt, but it''s probably better than posting my code on the forum. My code is horibly messy, and unorganized, but it''ll have to do.
You''ve been a great help! Thanks for replying.
-Doddler
Ok, I downloaded and looked at your program. I found some errors which you can find below. The bad thing is that all errors were introduced by me.
That''s what happening when programming without testing the code.
In DoCameraStuff() you should write this:
I swapped rx and ry, because ry is rotation about y-axis and yaw is also rotation about y-axis. I''m sorry if I misled you before, that is why it is good to understand what is happening and not just copying other peoples code.
In CheckInput() you should write like this:
Here I negated the z components of both vector. My mistake again, I forgot what I said about left-hand system and used formulas for a right-handed system. Sorry.

In DoCameraStuff() you should write this:
D3DXMatrixRotationYawPitchRoll( &matViewRot, -Cam.ry, -Cam.rx, -Cam.rz );
I swapped rx and ry, because ry is rotation about y-axis and yaw is also rotation about y-axis. I''m sorry if I misled you before, that is why it is good to understand what is happening and not just copying other peoples code.

In CheckInput() you should write like this:
D3DXVECTOR3 Front; Front.x = (FLOAT)-sin(Cam.ry); Front.y = 0; Front.z = (FLOAT)-cos(Cam.ry); D3DXVECTOR3 Right; Right.x = (FLOAT)cos(Cam.ry); Right.y = 0; Right.z = (FLOAT)-sin(Cam.ry);
Here I negated the z components of both vector. My mistake again, I forgot what I said about left-hand system and used formulas for a right-handed system. Sorry.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement