title: c++ first person camera in directx
body: <p>m a beginner programmer and im creating a project which allows me to walk around rooms via a first person camera so far i have the buildings drawn etc but now im stuck and don't know how to make a first person camera to allow me to walk around could anyone point me towards a camera class i could use or some useful code? thanks in advance</p>
  
  <p>below is the code for one of my buildings but not my full project, its rotating so i could see what i was drawing.
  i want to be able to move forwards and backwards using the arrow keys and also left and right :)</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;d3d9.h&gt;
  #include &lt;d3dx9.h&gt;
  #include &lt;dinput.h&gt;
  #include &lt;math.h&gt;
  
  const char TITLE[] = "game experimenting";
  
  
  
  #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
  
  //*****Direct 3D Initialization*****
  LPDIRECT3D9             g_pD3D       = NULL; 
  LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; 
  
  // Buffer to hold vertices
  LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL; 
  
  //Direct Input References
  LPDIRECTINPUT8 m_pDIObject = NULL;//DirectInput object
  LPDIRECTINPUTDEVICE8 m_pDIKeyboardDevice = NULL;//keyboard device
  LPDIRECTINPUTDEVICE8 m_pDIMouseDevice = NULL;//mouse device
  LPDIRECTINPUTDEVICE8 m_pDIJoystickDevice = NULL;//joystick device
  
  //D3DXMATRIX Transformation Matrices
  D3DXMATRIX g_matProj;
  D3DXMATRIX g_matView;
  D3DXMATRIX g_matWorld;
  //**********************
  
  //****** Vertex Buffer Definition and Setting ***
  
  struct CUSTOMVERTEX
  {
      FLOAT x, y, z; // The position for the vertex
      DWORD color;        // The vertex color
  };
  
  
  int numberOfTriangles = 34;
  int numberOfVertecies = 3*numberOfTriangles;
  float scale = 1.0f;
  float doorHeight = 1.0f;
  float doorWidth = 0.25f;
  
  CUSTOMVERTEX g_Vertices[] =
  {
      // Y +Axis 
      //Top Side Outer Wall
      { 1.0f, 1.0f,-1.0f, 0xffffffff, }, 
      { 1.0f, 1.0f,1.0f,  0xffffffff, }, 
      { -1.0f,1.0f, -1.0f, 0xffffffff,}, //Triangle 
      { -1.0f,1.0f, 1.0f, 0xffffffff,}, 
      { 1.0f, 1.0f, 1.0f, 0xffffffff, }, 
      { -1.0f,1.0f, -1.0f, 0xffffffff,}, //Triangle 
      //Top Side Inner Wall
      { 0.9f, 0.9f,-0.9f, 0x00ff0000, }, 
      { 0.9f, 0.9f,0.9f,  0x00ff0000, }, 
      { -0.9f,0.9f, -0.9f, 0x00ff0000,}, //Triangle 
      { -0.9f,0.9f, 0.9f, 0x00ff0000,}, 
      { 0.9f, 0.9f, 0.9f, 0x00ff0000, }, 
      { -0.9f,0.9f, -0.9f, 0x00ff0000,}, //Triangle 
  
      // X +Axis 
      //Right Side Outer Wall
      { 1.0f, 1.0f,-1.0f, 0xffffffff, }, 
      { 1.0f, 1.0f,1.0f,  0xffffffff, }, 
      { 1.0f,-1.0f, -1.0f, 0xffffffff,}, /////Triangle 
      { 1.0f,-1.0f, 1.0f, 0xffffffff,}, 
      { 1.0f, 1.0f, 1.0f, 0xffffffff, }, 
      { 1.0f,-1.0f, -1.0f, 0xffffffff,}, /////Triangle 
  
      //Right Side Inner Wall
      { 0.9f, 0.9f,-0.9f, 0xff0000ff, }, 
      { 0.9f, 0.9f,0.9f,  0xff0000ff, }, 
      { 0.9f,-1.0f, -0.9f, 0xff0000ff,}, /////Triangle 
      { 0.9f,-1.0f, 0.9f, 0xff0000ff,}, 
      { 0.9f, 0.9f, 0.9f, 0xff0000ff, }, 
      { 0.9f,-1.0f, -0.9f, 0xff0000ff,}, /////Triangle 
  
      // X -Axis 
      //Left Side Outer Wall
      {-1.0f, 1.0f,-1.0f, 0xffffffff, }, 
      {-1.0f, 1.0f,1.0f,  0xffffffff, }, 
      {-1.0f,-1.0f, -1.0f, 0xffffffff,}, /////Triangle 
      {-1.0f,-1.0f, 1.0f, 0xffffffff,}, 
      {-1.0f, 1.0f, 1.0f, 0xffffffff, }, 
      {-1.0f,-1.0f, -1.0f, 0xffffffff,}, /////Triangle 
  
      //Left Side Inner Wall
      {-0.9f, 0.9f,-0.9f, 0xff0000ff, }, 
      {-0.9f, 0.9f,0.9f,  0xff0000ff, }, 
      {-0.9f,-1.0f, -0.9f, 0xff0000ff,}, /////Triangle 
      {-0.9f,-1.0f, 0.9f, 0xff0000ff,}, 
      {-0.9f, 0.9f, 0.9f, 0xff0000ff, }, 
      {-0.9f,-1.0f, -0.9f, 0xff0000ff,}, /////Triangle 
  
      // Z +Axis  
      //Back Outer Wall
      { 1.0f,-1.0f, 1.0f, 0xffffffff, }, 
      { 1.0f, 1.0f, 1.0f, 0xffffffff, }, 
      { -1.0f,-1.0f, 1.0f, 0xffffffff,}, /////Triangle 
      { -1.0f,1.0f, 1.0f, 0xffffffff,}, 
      { 1.0f, 1.0f, 1.0f, 0xffffffff, }, 
      { -1.0f,-1.0f, 1.0f, 0xffffffff,}, /////Triangle 
  
      //Back Inner Wall
      { 0.9f,-1.0f, 0.9f, 0xff0000ff, }, 
      { 0.9f, 0.9f, 0.9f, 0xff0000ff, }, 
      { -0.9f,-1.0f, 0.9f, 0xff0000ff,}, /////Triangle 
      { -0.9f,0.9f, 0.9f, 0xff0000ff,}, 
      { 0.9f, 0.9f, 0.9f, 0xff0000ff, }, 
      { -0.9f,-1.0f, 0.9f, 0xff0000ff,}, /////Triangle 
  
      // Z Negative Axis 
      //Front Outer Wall Top1
      { 1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff, }, 
      { 1.0f, 1.0f, -1.0f, 0xffffffff, }, 
      { -1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, /////Triangle 
      //Front Outer Wall Top2
      { -1.0f, 1.0f, -1.0f, 0xffffffff, }, 
      { 1.0f, 1.0f, -1.0f, 0xffffffff, }, 
      { -1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, /////Triangle 
      //Front Outer Wall Left1
      { -1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, 
      { -1.0f,-1.0f, -1.0f, 0xffffffff,}, 
      { -1.0f+(scale-doorWidth),-1.0f, -1.0f, 0xffffffff,}, /////Triangle
      //Front Outer Wall Left2
      { -1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, 
      { -1.0f+(scale-doorWidth),-1.0f, -1.0f, 0xffffffff,}, 
      { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffffffff,}, /////Triangle
      //Front Outer Wall Right1
      { 1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, 
      { 1.0f,-1.0f, -1.0f, 0xffffffff,}, 
      { 1.0f-(scale-doorWidth),-1.0f, -1.0f, 0xffffffff,}, /////Triangle
      //Front Outer Wall Right2
      { 1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, 
      { 1.0f-(scale-doorWidth),-1.0f, -1.0f, 0xffffffff,}, 
      { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffffffff,}, /////Triangle
  
      //Door Inner Edges Right of door 1
      { 1.0f-(scale-doorWidth),-1.0f, -1.0f, 0xffff0099,}, 
      { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,}, 
      { 1.0f-(scale-doorWidth),-1.0f, -0.9f, 0xffff0099,}, /////Triangle
      //Door Inner Edges Right of door 2
      { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,}, 
      { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xffff0099,}, 
      { 1.0f-(scale-doorWidth),-1.0f, -0.9f, 0xffff0099,}, /////Triangle
      //Door Inner Edges Left of door 1
      { -1.0f+(scale-doorWidth),-1.0f, -1.0f, 0xffff0099,}, 
      { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,}, 
      { -1.0f+(scale-doorWidth),-1.0f, -0.9f, 0xffff0099,}, /////Triangle
      //Door Inner Edges Left of door 2
      { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,}, 
      { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xffff0099,},
      { -1.0f+(scale-doorWidth),-1.0f, -0.9f, 0xffff0099,}, /////Triangle
      //Door Inner Edges Top Of Door 1
      { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,},
      { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,}, 
      { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xffff0099,}, /////Triangle
      //Door Inner Edges Top Of Door 2
      { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xffff0099,}, 
      { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,},
      { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xffff0099,}, /////Triangle
  
      //FRONT Inner Wall Top1
      { 0.9f,-1.0f+doorHeight, -0.9f, 0xff0000ff, }, 
      { 0.9f, 1.0f, -0.9f, 0xff0000ff, }, 
      { -0.9f,-1.0f+doorHeight, -0.9f, 0xff0000ff,}, /////Triangle 
      //FRONT Inner Wall Top2
      { -0.9f, 1.0f, -0.9f, 0xff0000ff, }, 
      { 0.9f, 1.0f, -0.9f, 0xff0000ff, }, 
      { -0.9f,-1.0f+doorHeight, -0.9f, 0xff0000ff,}, /////Triangle 
      //FRONT Inner Wall Left1
      { -0.9f,-1.0f+doorHeight, -0.9f, 0xff0000ff,}, 
      { -0.9f,-1.0f, -0.9f, 0xff0000ff,}, 
      { -1.0f+(scale-doorWidth),-1.0f, -0.9f, 0xff0000ff,}, /////Triangle
      //FRONT Inner Wall Left2
      { -0.9f,-1.0f+doorHeight, -0.9f, 0xff0ff0ff,}, 
      { -1.0f+(scale-doorWidth),-1.0f, -0.9f, 0xff0ff0ff,}, 
      { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xff0ff0ff,}, /////Triangle  
      //FRONT Inner Wall Right1
      { 0.9f,-1.0f+doorHeight, -0.9f, 0xff0ff0ff,}, 
      { 0.9f,-1.0f, -0.9f, 0xff0ff0ff,}, 
      { 1.0f-(scale-doorWidth),-1.0f, -0.9f, 0xff0ff0ff,}, /////Triangle
      //FRONT Inner Wall Right2
      { 0.9f,-1.0f+doorHeight, -0.9f, 0xff0000ff,}, 
      { 1.0f-(scale-doorWidth),-1.0f, -0.9f, 0xff0000ff,}, 
      { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xff0000ff,}, /////Triangle
  
      };
  
  //*******************************************************************
  // Name: SetupMatrices()
  // Desc: Sets up the world, view, and projection transform matrices.
  //-------------------------------------------------------------------
  void SetupMatrices()
  {
      static float time = 0.0f;
      time += 10.0f;
  
      D3DXMatrixIdentity( &amp;g_matWorld );
      D3DXMatrixRotationYawPitchRoll( &amp;g_matWorld,
          time/1000.0f,
          time/700.0f,
          time/850.0f );
      g_pd3dDevice-&gt;SetTransform( D3DTS_WORLD, &amp;g_matWorld );
  
      D3DXMatrixLookAtLH( &amp;g_matView, &amp;D3DXVECTOR3( 0.0f, 0.0f,-5.0f ),
          &amp;D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
          &amp;D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
      g_pd3dDevice-&gt;SetTransform( D3DTS_VIEW, &amp;g_matView );
  
      D3DXMatrixPerspectiveLH(&amp;g_matProj, 2.0f, 2.0f/1.5f,
          1.0f, 10000.0f);
      g_pd3dDevice-&gt;SetTransform( D3DTS_PROJECTION, &amp;g_matProj );
  }
  
  void TestForMouse()
  {
      DIMOUSESTATE mouseState;
      m_pDIMouseDevice-&gt;GetDeviceState(sizeof(mouseState),
          (LPVOID)&amp;mouseState);
      if(mouseState.rgbButtons[0] &amp; 0x80) // left mouse button down
      {
      }
  }
  
  //************************ MESSAGE HANDLER **************************
  
  LRESULT CALLBACK WindowProc(HWND hwnd, 
      UINT msg, 
      WPARAM wparam, 
      LPARAM lparam)
  {
      // this is the main message handler of the system
      PAINTSTRUCT     ps; // used in WM_PAINT
      HDC             hdc;    // handle to a device context
  
      // what is the message 
      switch(msg)
      {   
      case WM_CREATE: 
          {
              // do initialization stuff here
              return(0);
          } 
  
      case WM_PAINT: 
          {
              // validate the window
              hdc = BeginPaint(hwnd,&amp;ps);  
              EndPaint(hwnd,&amp;ps);
              return(0);
          } 
  
      case WM_KEYDOWN:
          {
              // Handle any non-accelerated key commands
              switch (wparam)
              {
              case VK_ESCAPE:
              case VK_F12:
                  PostMessage(hwnd, WM_CLOSE, 0, 0);
                  return (0);
              default:
                  char message[15];
                  sprintf_s(message, "Key Pressed: %c", (char)wparam);
                  MessageBox(NULL, message, "Key Pressed", MB_OK);
              }
              break;
          }
  
      case WM_DESTROY: 
          {
              // kill the application         
              PostQuitMessage(0);
  
              return(0);
          }
  
      default:
          break;
  
      } // end switch
  
      // process any messages that wasn't taken care of
      return (DefWindowProc(hwnd, msg, wparam, lparam));
  
  } // end WinProc
  
  
  //********************* END OF MESSAGE HANDLER ***********************
  
  void InitializeDX(HWND hwnd)
  { 
      if(!( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
          MessageBox(hwnd,"Direct3d Create problem", NULL, NULL);
  
      D3DPRESENT_PARAMETERS d3dpp; 
      ZeroMemory( &amp;d3dpp, sizeof(d3dpp) );
      d3dpp.Windowed = TRUE;
      d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
      d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
      d3dpp.EnableAutoDepthStencil = TRUE;
      d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
  
      if(FAILED( g_pD3D-&gt;CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
          D3DCREATE_SOFTWARE_VERTEXPROCESSING,
          &amp;d3dpp, &amp;g_pd3dDevice ) ) )
          MessageBox(hwnd,"CreateDevice problem", NULL, NULL);
  
      //InitializeCircleArray();
      //InitializeSquareArray();
  
      //*************************** Create Vertex Buffer ****************************
      if( FAILED( g_pd3dDevice-&gt;CreateVertexBuffer( numberOfVertecies*sizeof(CUSTOMVERTEX),
          0 /* Usage */, D3DFVF_CUSTOMVERTEX,
          D3DPOOL_MANAGED, &amp;g_pVB, NULL ) ) )
          MessageBox(hwnd,"Vertex Buffer problem",NULL,NULL);
  
      VOID* pVertices;
      if( FAILED( g_pVB-&gt;Lock( 0, sizeof(g_Vertices), (void**)&amp;pVertices, 0 ) ) )
          MessageBox(hwnd,"Vertex Lock Problem",NULL,NULL);
  
      memcpy( pVertices, g_Vertices, sizeof(g_Vertices) );
  
      g_pVB-&gt;Unlock();
  
      g_pd3dDevice-&gt;SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer
  }
  void InitializeDI(HWND hwnd)
  {
      if(FAILED(DirectInput8Create(GetModuleHandle(NULL),
          DIRECTINPUT_VERSION,
          IID_IDirectInput8,
          (void**)&amp;m_pDIObject,
          NULL)))
          MessageBox(hwnd,"DirectInput8Create() failed!",NULL,NULL);
      // Setup Mouse Input
      if(FAILED(m_pDIObject-&gt;CreateDevice(GUID_SysMouse,
          &amp;m_pDIMouseDevice,
          NULL)))
          MessageBox(hwnd,"CreateDevice() failed!",NULL,NULL);
      if(FAILED(m_pDIMouseDevice-&gt;SetDataFormat(&amp;c_dfDIMouse)))
          MessageBox(hwnd,"SetDataFormat() failed!",NULL,NULL);
      if(FAILED(m_pDIMouseDevice-&gt;SetCooperativeLevel(hwnd,
          DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
          MessageBox(hwnd,"SetCooperativeLevel() failed!",NULL,NULL);
      if(FAILED(m_pDIMouseDevice-&gt;Acquire()))
          MessageBox(hwnd,"Acquire() failed!",NULL,NULL);
  }
  
  //**************************Render and display the scene***********************
  void Render()
  {
      g_pd3dDevice-&gt;Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
  
      // Turn off D3D lighting,
      // providing our own vertex colours
      g_pd3dDevice-&gt;SetRenderState( D3DRS_LIGHTING, FALSE );
  
      // Turn off culling
      g_pd3dDevice-&gt;SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  
      // Begin the scene
      if( SUCCEEDED( g_pd3dDevice-&gt;BeginScene() ) )
      {
          SetupMatrices();
          // Rendering of scene objects can happen here
          g_pd3dDevice-&gt;SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
          g_pd3dDevice-&gt;SetFVF( D3DFVF_CUSTOMVERTEX );
          //g_pd3dDevice-&gt;DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 179 ); // 179 triangles from 181 vertices
          //g_pd3dDevice-&gt;DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
  
          g_pd3dDevice-&gt;DrawPrimitive( D3DPT_TRIANGLELIST, 0,  numberOfTriangles ); //1 triangle
          // End the scene
          g_pd3dDevice-&gt;EndScene();
      }
  
      g_pd3dDevice-&gt;Present( NULL, NULL, NULL, NULL );
  }
  
  //************************ WIN MAIN***********************
  
  int WINAPI WinMain( HINSTANCE hinstance,
      HINSTANCE hprevinstance,
      LPSTR lpcmdline,
      int ncmdshow)
  {
      WNDCLASS    winclass;   // this will hold the class
      HWND        hwnd;       // generic window handle
      MSG         msg;        // generic message
  
      // first fill in the window class stucture
      winclass.style          = CS_HREDRAW | CS_VREDRAW;                  
      winclass.lpfnWndProc    = WindowProc;
      winclass.cbClsExtra     = 0;
      winclass.cbWndExtra     = 0;
      winclass.hInstance      = hinstance;
      winclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
      winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
      //  winclass.hbrBackground  = (HBRUSH)GetStockObject(BLACK_BRUSH);
      //  winclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);
      winclass.hbrBackground  = (HBRUSH)CreateSolidBrush(RGB(255, 0, 0));
      winclass.lpszMenuName   = NULL;
      winclass.lpszClassName  = "DX9WinClass";
  
      // register the window class
      if (!RegisterClass(&amp;winclass))
          return(0);
  
      // create the window
      if (!(hwnd = CreateWindow( "DX9WinClass", // class
          TITLE,       // title
          WS_OVERLAPPEDWINDOW | WS_VISIBLE,
          0,
          0,
          //Set the size of the window to the size of the screen 
          600,
          400,
          //GetSystemMetrics(SM_CXSCREEN),
          //GetSystemMetrics(SM_CYSCREEN),
          NULL,      // handle to parent 
          NULL,      // handle to menu
          hinstance,  // instance
          NULL))) // creation parms
          return(0);
  
      InitializeDX(hwnd);
      InitializeDI(hwnd);
  
      // enter main event loop
      bool quit = false;
      while(!quit)
      {
          TestForMouse();
          if (PeekMessage(&amp;msg,NULL,0,0,PM_REMOVE))
          { 
              // test if this is a quit
              if (msg.message == WM_QUIT) quit = true;
  
              // translate any accelerator keys
              TranslateMessage(&amp;msg);
              // send the message to the window proc
              DispatchMessage(&amp;msg);
          } // end if
          else {
              Render();
          }
  
      } // end while
  
      //Set Mouse Free Run Away Mouse
      m_pDIMouseDevice-&gt;Release();
      // return to Windows like this
      return(msg.wParam);
  
  } // end WinMain
  
  
  //************************ END OF WIN MAIN *******************
  </code></pre>