您的位置:首页 > 编程语言

修改DX代码:实现按方向键上下能控制摄像机的距离

2011-01-20 12:58 621 查看
Code:

//////////////////////////////////////////////////////////////////////////////////////////////////

// 2011/1/20

// cube.cpp文件:

//

// 渲染组旋转立方体在网格模式。演示了顶点和索引缓存,世界和观点变换

// *新增功能:按方向键能上下左右能调整摄像机距离和目标的距离

//////////////////////////////////////////////////////////////////////////////////////////////////

#include "d3dUtility.h"

//

// 全局设置

//

IDirect3DDevice9* Device = 0; //dx设备对象

const int Width = 640;

const int Height = 480;

IDirect3DVertexBuffer9* VB = 0;

IDirect3DIndexBuffer9* IB = 0;

D3DXVECTOR3 position(0.0f, 0.0f, -5.0f); //视角位置

D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); //目标

D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); //高度

D3DXMATRIX V; //表面,看到的东西

//

// 顶点/类和结构

//

struct Vertex

{

Vertex(){}

Vertex(float x, float y, float z)

{

_x = x; _y = y; _z = z;

}

float _x, _y, _z;

static const DWORD FVF;

};

const DWORD Vertex::FVF = D3DFVF_XYZ;

//

//框架功能

//

bool Setup()

{

//

// 创建顶点和索引缓冲.

//

Device->CreateVertexBuffer(

8 * sizeof(Vertex),

D3DUSAGE_WRITEONLY,

Vertex::FVF,

D3DPOOL_MANAGED,

&VB,

0);

Device->CreateIndexBuffer(

36 * sizeof(WORD),

D3DUSAGE_WRITEONLY,

D3DFMT_INDEX16,

D3DPOOL_MANAGED,

&IB,

0);

//

// 填补缓冲器与立方体数据。

//

// 定义独特的顶点。

Vertex* vertices;

VB->Lock(0, 0, (void**)&vertices, 0);

// vertices of a unit cube

vertices[0] = Vertex(-1.0f, -1.0f, -1.0f);

vertices[1] = Vertex(-1.0f, 1.0f, -1.0f);

vertices[2] = Vertex( 1.0f, 1.0f, -1.0f);

vertices[3] = Vertex( 1.0f, -1.0f, -1.0f);

vertices[4] = Vertex(-1.0f, -1.0f, 1.0f);

vertices[5] = Vertex(-1.0f, 1.0f, 1.0f);

vertices[6] = Vertex( 1.0f, 1.0f, 1.0f);

vertices[7] = Vertex( 1.0f, -1.0f, 1.0f);

VB->Unlock();

// 定义三角面的立方体:

WORD* indices = 0;

IB->Lock(0, 0, (void**)&indices, 0);

//正面

indices[0] = 0; indices[1] = 1; indices[2] = 2;

indices[3] = 0; indices[4] = 2; indices[5] = 3;

//背面

indices[6] = 4; indices[7] = 6; indices[8] = 5;

indices[9] = 4; indices[10] = 7; indices[11] = 6;

//左面

indices[12] = 4; indices[13] = 5; indices[14] = 1;

indices[15] = 4; indices[16] = 1; indices[17] = 0;

//右面

indices[18] = 3; indices[19] = 2; indices[20] = 6;

indices[21] = 3; indices[22] = 6; indices[23] = 7;

//顶面

indices[24] = 1; indices[25] = 5; indices[26] = 6;

indices[27] = 1; indices[28] = 6; indices[29] = 2;

//底面

indices[30] = 4; indices[31] = 0; indices[32] = 3;

indices[33] = 4; indices[34] = 3; indices[35] = 7;

IB->Unlock();

//

// 位置和目标照相机。

//

D3DXMatrixLookAtLH(&V, &position, &target, &up); //摄像机函数

Device->SetTransform(D3DTS_VIEW, &V); //转换为试图

//

// 投影矩阵的.

//

D3DXMATRIX proj;

D3DXMatrixPerspectiveFovLH(

&proj,

D3DX_PI * 0.5f, // 90 - degree

(float)Width / (float)Height,

1.0f,

1000.0f);

Device->SetTransform(D3DTS_PROJECTION, &proj);

//

// 切换到网格模式。

//

Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); //设置渲染方式

return true;

}

void Cleanup()

{

d3d::Release<IDirect3DVertexBuffer9*>(VB);

d3d::Release<IDirect3DIndexBuffer9*>(IB);

}

