Archived

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

Making a FPS style camera in DirectX 8…

This topic is 5680 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 know that I have asked this before, but I still can''t seem to get things straight. How would I go about making a first person view camera, like that of a first person shooter stype game, in DirectX 8? I think that I know how to do it, but I just can''t seem to get things working. What I am doing is calculating the angle that the camera is facing and then using D3DXMatrixLookAtLH() to generate the matrix for the view transform. After I calculate the direction the camera is facing, I translate the camera position and the lookat position to where it should be in the world, then I generate the matrix. I understand most of the math of what I am doing, but I can’t seem to get things right. Here is how I am generating the lookat position: The camera is sitting on the x/z plane. This means that if I mess with the x and z values of the lookat point, I should be able to rotate the camera around a point on this plane. I do this by using cos() and sin(). Since cos(0) = 1, and sin(0) = 0, this means at an angle of 0, the camera is facing directly down the z axis. If I change the angle, I can rotate the lookat point around the origin. Once I have it rotated to where it should be, I translate it to the position in the world to where it should be. Here is a code snippet of what I am doing:
  
float Yaw  = 0;	//the angle of rotation on the x/z plane

float Pitch  = 0;	//the angle of rotation for looking up/down

D3DXVECTOR3 Position;	//position of the camera


//get the change in mouse position and add to the rotation angles accordingly


//translate the camera in the direction that is being looked at, but how?

Position.x += cos(Yaw)*amount;
Position.y += sin(Yaw)*amount;	

//calculate the lookat point

LookAt = D3DXVECTOR3(cos(Yaw) + Position.x,
				cos(Pitch),
                               	 	sin(Yaw) + Position.z);
//then make the view matrix and set it…


  
I guess I don''t totally understand what I should be doing. Can someone tell me the right way of doing this? Moe''s site

Share this post


Link to post
Share on other sites
Hey,

I''m just about to head off to bed so I didn''t have a proper look at your code, but couldn''t you just get the camera transform

  Device3D->GetTransform( D3DTS_VIEW, &View );  
Then get the local z-axis from the camera transform...

  
D3DXVECTOR3 ZAxis( View._31, View._32, View._33 );

And you can then normalize that vector, multiply that by a scalar (and, if animating, by the delta value) then add that vector to your current camera position?

  
D3DXVECTOR3 NormZ;
D3DXVec3Normalize( &NormZ, &ZAxis ); // XXXX: is this necessary?

g_CameraPosition += NormZ*(MOVE_SCALE*Delta);


That sould move your camera along the local Z-axis (relative to the direction it''s facing) - I think ... sorry, too sleepy

Tom L

Share this post


Link to post
Share on other sites
For anyone interested, you can find my old thread here.

Take a look at the last code snippet in the last post. The thing that I don''t understand is exactly what is being done to calculate the lookat point.

Moe''s site

Share this post


Link to post
Share on other sites
I did one a while ago and what I did was basically this:
Store the ''player'' position and orientation then when you need to rebuild the view matrix you pick a point at an arbitrary distance from the player (say (0,0,1000)) apply your translation and rotation matrices to that point, and that''s your new LookAt.

And one day when I get off my butt, I''ll release the source too.

Stay Casual,

Ken
Drunken Hyena

Share this post


Link to post
Share on other sites
Actually, ignore any code or anything that I had first posted. I nearly have things working, thanks to the help of SHilbert. As soon as I get it working I will post the source to it...

Moe''s site

Share this post


Link to post
Share on other sites
this is why i think using helper librarys sucks sometimes, because people don''t have to understand the basics of whats going on... (and thats not to say that I have perfect understanding either...)

Moe: i see you''ve figured something out, but i''ve seen a few questions like this...

to orient an object in 3 dimensions, we use 3 vectors:
the direction it faces, its upwards direction, and its right direction ( well actually, we only need 2, the third is the cross product of the other two )

these vectors fit into the conventional cartesian axis, ie x,y,z
(i''m talking in left handed co-ords).

with your left hand, point your ''pointing'' finger at something straight ahead. stick your thumb up towards the roof and bend your middle finger so that it is 90 degrees to the thumb and pointing finger.
the pointing finger is the (+ve) z axis, or the lookat, the thumb is the up vector, or y axis, the middle finger is the x axis, or right vector.

