XFactorDev.net Article   XFactorDev.net Article

 

Prt-7- Lights camera action...CCamera.

 

We need to move around our 3D world for it to be a truly 3D world...no good standing still and watch things go by!  We want to run upto the enemy bots in our 3D world and blow them into a million pieces with our Cube gun!....  Now how we do this is with our CCamera class...which will basically allow us to move around.

 

This section of code below is what a very basic camera would be...its not much...it sets up our near and far clipping regions...our cameras position and what where looking at.... as in the past 2 examples this is what we've used.... but we need more power!!  POWERRRR

 

 

//camera camera camera camera camera camera camera camera camera camera

 

      D3DXMATRIX view_matrix, matProj;

      D3DXMatrixLookAtLH(&view_matrix,&D3DXVECTOR3( 0.0f, 0.0f,-4.0f ),

                        &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),

                        &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ));

 

      pD3DDevice->SetTransform(D3DTS_VIEW,&view_matrix);

 

      D3DXMatrixPerspectiveFovLH(&matProj, //Result Matrix

                        D3DX_PI/4,//Field of View, in radians. (PI/4) is typical

                        ((float)600 / (float)400),     //Aspect ratio

                        1.0f,     //Near view plane

                        1000.0f ); // Far view plane

 

      pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );

 

//end camera end camera end camera end camera end camera end camera end

 

 

 

To get this extreme power we're going to create the CCamera class.....its really not as bad as it sounds....just allows us to move our camera around our 3D world.

 

 

I think the best way to do this is two parts...we'll do a nice simple CCamera class first...with the 'essential' pieces....lets you see how it works and how we will use it....then as we progress we can add additional methods, such as Tracking etc.

 

 

Now there are two ways of generating our D3DTS_VIEW matrix that we use in "pD3DDevice->SetTransform(D3DTS_VIEW,&view_matrix);" the first is show above the second is to manually create it as follows:

 

 

      // Cameras position

      m_PosX = m_PosY = m_PosZ = 0.0f;

      // Our intial rotational values

      m_RotX = m_RotY = m_RotZ = 0.0f;

     

      D3DXMatrixTranslation(&m_matTranslation, -m_PosX, -m_PosY, -m_PosZ);

     

      D3DXMATRIX mRX, mRY, mRZ;

      D3DXMatrixRotationX(&mRX, -m_RotX);

      D3DXMatrixRotationY(&mRY, -m_RotY);

      D3DXMatrixRotationZ(&mRZ, -m_RotZ);

 

      m_matRotation = mRZ;

      D3DXMatrixMultiply(&m_matRotation, &m_matRotation, &mRY);

      D3DXMatrixMultiply(&m_matRotation, &m_matRotation, &mRX);

 

      // Combine it all

      D3DXMatrixMultiply(&m_matWorld, &m_matTranslation, &m_matRotation);

      m_pD3DDevice->SetTransform(D3DTS_VIEW,&m_matWorld);

 

      D3DXMATRIX  matProj;

      D3DXMatrixPerspectiveFovLH(&matProj, //Result Matrix

                              D3DX_PI/4,//Field of View, in radians. (PI/4) is typical

                              ((float)600 / (float)400),     //Aspect ratio

                              1.0f,     //Near view plane

                              1000.0f ); // Far view plane

 

      m_pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );

 

 

Notice....big thing...that we do things in reverse order...as its the view...we see things from the opposite .... all rotation angles are reversed, and we multiply Translation Matrix by the Rotation Matrix instead of the other way around...e.g. T x R...if you do it the other way around it won't be pretty :-/

 

Now if you look at that wonderful section of code above you'll see that we can set the position and the rotation angles for our camera....allowing us to walk around our 3D world and see everything.... we just have to put it in a nice useable class the CCamera class.

 

#include <xtl.h>

 

class CCamera

{

      IDirect3DDevice8* m_pD3DDevice;

 