void SetMatrixLookAt(D3DXVECTOR3 position,D3DXVECTOR3 target,D3DXVECTOR3 up,D3DXMATRIX V)

{

D3DXMatrixLookAtLH(&V, &position, &target, &up); //摄像机函数

Device->SetTransform(D3DTS_VIEW, &V); //转换为试图

}

bool Display(float timeDelta)

{

if( Device )

{

//

// 旋转立方体:

//

D3DXMATRIX Rx, Ry;

// 定义x轴要旋转的角度

static float x = 0.0f;

D3DXMatrixRotationX(&Rx, x);

x+=timeDelta;

// 重置的角度对零当角度达到 2*PI也就是360°

if(x > 2*D3DX_PI)

{ x = 0.0f; }

// 定义y轴要旋转的角度

static float y = 0.0f;

D3DXMatrixRotationY(&Ry, y);

y += timeDelta;

// 重置的角度对零当角度达到 2*PI也就是360°

if( y >= 2*D3DX_PI )

y = 0.0f;

// 结合x -和y维度旋转变换.

D3DXMATRIX p = Rx * Ry;

Device->SetTransform(D3DTS_WORLD, &p);

//

// 画现场:

//

Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);

Device->BeginScene();

Device->SetStreamSource(0, VB, 0, sizeof(Vertex));

Device->SetIndices(IB);

Device->SetFVF(Vertex::FVF);

// 画立方体.

Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);

Device->EndScene();

Device->Present(0, 0, 0, 0);

}

return true;

}

//

// 消息处理

//

LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

switch( msg )

{

case WM_DESTROY:

::PostQuitMessage(0);

break;

case WM_KEYDOWN:

switch(wParam)

{

case VK_ESCAPE:

::DestroyWindow(hwnd);break;

case VK_UP: //摄像机位置靠近目标

position.z+1<-1?position.z+=1:position.z;

SetMatrixLookAt(position,target,up,V);

break;

case VK_DOWN: //摄像机位置远离目标

position.z-=1;

SetMatrixLookAt(position,target,up,V);

break;

case VK_LEFT:

position.x+=0.1; //摄像机向左移动,同时观察点也相应移动

target.x+=0.1;

SetMatrixLookAt(position,target,up,V);

break;

case VK_RIGHT:

position.x-=0.1; //摄像机向右移动,同时观察点也相应移动

target.x-=0.1;

SetMatrixLookAt(position,target,up,V);

break;

}

}

return ::DefWindowProc(hwnd, msg, wParam, lParam);

}

//

// 入口函数

//

int WINAPI WinMain(HINSTANCE hinstance,

HINSTANCE prevInstance,

PSTR cmdLine,

int showCmd)

{

if(!d3d::InitD3D(hinstance,

Width, Height, true, D3DDEVTYPE_HAL, &Device))

{

::MessageBox(0, "InitD3D() - FAILED", 0, 0);

return 0;

}

if(!Setup())

{

::MessageBox(0, "Setup() - FAILED", 0, 0);

return 0;

}

d3d::EnterMsgLoop( Display );

Cleanup();

Device->Release();

return 0;

}

d3dUtility.cpp文件:

Code:

//////////////////////////////////////////////////////////////////////////////////////////////////

//

// d3dUtility.cpp文件:

//

// 作者:弗兰克露娜(C)保留所有权利

//

// 系统:的AMD Athlon 1800 + XP,512 DDR的Geforce 3日,Windows XP,MSVC + + 7.0

//

// 组:提供效用函数简化大体任务。

//

//////////////////////////////////////////////////////////////////////////////////////////////////

#include "d3dUtility.h"

bool d3d::InitD3D(

HINSTANCE hInstance,

int width, int height,

bool windowed,

D3DDEVTYPE deviceType,

IDirect3DDevice9** device)

