8,305
社区成员
发帖
与我相关
我的任务
分享
#ifndef __VERTEX_H__
#define __VERTEX_H__
struct Vertex
{
public:
Vertex()
{ }
Vertex(float x, float y, float z)
: m_x(x), m_y(y), m_z(z)
{ }
void SetX(float x) { m_x = x ; }
void SetY(float y) { m_y = y ; }
void SetZ(float z) { m_z = z ; }
float GetX() const { return m_x ; }
float GetY() const { return m_y ; }
float GetZ() const { return m_z ; }
public:
static const DWORD FVF;
public:
float m_x;
float m_y;
float m_z;
};
const DWORD Vertex::FVF = D3DFVF_XYZ;
#endif /* __VERTEX_H__ */
#ifndef __DIRECT3DFRAME_H__
#define __DIRECT3DFRAME_H__
#include <d3d9.h>
#include <d3dx9.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "winmm.lib")
// Direct3D 框架类,完成 Direct3D 的初始化等操作
class Direct3DFrame
{
public:
Direct3DFrame(
LPCWSTR wndName,
HINSTANCE hInstance,
int width, int height,
bool windowed,
D3DDEVTYPE deviceType);
~Direct3DFrame(void);
public:
bool InitD3D();
// Setup() 设置资源,Cleanup() 清除资源
bool Setup();
void Cleanup();
bool Display(float timeDelta);
public:
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam);
int EnterMsgLoop();
private:
bool CreateWin32Window(HWND& hWnd);
private:
LPCWSTR m_wndName; // 窗口名称
HINSTANCE m_hInstance; // 应用程序实例句柄
int m_width; // 后台缓冲大小
int m_height;
bool m_windowed; // 窗口模式 (true) 或者全屏模式 (false)
D3DDEVTYPE m_deviceType; // HAL or REF
IDirect3DDevice9* m_device;
IDirect3DVertexBuffer9* m_vb; // 顶点缓存
IDirect3DIndexBuffer9* m_ib; // 索引缓存
float m_yRotAngle; // y 轴每次旋转增量
};
#endif /* __DIRECT3DFRAME_H__ */
//file. winmain.cpp
#include "Direct3DFrame.h"
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE prevInstance,
PSTR cmdLine,
int showCmd)
{
Direct3DFrame d3dFrame(TEXT("Direct3DFrame"), hInstance,
640, 480, true, D3DDEVTYPE_HAL);
if (!d3dFrame.InitD3D()) {
::MessageBox(0, TEXT("InitD3D() - FAILED"), 0, 0);
return 0;
}
if (!d3dFrame.Setup()) {
::MessageBox(0, TEXT("Setup() - FAILED"), 0, 0);
return 0;
}
d3dFrame.EnterMsgLoop();
d3dFrame.Cleanup();
return 0;
}
// file.direct3dframe.cpp
[code=C/C++]
#include "Direct3DFrame.h"
#include "Vertex.h"
Direct3DFrame::Direct3DFrame(
LPCWSTR wndName,
HINSTANCE hInstance,
int width, int height,
bool windowed,
D3DDEVTYPE deviceType)
{
m_wndName = wndName;
m_hInstance = hInstance;
m_width = width;
m_height = height;
m_windowed = windowed;
m_deviceType = deviceType;
this->m_device = NULL;
this->m_vb = NULL;
this->m_ib = NULL;
m_yRotAngle = 0.0f;
}
Direct3DFrame::~Direct3DFrame(void)
{
m_device->Release();
}
bool Direct3DFrame::InitD3D()
{
HWND hWnd;
if (!CreateWin32Window(hWnd)) {
return false;
}
// ---- Init D3D:
HRESULT hr = 0;
// Step 1: Create the IDirect3D9 object.
/* IDirect3D9 用途:
* (1) 设置枚举 ( device enumeration )
* ->指获取系统中可用的每块图形卡的性能、显示模式(display mode)、格式及其他信息
* (2) 创建 IDirect3DDevice9 类型
*/
IDirect3D9* d3d9 = NULL;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d9) {
::MessageBox(0, TEXT("Direct3DCreate9() - FAILED"), 0, 0);
return false;
}
// Step 2: Check for hardare vp.
D3DCAPS9 caps;
d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, m_deviceType, &caps);
int vp = 0;
if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
else {
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
// Step3 : Fill out the D3DPRESENT_PARAMETERS structure.
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = m_width;
d3dpp.BackBufferHeight = m_height;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.Windowed = m_windowed;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
// Step 4: Create the device.
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT, // primary adapter
m_deviceType, // device type
hWnd, // window assocated with device
vp, // vertex processing
&d3dpp, // present parameters
&m_device); // return created device
if (FAILED(hr)) {
// try again using a 16-bit depth buffer
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT,
m_deviceType,
hWnd,
vp,
&d3dpp,
&m_device);
if (FAILED(hr)) {
d3d9->Release();
::MessageBox(0, TEXT("CreateDevice() - FAILED"), 0, 0);
return false;
}
}
d3d9->Release(); // done with d3d9 object
return true;
}
LRESULT CALLBACK Direct3DFrame::WndProc(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
::PostQuitMessage(0);
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
::DestroyWindow(hWnd);
break;
}
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}
bool Direct3DFrame::CreateWin32Window(HWND& hWnd)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = m_hInstance;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = m_wndName;
if (!RegisterClass(&wc)) {
::MessageBox(0, TEXT("RegisterClass() - FAILED"), 0, 0);
return false;
}
hWnd = ::CreateWindow(m_wndName, m_wndName,
WS_OVERLAPPEDWINDOW^WS_MAXIMIZEBOX , 0, 0, m_width, m_height,
0, 0, m_hInstance, 0);
/*hWnd = ::CreateWindow(m_wndName, m_wndName,
WS_EX_TOPMOST, 0, 0, m_width, m_height,
0, 0, m_hInstance, 0);*/
if (!hWnd) {
::MessageBox(0, TEXT("CreateWindow() - FAILED"), 0, 0);
return false;
}
::ShowWindow(hWnd, SW_SHOW);
::UpdateWindow(hWnd);
return true;
}
bool Direct3DFrame::Display(float timeDelta)
{
if (m_device) {
// spin the cube:
D3DXMATRIX rx, ry;
// rotate 45 degrees on x-axis
D3DXMatrixRotationX(&rx, 3.14f / 4.0f);
// increment y-rotation angle each frame
D3DXMatrixRotationY(&ry, m_yRotAngle);
m_yRotAngle += timeDelta;
// reset angle to zero when angle reaches 2*PI
if (m_yRotAngle >= 6.28f) {
m_yRotAngle = 0.0f;
}
D3DXMATRIX p = rx * ry;
m_device->SetTransform(D3DTS_WORLD, &p);
// draw the scene:
m_device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
m_device->BeginScene();
m_device->SetStreamSource(0, m_vb, 0, sizeof(Vertex));
m_device->SetIndices(m_ib);
m_device->SetFVF(Vertex::FVF);
// Draw cube.
m_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
m_device->EndScene();
m_device->Present(0, 0, 0, 0);
}
return true;
}
int Direct3DFrame::EnterMsgLoop()
{
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.001f;
Display(timeDelta);
lastTime = currTime;
}
}
return msg.wParam;
}
bool Direct3DFrame::Setup()
{
// Create vertex and index buffers.
m_device->CreateVertexBuffer (
8 * sizeof(Vertex),
D3DUSAGE_WRITEONLY,
Vertex::FVF,
D3DPOOL_MANAGED,
&m_vb,
0);
m_device->CreateIndexBuffer(
36 * sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&m_ib,
0);
// Fill the buffers with the cube data.
Vertex* vertices;
m_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);
m_vb->Unlock();
// define the triangle of the cube:
WORD* indices = NULL;
m_vb->Lock(0, 0, (void**)&indices, 0);
// front side
indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 0; indices[4] = 2; indices[5] = 3;
// back side
indices[6] = 4; indices[7] = 6; indices[8] = 5;
indices[9] = 4; indices[10] = 7; indices[11] = 6;
// left side
indices[12] = 4; indices[13] = 5; indices[14] = 1;
indices[15] = 4; indices[16] = 1; indices[17] = 0;
// right side
indices[18] = 3; indices[19] = 2; indices[20] = 6;
indices[21] = 3; indices[22] = 6; indices[23] = 7;
// top
indices[24] = 1; indices[25] = 5; indices[26] = 6;
indices[27] = 1; indices[28] = 6; indices[29] = 2;
// bottom
indices[30] = 4; indices[31] = 0; indices[32] = 3;
indices[33] = 4; indices[34] = 3; indices[35] = 7;
m_ib->Unlock();
// Position and aim the camera.
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;
D3DXMatrixLookAtLH(&v, &position, &target, &up);
m_device->SetTransform(D3DTS_VIEW, &v);
// Set the projection matrix.
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(
&proj,
D3DX_PI * 0.5f,
(float)m_width / (float)m_height,
1.0f,
1000.0f);
m_device->SetTransform(D3DTS_PROJECTION, &proj);
// Switch to wireframe mode.
m_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
return true;
}
void Direct3DFrame::Cleanup()
{
m_vb->Release();
m_vb = NULL;
m_ib->Release();
m_ib = NULL;
}