      // This is used to set our VIEW in ->SetTransform(D3DTS_VIEW,&m_matWorld)

      D3DXMATRIX m_matWorld;

      D3DXMATRIX m_matTranslation;

      D3DXMATRIX m_matRotation;

 

      // Camera's position in 3D world.

      float m_PosX, m_PosY, m_PosZ;

 

      // The point in 3D space where looking at.

      float m_RotX, m_RotY, m_RotZ;

 

public:

      // Called once for the creation.

      void Create( IDirect3DDevice8** pDevice );

      void Release();

 

      // Called if we want to move our camera around.

      void Move   (float x, float y, float z);

      void MoveRel(float x, float y, float z);

 

      void Rotate   (float x, float y, float z);

      void RotateRel(float x, float y, float z);

public:

      void UpdateCamera(); //Used internally

};

 

And the body (e.g. camera.cpp) is below...its not that complex..it may look it...but just compare it with the above example and see how I've wrapped it into a class.

 

g

#include "camera.h"

 

 

void CCamera::Create( IDirect3DDevice8** pDevice )

{

      m_pD3DDevice = *pDevice;

 

     

      // I'll set an initial position to a little back away from the origin

      m_PosX = m_PosY = 0.0f;

      m_PosZ = -4.0f;

      // Our intial rotational values

      m_RotX = m_RotY = m_RotZ = 0.0f;

     

      D3DXMatrixTranslation(&m_matTranslation, -m_PosX, -m_PosY, -m_PosZ);

     

      D3DXMATRIX mRX, mRY, mRZ;

      D3DXMatrixRotationX(&mRX, -m_RotX);

      D3DXMatrixRotationY(&mRY, -m_RotY);

      D3DXMatrixRotationZ(&mRZ, -m_RotZ);

 

      m_matRotation = mRZ;

      D3DXMatrixMultiply(&m_matRotation, &m_matRotation, &mRY);

      D3DXMatrixMultiply(&m_matRotation, &m_matRotation, &mRX);

 

 

      UpdateCamera();

 

 

      D3DXMATRIX  matProj;

      D3DXMatrixPerspectiveFovLH(&matProj, //Result Matrix

                              D3DX_PI/4,//Field of View, in radians. (PI/4) is typical

                              ((float)600 / (float)400),     //Aspect ratio

                              1.0f,     //Near view plane

                              1000.0f ); // Far view plane

 

      m_pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );

}

 

void CCamera::Release()

{

      // Tidy up if we allocate anything.

}

 

void CCamera::UpdateCamera()

{

      // Combine it all

      D3DXMatrixMultiply(&m_matWorld, &m_matTranslation, &m_matRotation);

      m_pD3DDevice->SetTransform(D3DTS_VIEW,&m_matWorld);

}

 

void CCamera::Move( float x, float y, float z)

{

      // Save our new position

      m_PosX = x;

      m_PosY = y;

      m_PosZ = z;

 

      D3DXMatrixTranslation(&m_matTranslation, -m_PosX, -m_PosY, -m_PosZ);

 

      UpdateCamera();

     

}

 

void CCamera::MoveRel( float x, float y, float z)

{

/*... code */

}

 

void CCamera::Rotate(float x, float y, float z)

{

      // Save our new rotation value.

      m_RotX = x;

      m_RotY = y;

      m_RotZ = z;

 

      D3DXMATRIX mRX, mRY, mRZ;

      D3DXMatrixRotationX(&mRX, -m_RotX);

      D3DXMatrixRotationY(&mRY, -m_RotY);

      D3DXMatrixRotationZ(&mRZ, -m_RotZ);

 

      m_matRotation = mRZ;

      D3DXMatrixMultiply(&m_matRotation, &m_matRotation, &mRY);

      D3DXMatrixMultiply(&m_matRotation, &m_matRotation, &mRX);

 

}

 

void CCamera::RotateRel(float x, float y, float z)

{

/*...code */

}

 

 

 