{

//

//创造应用的主窗口.

//

WNDCLASS wc;

wc.style = CS_HREDRAW | CS_VREDRAW;

wc.lpfnWndProc = (WNDPROC)d3d::WndProc;

wc.cbClsExtra = 0;

wc.cbWndExtra = 0;

wc.hInstance = hInstance;

wc.hIcon = LoadIcon(0, IDI_APPLICATION);

wc.hCursor = LoadCursor(0, IDC_ARROW);

wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

wc.lpszMenuName = 0;

wc.lpszClassName = "Direct3D9App";

if( !RegisterClass(&wc) )

{

::MessageBox(0, "RegisterClass() - FAILED", 0, 0);

return false;

}

HWND hwnd = 0;

hwnd = ::CreateWindow("Direct3D9App", "Direct3D9App",

WS_EX_TOPMOST,

0, 0, width, height,

0 /*父窗口句柄*/, 0 /* 菜单 */, hInstance, 0 /*扩展*/);

if( !hwnd )

{

::MessageBox(0, "CreateWindow() - FAILED", 0, 0);

return false;

}

::ShowWindow(hwnd, SW_SHOW);

::UpdateWindow(hwnd);

//

// 初始 D3D:

//

HRESULT hr = 0;

// Step 1: 创建 IDirect3D9 对象.

IDirect3D9* d3d9 = 0;

d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

if( !d3d9 )

{

::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);

return false;

}

// Step 2: 检查硬件能否支持硬件顶点处理.

D3DCAPS9 caps;

d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);

int vp = 0;

if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )

vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;

else

vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

// Step 3: 填满 the D3DPRESENT_PARAMETERS 结构体.

D3DPRESENT_PARAMETERS d3dpp;

d3dpp.BackBufferWidth = width;

d3dpp.BackBufferHeight = height;

d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;

d3dpp.BackBufferCount = 1;

d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;

d3dpp.MultiSampleQuality = 0;

d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

d3dpp.hDeviceWindow = hwnd;

d3dpp.Windowed = windowed;

d3dpp.EnableAutoDepthStencil = true;

d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;

d3dpp.Flags = 0;

d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

// Step 4:创建设备.

hr = d3d9->CreateDevice(

D3DADAPTER_DEFAULT, // 主要适配器显卡(省缺值)

deviceType, // 设备类型

hwnd, // 和设备相关的窗口句柄

vp, // 顶点处理类型

&d3dpp, // D3DPRESENT_PARAMETERS参数结构体

device); // 返回已经创建的设备对象

if( FAILED(hr) )

{

// 再试一次使用16位深度缓冲

d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

hr = d3d9->CreateDevice(

D3DADAPTER_DEFAULT,

deviceType,

hwnd,

vp,

&d3dpp,

device);

if( FAILED(hr) )

{

d3d9->Release(); // 释放D3D对象

::MessageBox(0, "CreateDevice() - FAILED", 0, 0);

return false;

}

}

d3d9->Release(); // done with d3d9 object

return true;

}

int d3d::EnterMsgLoop( bool (*ptr_display)(float timeDelta))

{

MSG msg;

::ZeroMemory(&msg, sizeof(MSG));

static float lastTime = (float)timeGetTime(); //得到最近(相对过去)时间

while(msg.message != WM_QUIT)

{

if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))

{

::TranslateMessage(&msg);

::DispatchMessage(&msg);

}

else

{

float currTime = (float)timeGetTime(); //得到当前时间

float timeDelta = (currTime - lastTime)*0.0018; //相当于控制物体的旋转速度0.001~0.002之间为好

ptr_display(timeDelta); //不解释

lastTime = currTime; //将当前时间传给最近(过去)时间

}

}

return msg.wParam;

}

d3dUtility.h文件:

Code:

//////////////////////////////////////////////////////////////////////////////////////////////////

//

// d3dUtility.h文件:

//

// 作者:弗兰克露娜(C)保留所有权利

//

// 系统:的AMD Athlon 1800 + XP,512 DDR的Geforce 3日,Windows XP,MSVC + + 7.0

//

// 组:提供效用函数简化大体任务。

//

//////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __d3dUtilityH__

#define __d3dUtilityH__

#include <d3dx9.h>

#include <string>

namespace d3d

{

bool InitD3D(

HINSTANCE hInstance, // [in]应用实例的.

int width, int height, // [in]后台缓存尺寸.

bool windowed, // [in]窗口或全屏.

D3DDEVTYPE deviceType, // [in] HAL or REF

IDirect3DDevice9** device);// [out]指定创建的设备.

int EnterMsgLoop(

bool (*ptr_display)(float timeDelta));

LRESULT CALLBACK WndProc(

HWND hwnd,

UINT msg,

WPARAM wParam,

LPARAM lParam);

template<class T> void Release(T t)

{

if( t )

{

t->Release();

t = 0;

}

}

template<class T> void Delete(T t)

{

if( t )

{

delete t;

t = 0;

}

}

}

#endif // __d3dUtilityH__
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