[引] 键盘控制3D场景漫游
//做了好久都不能整合鼠标做CS那样的运动引擎....看来暂时都只能用键盘控制了
//-----------------------------------------------------------------------------
// File: basic.cpp
//
//-----------------------------------------------------------------------------
#define STRICT
#include <Windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <math.h>
#include <D3DX9.h>
#include "DXUtil.h"
#include "D3DEnumeration.h"
#include "D3DSettings.h"
#include "D3DApp.h"
#include "D3DFile.h"
#include "D3DFont.h"
#include "D3DUtil.h"
#include "resource.h"
//-----------------------------------------------------------------------------
// Name: class CMyD3DApplication
// Desc: Application class. The base class (CD3DApplication) provides the
// generic functionality needed in all Direct3D samples. CMyD3DApplication
// adds functionality specific to this sample program.
//-----------------------------------------------------------------------------
class CMyD3DApplication : public CD3DApplication
{
LPD3DXMESH m_pMesh; //Mesh对象的接口指针
D3DMATERIAL9 *m_pMeshMaterials; //用于保存模型中各个子集的材质
LPDIRECT3DTEXTURE9 *m_pMeshTextures;//用于保存模型中各个子集的纹理
DWORD m_dwNumSubsets; //模型中子集的数目
TCHAR m_strMeshFilename[512];
TCHAR m_strInitialDir[512];
//CD3DArcBall m_ArcBall; // Mouse rotation utility
D3DXVECTOR3 m_vObjectCenter; // Center of bounding sphere of object
FLOAT m_fObjectRadius; // Radius of bounding sphere of object
D3DXVECTOR3 VDot,VAtPoint,VUp;//全局观察变量
BYTE m_bKey[256]; // keyboard state buffer
protected:
HRESULT OneTimeSceneInit();
HRESULT InitDeviceObjects();
HRESULT RestoreDeviceObjects();
HRESULT InvalidateDeviceObjects();
HRESULT DeleteDeviceObjects();
HRESULT FinalCleanup();
HRESULT Render();
HRESULT FrameMove();
HRESULT ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,
D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat );
LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
public:
CMyD3DApplication();
};
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything, and goes into a
// message-processing loop. Idle time is used to render the scene.
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
CMyD3DApplication d3dApp;
InitCommonControls();
if( FAILED( d3dApp.Create( hInst ) ) )
return 0;
return d3dApp.Run();
}
//-----------------------------------------------------------------------------
// Name: CMyD3DApplication()
// Desc: Application constructor. Sets attributes for the app.
//-----------------------------------------------------------------------------
CMyD3DApplication::CMyD3DApplication()
{
m_bStartFullscreen=TRUE;
//m_dwCreationWidth = 800; // Width used to create window
//m_dwCreationHeight = 600;
// Override base class members
m_strWindowTitle = _T("加载Mesh模型");
m_d3dEnumeration.AppUsesDepthBuffer = TRUE;
DXUtil_GetDXSDKMediaPathCb( m_strInitialDir, sizeof(m_strInitialDir) );
_tcscpy( m_strMeshFilename, _T("this.x") );
//初始化
ZeroMemory( m_bKey, 256 );
}
//-----------------------------------------------------------------------------
// Name: ConfirmDevice()
// Desc: Called during device initialization, this code checks the device
// for some minimum set of capabilities
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,
D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat )
{
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: OneTimeSceneInit()
// Desc: Called during initial app startup, this function performs all the
// permanent initialization.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::OneTimeSceneInit()
{
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InitDeviceObjects()
// Desc: Initialize scene objects.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::InitDeviceObjects()
{
LPD3DXBUFFER pD3DXMtrlBuffer;
TCHAR strMeshPath[512];
// Load the mesh from the specified file
DXUtil_FindMediaFileCb( strMeshPath, sizeof(strMeshPath), m_strMeshFilename );
//从.x文件创建Mesh对象
::D3DXLoadMeshFromX(
strMeshPath, D3DXMESH_SYSTEMMEM, m_pd3dDevice,
NULL, &pD3DXMtrlBuffer, NULL,
&m_dwNumSubsets, //返回模型中子集的数目
&m_pMesh ); //返回Mesh对象的接口指针
m_pMeshMaterials = new D3DMATERIAL9[m_dwNumSubsets];
m_pMeshTextures = new LPDIRECT3DTEXTURE9[m_dwNumSubsets];
ZeroMemory(m_pMeshMaterials , sizeof(D3DMATERIAL9) * m_dwNumSubsets);
ZeroMemory(m_pMeshTextures , sizeof(LPDIRECT3DTEXTURE9) * m_dwNumSubsets);
//从接口指针pD3DXMtrlBuffer获得各个子集的材质和纹理图片的文件名
D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
for( DWORD i=0; i < m_dwNumSubsets; i++ )
{
//复制子集的材质
m_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
//Direct3D在调入Mesh模型时,没有设置材质的环境光颜色,
//这里把它设置成和漫反射一样的颜色。
m_pMeshMaterials[i].Ambient = m_pMeshMaterials[i].Diffuse;
TCHAR strTexturePath[512] = _T("");
DXUtil_FindMediaFileCb( strTexturePath, sizeof(strTexturePath), d3dxMaterials[i].pTextureFilename );
//调入纹理图片
::D3DXCreateTextureFromFile(
m_pd3dDevice,
strTexturePath, //纹理图片的文件名
&m_pMeshTextures[i] );
}
pD3DXMtrlBuffer->Release(); //释放接口
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: RestoreDeviceObjects()
// Desc: Initialize scene objects.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::RestoreDeviceObjects()
{
m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,
D3DCOLOR_COLORVALUE(0.7,0.7,0.7,0.7 ));
// Set the arcball parameters
m_ArcBall.SetWindow( m_d3dsdBackBuffer.Width, m_d3dsdBackBuffer.Height,
0.85f );
m_ArcBall.SetRadius( m_fObjectRadius );
// Set the projection matrix
D3DXMATRIXA16 matProj;
::D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 10000.0f );
m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
D3DXMATRIX matView;
D3DXMatrixLookAtLH( &matView,&VDot, &VAtPoint, &VUp );
m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InvalidateDeviceObjects()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::InvalidateDeviceObjects()
{
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: DeleteDeviceObjects()
// Desc: Called when the app is exiting, or the device is being changed,
// this function deletes any device dependent objects.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::DeleteDeviceObjects()
{
for (DWORD i = 0; i < m_dwNumSubsets; i++)
m_pMeshTextures[i]->Release(); //释放纹理对象
delete [] m_pMeshMaterials;
delete [] m_pMeshTextures;
m_pMesh->Release(); //释放Mesh对象
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: FrameMove()
// Desc: Called once per frame, the call is the entry point for animating
// the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::FrameMove()
{
// Setup world matrix
float angle = 3 * D3DX_PI / 180;
D3DXMATRIX matWorld;
::D3DXMatrixRotationY( &matWorld, angle );
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
// Set up view matrix
float fRoll=0, fPitch =0, fYaw = 0.0f;
float fOneStep=1.5;
D3DXVECTOR3 vPos(0.0f, 0.0f, 0.0f);
static D3DXMATRIX matView = D3DXMATRIX(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
// Process keyboard input
if (m_bKey[VK_UP]) fPitch -= fOneStep*0.05; // Pitch Up
if (m_bKey[VK_DOWN]) fPitch += fOneStep*0.05; // Pitch Down
if (m_bKey[VK_LEFT]) fYaw -= fOneStep*0.05; // Turn Left
if (m_bKey[VK_RIGHT]) fYaw += fOneStep*0.05; // Turn Right
//if (m_bKey['C']) fRoll += fOneStep; // Rotate Left
//if (m_bKey['X']) fRoll -= fOneStep; // Rotate Right
if (m_bKey['W']) vPos.z += fOneStep; // Move Forward
if (m_bKey['S']) vPos.z -= fOneStep; // Move Backward
if (m_bKey['A']) vPos.x -= fOneStep; // Slide Left
if (m_bKey['D']) vPos.x += fOneStep; // Slide Right
if (m_bKey['Q']) vPos.y += fOneStep; // Slide Down
if (m_bKey['E']) vPos.y -= fOneStep; // Slide Up
// Update position and view matricies
D3DXMATRIX matR, matTemp;
D3DXQUATERNION qR;
D3DXQuaternionRotationYawPitchRoll (&qR, fYaw, fPitch, fRoll);
D3DXMatrixRotationQuaternion (&matR, &qR);
D3DXMatrixMultiply (&matView, &matR, &matView);
D3DXMatrixTranslation (&matTemp, vPos.x, vPos.y, vPos.z);
D3DXMatrixMultiply (&matView, &matTemp, &matView);
D3DXMatrixInverse (&matTemp, NULL, &matView);
//D3DXMatrixMultiply(&matTemp,&matTemp,m_ArcBall.GetRotationMatrix());
m_pd3dDevice->SetTransform(D3DTS_VIEW, &matTemp );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Called once per frame, the call is the entry point for 3d
// rendering. This function sets up render states, clears the
// viewport, and renders the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::Render()
{
// Clear the backbuffer
m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0x000000ff, 1.0f, 0x00000000 );
// Begin the scene
if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
{
//m_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);//解决发暗问题
for( DWORD i=0; i < m_dwNumSubsets; i++ )
{
//设置子集的材质
m_pd3dDevice->SetMaterial( &m_pMeshMaterials[i] );
//设置子集的纹理,混合方式使用缺省值:纹理 × 材质的漫反射
m_pd3dDevice->SetTexture( 0, m_pMeshTextures[i] );
//绘制子集
m_pMesh->DrawSubset( i );
m_pd3dDevice->SetTexture( 0, NULL);
}
// End the scene.
m_pd3dDevice->EndScene();
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: FinalCleanup()
// Desc: Called before the app exits, this function gives the app the chance
// to cleanup after itself.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::FinalCleanup()
{
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: Message proc function to handle key and menu input
//-----------------------------------------------------------------------------
LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam )
{
// Pass mouse messages to the ArcBall so it can build internal matrices
//m_ArcBall.HandleMouseMessages( hWnd, uMsg, wParam, lParam );
// Record key presses
if( WM_KEYDOWN == uMsg )
{
m_bKey[wParam] = 1;
}
// Perform commands when keys are rleased
if( WM_KEYUP == uMsg )
{
m_bKey[wParam] = 0;
}
// Pass remaining messages to default handler
return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
}