Using our wonderful CCamera class?  How....easy as pie....

 

IDirect3DDevice8* pD3DDevice; // Already initialized earliear

 

CCamera c;

c.Create( &pD3DDevice );

 

 

c. Move( 0.0f, 10.0f 0.0f);  // our x, y, z position for the camera

c.Rotate( 0.0f, 0.0f, 0.0f);  // Rotate it if we want

 

 

 

c.Release();

 

 

 

Now I've added it to the simple but effective game-engine skeleton that we've created upto now....it allows us to go around our 3D world....all that in the 3D world is a single Cube in the middle...but please don't let me stop you creating a 100 cubes and placing them all over world and exploring.

 

 

// NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

// NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

#include "code/camera/camera.h"

 

class CGame

{

protected:

      // Lets create an instance of our CGraphics class!...m for member, and

      // I chose g for graphics.....not a very descriptive name but I like it.

      CGraphics m_g;

 

      // NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

      CCamera m_camera;

 

      // For the gamepad input

      CGamePad  m_gamepad;

 

      CCube cubeA;

 

public:

      // Initilisation called only once in the constructor

      CGame();

 

      // GameLoop, gets called repeatedly while it returns 1;

      bool GameLoop();

 

      // Cleanup process, all done in our destructor

      ~CGame();

};

 

 

// Initilisation called only once in the constructor

CGame::CGame()

{

      m_g.Create();

 

      m_gamepad.InitGamePad();

 

      IDirect3DDevice8 *pD3DDevice = NULL;

      m_g.GetScreen( &pD3DDevice );

 

      m_camera.Create( &pD3DDevice );

 

      cubeA.Create( &pD3DDevice );

}

 

 

 

// GameLoop, gets called repeatedly while it returns 1;

bool CGame::GameLoop()

{

 

      IDirect3DDevice8 *pD3DDevice = NULL;

      m_g.GetScreen( &pD3DDevice );

 

      float static x = 0.0f;

      float static y = 0.0f;

      float static z = -4.0f;

 

     

      m_gamepad.GetInput();

 

     

      if( m_gamepad.iAnalogStickUp() )

            z += 0.04f;

      if( m_gamepad.iAnalogStickDown() )

            z -= 0.04f;

      if( m_gamepad.iAnalogStickRight() )

            x += 0.04f;

      if( m_gamepad.iAnalogStickLeft() )

            x -= 0.04f;

     

      cubeA.Move( 0.0f,   0.0f,   2.0f);

 

      float static xr = 0.0f;

      float static yr = 0.0f;

      float static zr = 0.0f;

 

      m_camera.Move( x, y, z);

 

      if( m_gamepad.iRightStickUp() )

            xr += 0.01f;

      if( m_gamepad.iRightStickDown() )

            xr -= 0.01f;

      if( m_gamepad.iRightStickLeft() )

            yr -= 0.01f;

      if( m_gamepad.iRightStickRight() )

            yr += 0.01f;

 

 

      m_camera.Rotate( xr, yr, zr );

     

 

      // Lets use it to clear the screen....set it to red ;)

      // Clear the backbuffer to black

      pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 0, 0), 1.0f, 0);

     

     

      // Begin the scene

      pD3DDevice->BeginScene();

 

      cubeA.Render();

 

      // End the scene

      pD3DDevice->EndScene();

     

 

      // Filp the back and front buffers so that whatever has been rendered on the

      // back buffer will now be visible on screen (front buffer).

      pD3DDevice->Present(NULL, NULL, NULL, NULL);

 

     

 

      // Return 1 for the game to continue, 0 to terminate.

      return 1;

}

 

// Cleanup process, all done in our destructor

CGame::~CGame()

{

      m_g.Release();

 

      cubeA.Release();

 

      m_camera.Release();

}

 

 

There you have it....a bit more work and create a First Person Shooter Up.....just like halo ;)

 

 

 

  XFactorDev.net Article



      
webmaster@xfactordev.net