Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

SDyer

First Person Camera Control Schemes

This topic is 5648 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a little 3D world I can render in DirectX. Now I want a first-person camera to move around it. I have searched quite a bit, but have only found a couple of very basic tutorials. What I need is a medium-level example: - Move with up/down keyboard buttons - Strafe with left/right keyboard buttons - Look left/right with mouse, camera moves along that direction when up/down keyboard buttons pressed - Perhaps some limited up/down looking via the mouse while moving - "Look around" mode where user is stopped and can look in any direction with the mouse The examples I''ve seen move the camera, but it certainly wouldn''t be anything I''d want to use in a game. I don''t think this is tremendously difficult, I just need a good tutorial or example to get me started.

Share this post


Link to post
Share on other sites
Advertisement
Well, my answer won't be useless (looks at hexalite ). What you need to know how to do is rotate a vector given the degrees of rotation. Then it's really simple.

Here is my code for an operator called rotated_by. I'll example how to use it afterwards. It uses D3DX functions, but you can use these with OpenGL (I do) as they are just math functions, not tied to the DirectX API.


      
// The rotated_by operator is really operator::^. You can use any symbol

// you want, if you're already using ^ for something else.

#define rotated_by ^

#define PI_OVER_180 0.017453292519943295769236907684886

// The operator is a member function of the 'vector' class.

vector vector :: operator rotated_by ( vector Rotation )
{
static D3DXMATRIX Matrix;
static D3DXVECTOR3 LookAt;
static vector Return;

LookAt.x = X;
LookAt.y = Y;
LookAt.z = -Z;

D3DXMatrixRotationYawPitchRoll( &Matrix,
-float(PI_OVER_180) * (float)Rotation.Y,
-float(PI_OVER_180) * (float)Rotation.X,
-float(PI_OVER_180) * (float)Rotation.Z );
D3DXVec3TransformCoord( &LookAt, &LookAt, &Matrix );

Return.X = (Type)LookAt.x;
Return.Y = (Type)LookAt.y;
Return.Z = (Type)LookAt.z;

return Return;
}


Now to move the camera forward you do this:

Camera.Position += vector(0,0,WALK_SPEED) rotated_by Camera.Rotation;

...where Camera.Rotation.X is pitch, .Y is yaw and .Z is roll. To strafe right, you'd do this:

Camera.Position += vector(STRAFE_SPEED,0,0) rotated_by Camera.Rotation;

And of course you'd make that -WALK_SPEED or -STRAFE_SPEED to move backwards or left.

Now this is the code to set up the view matrices, sans comments. Hopefully it's not hard to follow or use. It uses D3DX functions, but again, these are only math functions and they do work with OpenGL, since I use them with OpenGL.


  
D3DXMATRIX Pitch;
D3DXMATRIX Yaw;
D3DXMATRIX Roll;
D3DXMATRIX Rotation;
D3DXVECTOR3 Eye;
D3DXVECTOR3 LookAt;

D3DXMatrixRotationX( &Pitch, (float)PI_OVER_180 * -ms_Camera.Pitch );
D3DXMatrixRotationY( &Yaw, (float)PI_OVER_180 * -ms_Camera.Yaw );
D3DXMatrixRotationZ( &Roll, (float)PI_OVER_180 * -ms_Camera.Roll );

D3DXMatrixMultiply( &Rotation, &Pitch, &Yaw );
D3DXMatrixMultiply( &Rotation, &Rotation, &Roll );

LookAt = D3DXVECTOR3( 0, 0, -1 );

D3DXVec3TransformCoord( &LookAt, &LookAt, &Rotation );

LookAt.x += ms_Camera.X;
LookAt.y += ms_Camera.Y;
LookAt.z += ms_Camera.Z;

if( ms_Camera.Follow )
{
Eye = D3DXVECTOR3( 0, 0, 1 );
D3DXVec3TransformCoord( &Eye, &Eye, &Rotation );
Eye.x = (Eye.x * ms_Camera.Follow) + ms_Camera.X;
Eye.y = (Eye.y * ms_Camera.Follow) + ms_Camera.Y;
Eye.z = (Eye.z * ms_Camera.Follow) + ms_Camera.Z;
}
else
{
Eye.x = ms_Camera.X;
Eye.y = ms_Camera.Y;
Eye.z = ms_Camera.Z;
}

ms_Camera.Eye = vector<float>( Eye.x, Eye.y, Eye.z );
ms_Camera.LookAt = vector<float>( LookAt.x, LookAt.y, LookAt.z );

D3DXMatrixIdentity( &ms_Camera.World );
D3DXMatrixPerspectiveFovRH( &ms_Camera.Project,
ms_FOV * 0.5f,
float(ms_Viewport.Width) / float(ms_Viewport.Height),
ms_Near,
ms_Far );
D3DXMatrixLookAtRH( &ms_Camera.View,
&Eye,
&LookAt,
&D3DXVECTOR3(0,1,0) );


~CGameProgrammer( );

EDIT: Oh yeah, I forgot to mention that my code for calculating the View matrix ignores roll. That last line "D3DXVECTOR3(0,1,0)" specifies the Up vector. Setting it at (0,1,0) ignores roll. Oh well. For most games, it is not needed.

[edited by - CGameProgrammer on December 1, 2002 9:40:25 PM]

Share this post


Link to post
Share on other sites
Thanks, CGP. That''s exactly the kind of stuff I was looking for.

Hex - take a lesson on giving helpful responses from CGP.

Share this post


Link to post
Share on other sites
CGP - in your rotated_by code, you list

LookAt.x = X;
LookAt.y = Y;
LookAt.z = -Z;

Are X, Y and Z really rotation.X, .Y and .Z? Or, are they the previous camera location? Previous LookAt vector...?

Share this post


Link to post
Share on other sites
Good questions. When you say "A rotated_by B" that calls "A::rotated_by( B )". So X, Y, and Z are the values of the transformation vector that you are rotating. Z is negative just because I had to do that to make sure a positive Z moves forward, or something. I wrote this code a year ago.

"Follow" is the third-person camera distance. If it''s zero, you have a first-person camera. If it''s anything else, it''s the distance of the third-person camera behind the focus (the player).

~CGameProgrammer( );

Share this post


Link to post
Share on other sites
So: X, Y and Z are members of the vector class object, then? In your "A rotated_by B" example, they would be A.X, A.Y, and A.Z?

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!