now all that you need to do when you want the object to move is to rotate this set of axes.

lets say i want to turn a camera left.
set up a rotation matrix around the up vector, for the desired angle.
use this matrix to transform the lookat and right vectors.
done.

its also good to reorthagonalise the axes every so often ( ie normalise and make 90 degrees)

the three axis vectors can then be used to set a view or world matrix:

world matrix
right.x right.y right.z 0
up.x up.y up.z 0
look.x look.y look.z 0
pos.x pos.y pos.z 1


view matrix
right.x up.x look.x 0
right.y up.y look.y 0
right.z up.z look.z 0
dp(r,pos) dp(u,pos) dp(l,pos) 1

where dp() is dot product. (i just know that the formattings going to stuff up.)

this means that we can build the view or world matrix directly, rather than having to use the LookAt..() functions and continually figure the point we''re looking at.

this approach won''t experience gimbal lock like the euler model is prone to do. (ie the yaw, pitch, roll model. sometimes, due to sin(0) =0 and cos(pi)=0 etc etc, the object rotation cant be determined correctly).

and sure, it seems like a lot of work, and its easy to hack an easier way to do it, but this will provide a powerful and flexible way to do orient your objects. plus if there is more than one such object, whack all this stuff into a class.

people will also say to use quaternions. power to them, i;ve never bothered. when you get down to the maths of it, the equations come out the same.

thats all we have time for today. the general concept is hopefully there, although i havent talked about how to make it move. if i remember correctly it was a tutorial by mr gamemaker
that first got me ovulating about this ''camera'' system, but the sites shutdown so i don''t know if the tute is still around.

if you want more help: reillyhead@hotmail.com

later
Marc




Share this post


Link to post
Share on other sites
Actually, I got things working fine (with the help of SHilbert). Here is the source:

camera.h:

  
//----------------------------------------//

// camera.h - header file for the camera class and functions, which

// control the view of the scene that gets rendered

//

//----------------------------------------//


//include the other necessary files

#include "d3d.h"
//#include <stdio.h> //file i/o stuff for camera configuration file



#ifndef _CAMERA_H_
#define _CAMERA_H_

//return types for the camera

const int CAMERA_OK = 0;
const int CAMERA_BAD = 1;

enum CAMERAMODE
{
FIRSTPERSON, //first person shooter style camera

THIRDPERSON, //third person style camera

STATIC //camera doesn''t move

};


class CAMERA
{
public:
//constructor - gives default variables

CAMERA();

D3DXMATRIX matProjection; //projection matrix

float NearClip; //near clip plane distance

float FarClip; //far clip plane distance

float Fov; //field of view


D3DXMATRIX matView; //view matrix

D3DXVECTOR3 Position; //camera position

D3DXVECTOR3 Velocity; //camera velocity

D3DXVECTOR3 LookAt; //lookat position

float Yaw, YawVelocity; //yaw rotation stuff

float Pitch, PitchVelocity; //pitch rotation stuff


//int CameraState;


//functions

int InitializeCamera(LPDIRECT3DDEVICE8 device, int screenwidth, int screenheight);
void TranslateCamera(float x, float y, float z);
void RotateCamera(float yaw, float pitch);
void UpdateCamera(LPDIRECT3DDEVICE8 device, float delta);

};





#endif //for _CAMERA_H_



In camera.cpp:

  

//----------------------------------------//

// camera.cpp - main file for the camera class/functions

//

//----------------------------------------//


#include "camera.h"

//----------------------------------------//

// Name: CAMERA2()

// Purpose: constructor - gives default values

//----------------------------------------//

CAMERA::CAMERA()
{
//CameraState = FIRSTPERSON;

FarClip = 1000.0f;
Fov = D3DX_PI/4;
LookAt = D3DXVECTOR3(2.0f, 2.0f, 1.0f);
D3DXMatrixIdentity(&matProjection);
D3DXMatrixIdentity(&matView);
NearClip = 0.05f;
Pitch = 0.0f;
PitchVelocity = 0.0f;
Position = D3DXVECTOR3(2.0f, 2.0f, 0.0f);
Velocity = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
Yaw = 0.0f;
YawVelocity = 0.0f;

}


