xaxis.x yaxis.x zaxis.x 0
xaxis.y yaxis.y zaxis.y 0
xaxis.z yaxis.z zaxis.z 0
-dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) 1
وحيث
zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)
//===========================
//------------------------------------------------------
// A simple camera class by : Mahmoud Yassin (14 Oct,2006)
// Control Keys: Up - move forward
// Down - move backward
// Left - camera strafes left
// Right - camera strafes Right
// + - move to the right
// - - move to the left
// * - rotate up
// / - rotate down
// Home - camera moves up
// End - camera moves down
//----------------------------------------------------------
#include
#include
#include
#include
HWND g_hWnd = NULL;
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL;
LPD3DXMESH g_pMesh = NULL;
D3DMATERIAL9 *g_pMeshMaterials = NULL;
LPDIRECT3DTEXTURE9 *g_pMeshTextures = NULL;
unsigned long g_dwNumMaterials = 0L;
float g_fElpasedTime;
double g_dCurTime;
double g_dLastTime;
float g_fMoveSpeed = 10.0f;
////////////////////////////////////
// prototypes
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void init(void);
void shutDown(void);
void render(void);
void getUserInput(void);
//////////////////////////////////
// class for simple camera manipulation
class SimpleCamera
{
private:
LPDIRECT3DDEVICE9 m_pd3dDevice;
D3DXMATRIX matXRotation, //rotate about X-Axis (Up-Down)
matYRotation ; //rotate about Y-Axis (Left-Right)
D3DXVECTOR3 m_vEye; // Eye Position
D3DXVECTOR3 m_vLook; // Look Vector
D3DXVECTOR3 m_vUp; // Up Vector
D3DXVECTOR3 m_vRight; // Right Vector
D3DXMATRIX matProj; //projection matrix
D3DXMATRIX view; // view matrix
public:
SimpleCamera(IDirect3DDevice9 * g_pd3dDevice)
{
m_pd3dDevice = g_pd3dDevice;
// set the default camera position
m_vEye=D3DXVECTOR3(0.0f, 2.0f, -10.0f); // Eye Position
m_vLook=D3DXVECTOR3(0.0f, 0.0f, 5.0f); // Look Vector
//up vector is parallel to Y axis
m_vUp=D3DXVECTOR3(0.0f, 1.0f, 0.0f); // Up Vector
//right vector is parallel to X axis
m_vRight=D3DXVECTOR3(1.0f, 0.0f, 0.0f); // Right Vector
//create the projection matrix
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4,
640.0f / 480.0f, 0.1f, 10000.0f );
m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}
//position of the camera
void SetPosition(float x,float y,float z)
{
m_vEye=D3DXVECTOR3(x,y,z);
}
//make the camera look at a specific point
void LookAt(float x,float y,float z)
{
m_vLook=D3DXVECTOR3(x,y,z);
}
//rotate left and right
void RotateLeftRight(float angle)
{
D3DXMatrixRotationAxis( &matYRotation, &D3DXVECTOR3(0,1,0), D3DXToRadian(angle) );
D3DXVec3TransformCoord( &m_vLook, &m_vLook, &matYRotation );
D3DXVec3TransformCoord( &m_vUp, &m_vUp, &matYRotation );
}
//rotate up and down
void RotateUpDown(float angle)
{
D3DXMatrixRotationAxis( &matXRotation, &D3DXVECTOR3(1,0,0), D3DXToRadian(angle) );
D3DXVec3TransformCoord( &m_vLook, &m_vLook, &matXRotation );
D3DXVec3TransformCoord( &m_vUp, &m_vUp, &matXRotation );
}
//----------------------------------------------------------------
// here we have to build the view matrix, it should be in the form:
// | rx ux lx 0 |
// | ry uy ly 0 |
// | rz uz lz 0 |
// | -(r.e) -(u.e) -(l.e) 1 |
// Where r = Right vector
// u = Up vector
// l = Look vector
// e = Eye position in world space
// . = Dot-product operation
//-----------------------------------------------------------------
void UpdateCamera()
{
D3DXMatrixIdentity( &view );
D3DXVec3Normalize( &m_vLook, &m_vLook );
D3DXVec3Cross( &m_vRight, &m_vUp, &m_vLook );
D3DXVec3Normalize( &m_vRight, &m_vRight );
D3DXVec3Cross( &m_vUp, &m_vLook, &m_vRight );
D3DXVec3Normalize( &m_vUp, &m_vUp );
view._11 = m_vRight.x;
view._12 = m_vUp.x;
view._13 = m_vLook.x;
view._14 = 0.0f;
view._21 = m_vRight.y;
view._22 = m_vUp.y;
view._23 = m_vLook.y;
view._24 = 0.0f;
view._31 = m_vRight.z;
view._32 = m_vUp.z;
view._33 = m_vLook.z;
view._34 = 0.0f;
view._41 = -D3DXVec3Dot( &m_vEye, &m_vRight );
view._42 = -D3DXVec3Dot( &m_vEye, &m_vUp );
view._43 = -D3DXVec3Dot( &m_vEye, &m_vLook );
view._44 = 1.0f;
m_pd3dDevice->SetTransform( D3DTS_VIEW, &view );
}
D3DXVECTOR3 GetPosition()
{
return m_vEye;
}
D3DXVECTOR3 GetUpVector()
{
return m_vUp;
}
D3DXVECTOR3 GetRightVector()
{
return m_vRight;
}
D3DXVECTOR3 GetLookVector()
{
return m_vLook;
}
};
SimpleCamera * camera;
// The application's entry point
//--------------------------------------
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
WNDCLASSEX winClass;
MSG uMsg;
memset(&uMsg,0,sizeof(uMsg));
winClass.lpszClassName = "MY_WINDOWS_CLASS";
winClass.cbSize = sizeof(WNDCLASSEX);
winClass.style = CS_HREDRAW | CS_VREDRAW;
winClass.lpfnWndProc = WindowProc;
winClass.hInstance = hInstance;
winClass.hIcon = NULL;//
winClass.hIconSm = NULL;//
winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winClass.lpszMenuName = NULL;
winClass.cbClsExtra = 0;
winClass.cbWndExtra = 0;
if( !RegisterClassEx(&winClass) )
return E_FAIL;
g_hWnd = CreateWindowEx( NULL, "MY_WINDOWS_CLASS",
"Simple Camera - Mahmoud Yassin",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 640, 480, NULL, NULL, hInstance, NULL );
if( g_hWnd == NULL )
return E_FAIL;
ShowWindow( g_hWnd, nCmdShow );
UpdateWindow( g_hWnd );
init();
while( uMsg.message != WM_QUIT )
{
if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &uMsg );
DispatchMessage( &uMsg );
}
else
{
g_dCurTime = timeGetTime();
g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001);
g_dLastTime = g_dCurTime;
render();
}
}
shutDown();
UnregisterClass( "MY_WINDOWS_CLASS", winClass.hInstance );
return uMsg.wParam;
}
//----------------------------------
// Name: WindowProc()
// Desc: The window's message handler
//----------------------------------
LRESULT CALLBACK WindowProc( HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam )
{
switch( msg )
{
case WM_KEYDOWN:
{
switch( wParam )
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
}
break;
case WM_CLOSE:
{
PostQuitMessage(0);
}
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
{
return DefWindowProc( hWnd, msg, wParam, lParam );
}
break;
}
return 0;
}
//------------------------------------------------------------------------------
// Name: getUserInput()
// Desc:
//------------------------------------------------------------------------------
void getUserInput( void )
{
float x_Rot=0.0f,y_Rot=0.0f;
unsigned char keys[256];
GetKeyboardState( keys );
D3DXVECTOR3 tmpLook = camera->GetLookVector();
D3DXVECTOR3 tmpRight = camera->GetRightVector();
D3DXVECTOR3 tmpEye = camera->GetPosition();
// Up
if( keys[VK_UP] & 0x80 )
tmpEye -= tmpLook*-g_fMoveSpeed*g_fElpasedTime;
// Down
if( keys[VK_DOWN] & 0x80 )
tmpEye += (tmpLook*-g_fMoveSpeed)*g_fElpasedTime;
// Left
if( keys[VK_LEFT] & 0x80 )
tmpEye -= (tmpRight*g_fMoveSpeed)*g_fElpasedTime;
// Right
if( keys[VK_RIGHT] & 0x80 )
tmpEye += (tmpRight*g_fMoveSpeed)*g_fElpasedTime;
//------------------------------------
//Rotation left - right
if( keys[VK_SUBTRACT] & 0x80 )
y_Rot-=0.1f;
if( keys[VK_ADD] & 0x80 )
y_Rot+=0.1f;
//Rotation up - down
if( keys[VK_MULTIPLY] & 0x80 )
x_Rot-=0.1f;
if( keys[VK_DIVIDE] & 0x80 )
x_Rot+=0.1f;
// Home Key - move up
if( keys[VK_HOME] & 0x80 )
tmpEye.y += g_fMoveSpeed*g_fElpasedTime;
// End Key - move down
if( keys[VK_END] & 0x80 )
tmpEye.y -= g_fMoveSpeed*g_fElpasedTime;
//update camera position
camera->SetPosition(tmpEye.x,tmpEye.y,tmpEye.z);
//update camera rotations
camera->RotateLeftRight(y_Rot);
camera->RotateUpDown(x_Rot);
}
/////////////////////////////////////
//init 3D then the camera
///////////////////////////////////
void init( void )
{
g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
D3DDISPLAYMODE d3ddm;
g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice );
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
//-------------------------------
LPD3DXBUFFER pD3DXMtrlBuffer;
HRESULT hr = D3DXLoadMeshFromX("mesh.x", D3DXMESH_SYSTEMMEM,
g_pd3dDevice, NULL,
&pD3DXMtrlBuffer, NULL, &g_dwNumMaterials,
&g_pMesh );
if (FAILED(hr))
{
MessageBox(0,"can not find the mesh file","error",0);
exit(0);
}
// We need to extract the material properties and texture names
// from the pD3DXMtrlBuffer
D3DXMATERIAL *d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials];
g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials];
for( unsigned long i = 0; i < g_dwNumMaterials; ++i )
{
// Copy the material over...
g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
// Set the ambient color for the material (D3DX does not do this)
g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse;
// Create the texture...
g_pMeshTextures[i] = NULL;
D3DXCreateTextureFromFile( g_pd3dDevice, d3dxMaterials[i].pTextureFilename,
&g_pMeshTextures[i] );
}
pD3DXMtrlBuffer->Release();
//now create the camera
camera=new SimpleCamera(g_pd3dDevice);
}
// shutDown()
void shutDown( void )
{
if( g_pMeshMaterials != NULL )
delete[] g_pMeshMaterials;
if( g_pMeshTextures != NULL )
{
for( unsigned long i = 0; i < g_dwNumMaterials; i++ )
{
if( g_pMeshTextures[i] != NULL )
g_pMeshTextures[i]->Release();
}
delete[] g_pMeshTextures;
}
if( g_pMesh != NULL )
g_pMesh->Release();
if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();
if( g_pD3D != NULL )
g_pD3D->Release();
}
///////////////////////////////
//render everything here
///////////////////////////////
void render( void )
{
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_COLORVALUE(0.0f, 0.0f, 1.0, 0.5f), 1.0f, 0 );
//read keyboard input
getUserInput();
//here I update the view matrix and the orientation
camera->UpdateCamera();
D3DXMATRIX matWorld;
D3DXMatrixScaling( &matWorld, 5.0f, 5.0f, 5.0f );
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
g_pd3dDevice->BeginScene();
for( unsigned long i = 0; i < g_dwNumMaterials; i++ )
{
g_pd3dDevice->SetMaterial( &g_pMeshMaterials[i] );
g_pd3dDevice->SetTexture( 0, g_pMeshTextures[i] );
g_pMesh->DrawSubset( i );
}
g_pd3dDevice->EndScene();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}