- //
- // 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文件:
- //
- //
- // 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文件:
- //
- //
- // 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__