//----------------------------------------//

// Name: InitializeCamera()

// Purpose: initializes the camera to the set values

//----------------------------------------//

int CAMERA::InitializeCamera(LPDIRECT3DDEVICE8 device, int screenwidth, int screenheight)
{

//set up the view matrix

D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(Position.x, Position.y, Position.z), //camera position

&D3DXVECTOR3(LookAt.x, LookAt.y, LookAt.z), //lookat position

&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) ); //up vector

//set the view projection

device->SetTransform(D3DTS_VIEW, &matView);

//set the projection matrix

D3DXMatrixPerspectiveFovLH(&matProjection, Fov, float(screenwidth/screenheight),
NearClip, FarClip);
device->SetTransform(D3DTS_PROJECTION, &matProjection);

//return ok

return CAMERA_OK;
}


//----------------------------------------//

// Name: RotateCamera()

// Purpose: rotates the camera on the x and y axis

//----------------------------------------//

void CAMERA::RotateCamera(float yaw, float pitch)
{
yaw/=15.0f;
pitch/=15.0f;

//simply add to the velocity

PitchVelocity+=pitch;
YawVelocity +=yaw;

/*if (Pitch <= 0.01f)
{
Pitch = 0.01f;
PitchVelocity = 0.0f;
}

if (Pitch >= 3.13f)
{
Pitch = 3.13f;
PitchVelocity = 0.0f;
}*/

}


//----------------------------------------//
// Name: TranslateCamera()
// Purpose: moves the camera with the correct speed according to what way
// the camera is facing - z isn''t implemented yet *** FIX ME ***
//----------------------------------------//
void CAMERA::TranslateCamera(float x, float y, float z)
{
Velocity.x += x*cosf(-Yaw) - z*sinf(-Yaw);
Velocity.z += x*sinf(-Yaw) + z*cosf(-Yaw);

}


//----------------------------------------//
// Name: UpdateCamera()
// Purpose: updates the camera projections/matrices
//----------------------------------------//
void CAMERA::UpdateCamera(LPDIRECT3DDEVICE8 device, float delta)
{



Position += Velocity*delta;
Yaw += YawVelocity*delta;
Pitch += PitchVelocity*delta;

Velocity /= 1.2f;
YawVelocity /= 1.2f;
PitchVelocity /= 1.2f;

// calculate lookat on the fly.
// this should produce a vector that is slightly
// in front of the camera no matter where the camera is.

/*LookAt = D3DXVECTOR3(sinf(Yaw)*cosf(Pitch) + Position.x,
sinf(Pitch),
cosf(Yaw)*cosf(Pitch) + Position.z);*/

LookAt.x = (sinf(Yaw)*cosf(Pitch)) + Position.x;
LookAt.y = sinf(-Pitch) + Position.y;
LookAt.z = (cosf(Yaw)*cosf(Pitch)) + Position.z;

D3DXMatrixLookAtLH(&matView, &Position, //position vector

&LookAt, //lookat vector

&D3DXVECTOR3(0.0f, 1.0f, 0.0f)); //up vector


//set the new matrix

device->SetTransform(D3DTS_VIEW, &matView);

}
[/soruce]


Moe''s site

Share this post


Link to post
Share on other sites
That''s pretty close to how i do it.

Here''s mine


  
if (KEYDOWN(buffer, DIK_RIGHT))
x2+=2;
else if(KEYDOWN(buffer, DIK_LEFT))
x2-=2;

if (x2>360) x2=2;
if (x2<0)x2=358;

if (KEYDOWN(buffer, DIK_UP))
{
D3DXVec3Normalize(&vecDir, &D3DXVECTOR3(x+(float)sin(rad(x2)), y, z+(float)cos(rad(x2))));

D3DXIntersect( spider.mesh,
&D3DXVECTOR3(x,y,z), &vecDir,
&hit, &FaceIndex, &u, &v, &Dist);
if ((hit==false) || (Dist>5))
{ x+=(float)sin(rad(x2)); z+=(float)cos(rad(x2));}}
else if (KEYDOWN(buffer, DIK_DOWN)) {x-=(float)sin(rad(x2));z-=(float)cos(rad(x2));}
}

Share this post


Link to post
Share on other sites