#include
<
d3dx9.h
>
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib")
D3DXVECTOR3 CubeLookAt[] =
{
D3DXVECTOR3( 0.0f , - 30.0f , - 30.0f ),
D3DXVECTOR3( 0.0f , 0.0f , 0.0f ),
D3DXVECTOR3( 0.0f , 1.0f , 0.0f )
};
LPDIRECT3D9 g_pD3D = NULL; // Direct3D对象
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; // Direct3D设备对象
LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL; // Buffer to hold vertices
PDIRECT3DTEXTURE9 g_pTexture = NULL; // 纹理指针
LPD3DXMESH g_pMesh = NULL; // 网格模型对象
D3DMATERIAL9 * g_pMeshMaterials = NULL; // 网格模型材质
LPDIRECT3DTEXTURE9 * g_pMeshTextures = NULL; // 网格模型纹理
DWORD g_dwNumMaterials = 0L ; // 网格模型材质数量
struct CUSTOMVERTEX // 自定义的顶点格式
{
FLOAT x, y, z; // 顶点坐标
DWORD color; // 顶点颜色
FLOAT tu, tv; // 纹理坐标
};
// Flexible Vertex Format (FVF) 灵活顶点格式
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
// 释放对象
#define SafeRelease(pObject) if(pObject != NULL) {pObject->Release(); pObject=NULL;}
// 释放对象数组
#define SafeDelete(pObjectArray) if(pObjectArray != NULL){delete[] pObjectArray;}
// 键盘控制
#define KeyDown(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KeyUp(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
/* *************************************************************
* Desc: 初始化 Direct3D
************************************************************* */
HRESULT InitialiseD3D(HWND hWnd)
{
// First of all, create the main D3D object. If it is created successfully we
// should get a pointer to an IDirect3D8 interface.
g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (g_pD3D == NULL)
{
return E_FAIL;
}
// Get the current display mode
/* D3DDISPLAYMODE d3ddm;
if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
{
return E_FAIL;
} */
// Create a structure to hold the settings for our device
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( & d3dpp, sizeof (d3dpp));
// Fill the structure.
// We want our program to be windowed, and set the back buffer to a format
// that matches our current display mode
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
// 深度缓冲
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.EnableAutoDepthStencil = TRUE;
// Create a Direct3D device.
if (FAILED(g_pD3D -> CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, & d3dpp,
& g_pD3DDevice)))
{
return E_FAIL;
}
// 开启背面拣选
// g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
// 去除灯光
// g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
// 激活深度缓冲
// g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
// 设置环境灯光
g_pD3DDevice -> SetRenderState(D3DRS_AMBIENT, 0xFFFFFFFF );
return S_OK;
}
/* *************************************************************
* Desc: 初始化顶点缓冲(立方体)
************************************************************* */
HRESULT InitVertexBuffer()
{
VOID * pVertices;
// Store each point of the cube together with it's colour
// Make sure that the points of a polygon are specified in a clockwise direction,
// this is because anti-clockwise faces will be culled
// We will use a three triangle strips to render these polygons
// (Top, Sides, Bottom).
CUSTOMVERTEX cvVertices[] =
{
// Top Face
{ - 5.0f , 5.0f , - 5.0f , D3DCOLOR_XRGB( 0 , 0 , 255 ), 0.0f , 1.0f }, // Vertex 0 - Blue
{ - 5.0f , 5.0f , 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 0.0f , 0.0f }, // Vertex 1 - Red
{ 5.0f , 5.0f , - 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 1.0f , 1.0f }, // Vertex 2 - Red
{ 5.0f , 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 1.0f , 0.0f }, // Vertex 3 - Green
// Face 1
{ - 5.0f , - 5.0f , - 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 0.0f , 1.0f }, // Vertex 4 - Red
{ - 5.0f , 5.0f , - 5.0f , D3DCOLOR_XRGB( 0 , 0 , 255 ), 0.0f , 0.0f }, // Vertex 5 - Blue
{ 5.0f , - 5.0f , - 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 1.0f , 1.0f }, // Vertex 6 - Green
{ 5.0f , 5.0f , - 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 1.0f , 0.0f }, // Vertex 7 - Red
// Face 2
{ 5.0f , - 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 0 , 255 ), 0.0f , 1.0f }, // Vertex 8 - Blue
{ 5.0f , 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 0.0f , 0.0f }, // Vertex 9 - Green
// Face 3
{ - 5.0f , - 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 1.0f , 1.0f }, // Vertex 10 - Green
{ - 5.0f , 5.0f , 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 1.0f , 0.0f }, // Vertex 11 - Red
// Face 4
{ - 5.0f , - 5.0f , - 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 0.0f , 1.0f }, // Vertex 12 - Red
{ - 5.0f , 5.0f , - 5.0f , D3DCOLOR_XRGB( 0 , 0 , 255 ), 0.0f , 0.0f }, // Vertex 13 - Blue
// Bottom Face
{ 5.0f , - 5.0f , - 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 0.0f , 1.0f }, // Vertex 14 - Green
{ 5.0f , - 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 0 , 255 ), 0.0f , 0.0f }, // Vertex 15 - Blue
{ - 5.0f , - 5.0f , - 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 1.0f , 1.0f }, // Vertex 16 - Red
{ - 5.0f , - 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 1.0f , 0.0f }, // Vertex 17 - Green
};
// Create the texture from file
if (FAILED(D3DXCreateTextureFromFile(g_pD3DDevice, " 1.bmp " , & g_pTexture)))
{
return E_FAIL;
}
// Create the vertex buffer from our device.
if (FAILED(g_pD3DDevice -> CreateVertexBuffer( 18 * sizeof (CUSTOMVERTEX),
0 , D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, & g_pVertexBuffer, NULL)))
{
return E_FAIL;
}
// Get a pointer to the vertex buffer vertices and lock the vertex buffer
if (FAILED(g_pVertexBuffer -> Lock( 0 , sizeof (cvVertices), ( void ** ) & pVertices, 0 )))
{
return E_FAIL;
}
// Copy our stored vertices values into the vertex buffer
memcpy(pVertices, cvVertices, sizeof (cvVertices));
// Unlock the vertex buffer
g_pVertexBuffer -> Unlock();
return S_OK;
}
/* *************************************************************
* Desc: 响应键盘事件
************************************************************* */
VOID ProcInput()
{
if (KeyDown(VK_DOWN))
{
CubeLookAt[ 0 ].z -= 0.2f ;
CubeLookAt[ 1 ].z -= 0.2f ;
}
if (KeyDown(VK_UP))
{
CubeLookAt[ 0 ].z += 0.2f ;
CubeLookAt[ 1 ].z += 0.2f ;
}
if (KeyDown(VK_RIGHT))
{
CubeLookAt[ 1 ].x += 0.2f ;
}
if (KeyDown(VK_LEFT))
{
CubeLookAt[ 1 ].x -= 0.2f ;
}
}
/* *************************************************************
* Desc: 初始化网格模型
************************************************************* */
HRESULT InitMesh()
{
LPD3DXBUFFER pMaterialsBuffer;
// 从磁盘文件加载网格模型
if (FAILED(D3DXLoadMeshFromX( " SKULL.x " , D3DXMESH_MANAGED, g_pD3DDevice, NULL,
& pMaterialsBuffer, NULL, & g_dwNumMaterials, & g_pMesh)))
{
MessageBox(NULL, " Could not find corresponding mesh file " , " Mesh " , MB_OK);
return E_FAIL;
}
// 从网格模型中提取材质属性和纹理文件名
D3DXMATERIAL * matMaterials = (D3DXMATERIAL * )pMaterialsBuffer -> GetBufferPointer();
// Create two arrays. One to hold the materials and other to hold the textures
g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials];
g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials];
// 逐块提取网格模型材质属性和纹理文件名
for (DWORD i = 0 ; i < g_dwNumMaterials; i ++ )
{
// 材料属性
g_pMeshMaterials[i] = matMaterials[i].MatD3D;
// 设置模型材料的环境光反射系数,因为模型材料本身没有设置
g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse;
// 创建纹理
if (FAILED(D3DXCreateTextureFromFile(g_pD3DDevice,
matMaterials[i].pTextureFilename,
& g_pMeshTextures[i])))
{
g_pMeshTextures[i] = NULL;
}
}
// We've finished with the material buffer, so release it
SafeRelease(pMaterialsBuffer);
return S_OK;
}
/* *************************************************************
* Desc: 渲染立方体
************************************************************* */
void RenderCube()
{
ProcInput();
/* ***************************
* Desc: 创建并设置世界矩阵 *
*************************** */
D3DXMATRIX matWorld, matWorldX, matWorldY, matWorldZ;
// Create the transformation matrices
D3DXMatrixRotationX( & matWorldX, timeGetTime() / 400.0f );
D3DXMatrixRotationY( & matWorldY, timeGetTime() / 400.0f );
D3DXMatrixRotationZ( & matWorldZ, timeGetTime() / 400.0f );
/* 我们调用了D3DXMatrixRotationX、D3DXMatrixRotationY和D3DXMatrixRotationZ
函数产生了3个矩阵而且分别将它们保存在了3个D3DXMATRIX结构中
然后我们将它们相乘后形成了世界矩阵 */
D3DXMatrixMultiply( & matWorld, & matWorldX, & matWorldY);
D3DXMatrixMultiply( & matWorld, & matWorld, & matWorldZ);
// 我们又调用了SetTransform函数为我们的顶点应用了此变换
g_pD3DDevice -> SetTransform(D3DTS_WORLD, & matWorld);
/* ***************************
* Desc: 创建并设置观察矩阵 *
*************************** */
D3DXMATRIX matView;
D3DXMatrixLookAtLH( & matView, & CubeLookAt[ 0 ], // Camera Position
& CubeLookAt[ 1 ], // Look At Position
& CubeLookAt[ 2 ]); // Up Direction
g_pD3DDevice -> SetTransform(D3DTS_VIEW, & matView);
/* ***************************
* Desc: 创建并设置投影矩阵 *
*************************** */
D3DXMATRIX matProj;
/* 我们设置摄像机的镜头:我们确定了视界为PI/4(正常)而横纵比为1
我们还确定了前、后裁剪平面分别为1和500,这意味着范围之外的三角形将会被裁剪掉 */
D3DXMatrixPerspectiveFovLH( & matProj, D3DX_PI / 4 , 1.0f , 1.0f , 500.0f );
g_pD3DDevice -> SetTransform(D3DTS_PROJECTION, & matProj);
// Set how the texture should be rendered.
if (g_pTexture != NULL)
{
// A texture has been set. We don't want to blend our texture with
// the colours of our vertices, so use D3DTOP_SELECTARG1
g_pD3DDevice -> SetTexture( 0 , g_pTexture);
g_pD3DDevice -> SetTextureStageState( 0 , D3DTSS_COLOROP, D3DTOP_SELECTARG1);
}
else
{
// No texture has been set. So we will disable texture rendering.
g_pD3DDevice -> SetTextureStageState( 0 , D3DTSS_COLOROP, D3DTOP_DISABLE);
}
// Rendering our objects
g_pD3DDevice -> SetStreamSource( 0 , g_pVertexBuffer, 0 , sizeof (CUSTOMVERTEX));
g_pD3DDevice -> SetFVF(D3DFVF_CUSTOMVERTEX);
g_pD3DDevice -> DrawPrimitive(D3DPT_TRIANGLESTRIP, 0 , 2 ); // Top
g_pD3DDevice -> DrawPrimitive(D3DPT_TRIANGLESTRIP, 4 , 8 ); // Sides
g_pD3DDevice -> DrawPrimitive(D3DPT_TRIANGLESTRIP, 14 , 2 ); // Bottom
}
/* *************************************************************
* Desc: 渲染网格模型
************************************************************* */
DWORD RenderMesh()
{
// 创建并设置世界坐标系
D3DXMATRIX matWorld;
D3DXMatrixRotationY( & matWorld, timeGetTime() / 1000.0f );
g_pD3DDevice -> SetTransform(D3DTS_WORLD, & matWorld);
// 创建并设置观察矩阵
D3DXMATRIX matView;
D3DXMatrixLookAtLH( & matView, & D3DXVECTOR3( 0.0f , 0.0f , - 20.0f ),
& D3DXVECTOR3( 0.0f , 0.0f , 0.0f ),
& D3DXVECTOR3( 0.0f , 1.0f , 0.0f ));
g_pD3DDevice -> SetTransform(D3DTS_VIEW, & matView);
// 创建并设置投影矩阵
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( & matProj, D3DX_PI / 4 , 1.0f , 1.0f , 100.0f );
g_pD3DDevice -> SetTransform(D3DTS_PROJECTION, & matProj);
// 逐块渲染网格模型
if (g_pMesh != NULL)
{
for (DWORD i = 0 ; i < g_dwNumMaterials; i ++ )
{
g_pD3DDevice -> SetMaterial( & g_pMeshMaterials[i]);
g_pD3DDevice -> SetTexture( 0 , g_pMeshTextures[i]);
g_pMesh -> DrawSubset(i);
}
return g_pMesh -> GetNumFaces();
}
else
{
MessageBox(NULL, " Could not open mesh file " , " Mesh " , MB_OK);
return 0 ;
}
}
/* *************************************************************
* Desc: 渲染主场景
************************************************************* */
void Render()
{
if (g_pD3DDevice == NULL)
{
return ;
}
// 清空深度缓冲
g_pD3DDevice -> Clear( 0 , NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0 , 0 , 0 ), 1.0f , 0 );
// Begin the scene
g_pD3DDevice -> BeginScene();
// RenderCube();
RenderMesh();
// End the scene
g_pD3DDevice -> EndScene();
// Filp the back and front buffers so that whatever has been rendered on the
// back buffer will now be visible on screen (front buffer).
g_pD3DDevice -> Present(NULL, NULL, NULL, NULL);
}
/* *************************************************************
* Desc: 释放对象
************************************************************* */
void CleanUp()
{
SafeDelete(g_pMeshMaterials);
if (g_pMeshTextures != NULL)
{
for (DWORD i = 0 ; i < g_dwNumMaterials; i ++ )
{
if (g_pMeshTextures[i])
{
SafeRelease(g_pMeshTextures[i]);
}
}
}
SafeDelete(g_pMeshTextures);
SafeRelease(g_pMesh);
SafeRelease(g_pTexture);
SafeRelease(g_pVertexBuffer);
SafeRelease(g_pD3DDevice);
SafeRelease(g_pD3D);
}
/* *************************************************************
* Desc: 游戏循环
************************************************************* */
void GameLoop()
{
// Enter the game loop
MSG msg;
BOOL fMessage;
PeekMessage( & msg, NULL, 0U , 0U , PM_NOREMOVE);
while (msg.message != WM_QUIT)
{
fMessage = PeekMessage( & msg, NULL, 0U , 0U , PM_REMOVE);
if (fMessage)
{
// Process message
TranslateMessage( & msg); // 将虚拟键消息转换为字符消息
DispatchMessage( & msg); // 将转换后的消息传送给windows
}
else
{
// No message to process, so render the current scene
Render();
}
}
}
/* *************************************************************
* Desc: 消息处理函数
************************************************************* */
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0 ;
break ;
case WM_KEYUP:
switch (wParam)
{
case VK_ESCAPE:
// User has pressed the escape key, so quit
DestroyWindow(hWnd);
return 0 ;
break ;
}
break ;
}
return DefWindowProc(hWnd, msg, wParam, lParam); // 调用默认消息处理过程
}
/* *************************************************************
* Desc: WIN32入口函数
************************************************************* */
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
// Register the window class
/* WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"DX Project 3", NULL}; */
WNDCLASSEX wc;
// 指定了结构的大小
wc.cbSize = sizeof (WNDCLASSEX);
wc.style = CS_CLASSDC;
// 指定窗口类别的消息处理函数
wc.lpfnWndProc = WinProc;
// 指定窗口结构的额外空间
wc.cbClsExtra = 0L ;
wc.cbWndExtra = 0L ;
// 代表程序的实例句柄
wc.hInstance = GetModuleHandle(NULL);
// 图标
wc.hIcon = LoadIcon(NULL,MAKEINTRESOURCE(IDI_ERROR));
// 鼠标指针
wc.hCursor = LoadCursor(NULL,MAKEINTRESOURCE(IDC_CROSS));
// 背景
wc.hbrBackground = NULL;
// 菜单
wc.lpszMenuName = NULL;
// 窗口类的名称
wc.lpszClassName = " DX Project 3 " ;
// 包含了窗口类的小图标句柄
wc.hIconSm = NULL;
RegisterClassEx( & wc);
// 全屏模式
/* HWND hWnd = CreateWindow("DX Project 3", "3D游戏",
WS_POPUP, 0, 0,
GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
GetDesktopWindow(), NULL, wc.hInstance, NULL); */
// 窗口模式
HWND hWnd = CreateWindow( " DX Project 3 " , " 3D游戏 " ,
WS_OVERLAPPEDWINDOW & ~ WS_MAXIMIZEBOX & ~ WS_MINIMIZEBOX,
50 , 50 , 500 , 500 ,
GetDesktopWindow(), NULL, wc.hInstance, NULL);
// Initialize Direct3D
if (SUCCEEDED(InitialiseD3D(hWnd)))
{
// Show our window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
// Initialize Vertex Buffer
if (SUCCEEDED( /* InitVertexBuffer() */ InitMesh()))
{
// Start game running: Enter the game loop
GameLoop();
}
}
CleanUp();
UnregisterClass( " DX Project 3 " , wc.hInstance);
return 0 ;
}
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib")
D3DXVECTOR3 CubeLookAt[] =
{
D3DXVECTOR3( 0.0f , - 30.0f , - 30.0f ),
D3DXVECTOR3( 0.0f , 0.0f , 0.0f ),
D3DXVECTOR3( 0.0f , 1.0f , 0.0f )
};
LPDIRECT3D9 g_pD3D = NULL; // Direct3D对象
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; // Direct3D设备对象
LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL; // Buffer to hold vertices
PDIRECT3DTEXTURE9 g_pTexture = NULL; // 纹理指针
LPD3DXMESH g_pMesh = NULL; // 网格模型对象
D3DMATERIAL9 * g_pMeshMaterials = NULL; // 网格模型材质
LPDIRECT3DTEXTURE9 * g_pMeshTextures = NULL; // 网格模型纹理
DWORD g_dwNumMaterials = 0L ; // 网格模型材质数量
struct CUSTOMVERTEX // 自定义的顶点格式
{
FLOAT x, y, z; // 顶点坐标
DWORD color; // 顶点颜色
FLOAT tu, tv; // 纹理坐标
};
// Flexible Vertex Format (FVF) 灵活顶点格式
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
// 释放对象
#define SafeRelease(pObject) if(pObject != NULL) {pObject->Release(); pObject=NULL;}
// 释放对象数组
#define SafeDelete(pObjectArray) if(pObjectArray != NULL){delete[] pObjectArray;}
// 键盘控制
#define KeyDown(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KeyUp(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
/* *************************************************************
* Desc: 初始化 Direct3D
************************************************************* */
HRESULT InitialiseD3D(HWND hWnd)
{
// First of all, create the main D3D object. If it is created successfully we
// should get a pointer to an IDirect3D8 interface.
g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (g_pD3D == NULL)
{
return E_FAIL;
}
// Get the current display mode
/* D3DDISPLAYMODE d3ddm;
if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
{
return E_FAIL;
} */
// Create a structure to hold the settings for our device
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( & d3dpp, sizeof (d3dpp));
// Fill the structure.
// We want our program to be windowed, and set the back buffer to a format
// that matches our current display mode
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
// 深度缓冲
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.EnableAutoDepthStencil = TRUE;
// Create a Direct3D device.
if (FAILED(g_pD3D -> CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, & d3dpp,
& g_pD3DDevice)))
{
return E_FAIL;
}
// 开启背面拣选
// g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
// 去除灯光
// g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
// 激活深度缓冲
// g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
// 设置环境灯光
g_pD3DDevice -> SetRenderState(D3DRS_AMBIENT, 0xFFFFFFFF );
return S_OK;
}
/* *************************************************************
* Desc: 初始化顶点缓冲(立方体)
************************************************************* */
HRESULT InitVertexBuffer()
{
VOID * pVertices;
// Store each point of the cube together with it's colour
// Make sure that the points of a polygon are specified in a clockwise direction,
// this is because anti-clockwise faces will be culled
// We will use a three triangle strips to render these polygons
// (Top, Sides, Bottom).
CUSTOMVERTEX cvVertices[] =
{
// Top Face
{ - 5.0f , 5.0f , - 5.0f , D3DCOLOR_XRGB( 0 , 0 , 255 ), 0.0f , 1.0f }, // Vertex 0 - Blue
{ - 5.0f , 5.0f , 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 0.0f , 0.0f }, // Vertex 1 - Red
{ 5.0f , 5.0f , - 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 1.0f , 1.0f }, // Vertex 2 - Red
{ 5.0f , 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 1.0f , 0.0f }, // Vertex 3 - Green
// Face 1
{ - 5.0f , - 5.0f , - 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 0.0f , 1.0f }, // Vertex 4 - Red
{ - 5.0f , 5.0f , - 5.0f , D3DCOLOR_XRGB( 0 , 0 , 255 ), 0.0f , 0.0f }, // Vertex 5 - Blue
{ 5.0f , - 5.0f , - 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 1.0f , 1.0f }, // Vertex 6 - Green
{ 5.0f , 5.0f , - 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 1.0f , 0.0f }, // Vertex 7 - Red
// Face 2
{ 5.0f , - 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 0 , 255 ), 0.0f , 1.0f }, // Vertex 8 - Blue
{ 5.0f , 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 0.0f , 0.0f }, // Vertex 9 - Green
// Face 3
{ - 5.0f , - 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 1.0f , 1.0f }, // Vertex 10 - Green
{ - 5.0f , 5.0f , 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 1.0f , 0.0f }, // Vertex 11 - Red
// Face 4
{ - 5.0f , - 5.0f , - 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 0.0f , 1.0f }, // Vertex 12 - Red
{ - 5.0f , 5.0f , - 5.0f , D3DCOLOR_XRGB( 0 , 0 , 255 ), 0.0f , 0.0f }, // Vertex 13 - Blue
// Bottom Face
{ 5.0f , - 5.0f , - 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 0.0f , 1.0f }, // Vertex 14 - Green
{ 5.0f , - 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 0 , 255 ), 0.0f , 0.0f }, // Vertex 15 - Blue
{ - 5.0f , - 5.0f , - 5.0f , D3DCOLOR_XRGB( 255 , 0 , 0 ), 1.0f , 1.0f }, // Vertex 16 - Red
{ - 5.0f , - 5.0f , 5.0f , D3DCOLOR_XRGB( 0 , 255 , 0 ), 1.0f , 0.0f }, // Vertex 17 - Green
};
// Create the texture from file
if (FAILED(D3DXCreateTextureFromFile(g_pD3DDevice, " 1.bmp " , & g_pTexture)))
{
return E_FAIL;
}
// Create the vertex buffer from our device.
if (FAILED(g_pD3DDevice -> CreateVertexBuffer( 18 * sizeof (CUSTOMVERTEX),
0 , D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, & g_pVertexBuffer, NULL)))
{
return E_FAIL;
}
// Get a pointer to the vertex buffer vertices and lock the vertex buffer
if (FAILED(g_pVertexBuffer -> Lock( 0 , sizeof (cvVertices), ( void ** ) & pVertices, 0 )))
{
return E_FAIL;
}
// Copy our stored vertices values into the vertex buffer
memcpy(pVertices, cvVertices, sizeof (cvVertices));
// Unlock the vertex buffer
g_pVertexBuffer -> Unlock();
return S_OK;
}
/* *************************************************************
* Desc: 响应键盘事件
************************************************************* */
VOID ProcInput()
{
if (KeyDown(VK_DOWN))
{
CubeLookAt[ 0 ].z -= 0.2f ;
CubeLookAt[ 1 ].z -= 0.2f ;
}
if (KeyDown(VK_UP))
{
CubeLookAt[ 0 ].z += 0.2f ;
CubeLookAt[ 1 ].z += 0.2f ;
}
if (KeyDown(VK_RIGHT))
{
CubeLookAt[ 1 ].x += 0.2f ;
}
if (KeyDown(VK_LEFT))
{
CubeLookAt[ 1 ].x -= 0.2f ;
}
}
/* *************************************************************
* Desc: 初始化网格模型
************************************************************* */
HRESULT InitMesh()
{
LPD3DXBUFFER pMaterialsBuffer;
// 从磁盘文件加载网格模型
if (FAILED(D3DXLoadMeshFromX( " SKULL.x " , D3DXMESH_MANAGED, g_pD3DDevice, NULL,
& pMaterialsBuffer, NULL, & g_dwNumMaterials, & g_pMesh)))
{
MessageBox(NULL, " Could not find corresponding mesh file " , " Mesh " , MB_OK);
return E_FAIL;
}
// 从网格模型中提取材质属性和纹理文件名
D3DXMATERIAL * matMaterials = (D3DXMATERIAL * )pMaterialsBuffer -> GetBufferPointer();
// Create two arrays. One to hold the materials and other to hold the textures
g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials];
g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials];
// 逐块提取网格模型材质属性和纹理文件名
for (DWORD i = 0 ; i < g_dwNumMaterials; i ++ )
{
// 材料属性
g_pMeshMaterials[i] = matMaterials[i].MatD3D;
// 设置模型材料的环境光反射系数,因为模型材料本身没有设置
g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse;
// 创建纹理
if (FAILED(D3DXCreateTextureFromFile(g_pD3DDevice,
matMaterials[i].pTextureFilename,
& g_pMeshTextures[i])))
{
g_pMeshTextures[i] = NULL;
}
}
// We've finished with the material buffer, so release it
SafeRelease(pMaterialsBuffer);
return S_OK;
}
/* *************************************************************
* Desc: 渲染立方体
************************************************************* */
void RenderCube()
{
ProcInput();
/* ***************************
* Desc: 创建并设置世界矩阵 *
*************************** */
D3DXMATRIX matWorld, matWorldX, matWorldY, matWorldZ;
// Create the transformation matrices
D3DXMatrixRotationX( & matWorldX, timeGetTime() / 400.0f );
D3DXMatrixRotationY( & matWorldY, timeGetTime() / 400.0f );
D3DXMatrixRotationZ( & matWorldZ, timeGetTime() / 400.0f );
/* 我们调用了D3DXMatrixRotationX、D3DXMatrixRotationY和D3DXMatrixRotationZ
函数产生了3个矩阵而且分别将它们保存在了3个D3DXMATRIX结构中
然后我们将它们相乘后形成了世界矩阵 */
D3DXMatrixMultiply( & matWorld, & matWorldX, & matWorldY);
D3DXMatrixMultiply( & matWorld, & matWorld, & matWorldZ);
// 我们又调用了SetTransform函数为我们的顶点应用了此变换
g_pD3DDevice -> SetTransform(D3DTS_WORLD, & matWorld);
/* ***************************
* Desc: 创建并设置观察矩阵 *
*************************** */
D3DXMATRIX matView;
D3DXMatrixLookAtLH( & matView, & CubeLookAt[ 0 ], // Camera Position
& CubeLookAt[ 1 ], // Look At Position
& CubeLookAt[ 2 ]); // Up Direction
g_pD3DDevice -> SetTransform(D3DTS_VIEW, & matView);
/* ***************************
* Desc: 创建并设置投影矩阵 *
*************************** */
D3DXMATRIX matProj;
/* 我们设置摄像机的镜头:我们确定了视界为PI/4(正常)而横纵比为1
我们还确定了前、后裁剪平面分别为1和500,这意味着范围之外的三角形将会被裁剪掉 */
D3DXMatrixPerspectiveFovLH( & matProj, D3DX_PI / 4 , 1.0f , 1.0f , 500.0f );
g_pD3DDevice -> SetTransform(D3DTS_PROJECTION, & matProj);
// Set how the texture should be rendered.
if (g_pTexture != NULL)
{
// A texture has been set. We don't want to blend our texture with
// the colours of our vertices, so use D3DTOP_SELECTARG1
g_pD3DDevice -> SetTexture( 0 , g_pTexture);
g_pD3DDevice -> SetTextureStageState( 0 , D3DTSS_COLOROP, D3DTOP_SELECTARG1);
}
else
{
// No texture has been set. So we will disable texture rendering.
g_pD3DDevice -> SetTextureStageState( 0 , D3DTSS_COLOROP, D3DTOP_DISABLE);
}
// Rendering our objects
g_pD3DDevice -> SetStreamSource( 0 , g_pVertexBuffer, 0 , sizeof (CUSTOMVERTEX));
g_pD3DDevice -> SetFVF(D3DFVF_CUSTOMVERTEX);
g_pD3DDevice -> DrawPrimitive(D3DPT_TRIANGLESTRIP, 0 , 2 ); // Top
g_pD3DDevice -> DrawPrimitive(D3DPT_TRIANGLESTRIP, 4 , 8 ); // Sides
g_pD3DDevice -> DrawPrimitive(D3DPT_TRIANGLESTRIP, 14 , 2 ); // Bottom
}
/* *************************************************************
* Desc: 渲染网格模型
************************************************************* */
DWORD RenderMesh()
{
// 创建并设置世界坐标系
D3DXMATRIX matWorld;
D3DXMatrixRotationY( & matWorld, timeGetTime() / 1000.0f );
g_pD3DDevice -> SetTransform(D3DTS_WORLD, & matWorld);
// 创建并设置观察矩阵
D3DXMATRIX matView;
D3DXMatrixLookAtLH( & matView, & D3DXVECTOR3( 0.0f , 0.0f , - 20.0f ),
& D3DXVECTOR3( 0.0f , 0.0f , 0.0f ),
& D3DXVECTOR3( 0.0f , 1.0f , 0.0f ));
g_pD3DDevice -> SetTransform(D3DTS_VIEW, & matView);
// 创建并设置投影矩阵
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( & matProj, D3DX_PI / 4 , 1.0f , 1.0f , 100.0f );
g_pD3DDevice -> SetTransform(D3DTS_PROJECTION, & matProj);
// 逐块渲染网格模型
if (g_pMesh != NULL)
{
for (DWORD i = 0 ; i < g_dwNumMaterials; i ++ )
{
g_pD3DDevice -> SetMaterial( & g_pMeshMaterials[i]);
g_pD3DDevice -> SetTexture( 0 , g_pMeshTextures[i]);
g_pMesh -> DrawSubset(i);
}
return g_pMesh -> GetNumFaces();
}
else
{
MessageBox(NULL, " Could not open mesh file " , " Mesh " , MB_OK);
return 0 ;
}
}
/* *************************************************************
* Desc: 渲染主场景
************************************************************* */
void Render()
{
if (g_pD3DDevice == NULL)
{
return ;
}
// 清空深度缓冲
g_pD3DDevice -> Clear( 0 , NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0 , 0 , 0 ), 1.0f , 0 );
// Begin the scene
g_pD3DDevice -> BeginScene();
// RenderCube();
RenderMesh();
// End the scene
g_pD3DDevice -> EndScene();
// Filp the back and front buffers so that whatever has been rendered on the
// back buffer will now be visible on screen (front buffer).
g_pD3DDevice -> Present(NULL, NULL, NULL, NULL);
}
/* *************************************************************
* Desc: 释放对象
************************************************************* */
void CleanUp()
{
SafeDelete(g_pMeshMaterials);
if (g_pMeshTextures != NULL)
{
for (DWORD i = 0 ; i < g_dwNumMaterials; i ++ )
{
if (g_pMeshTextures[i])
{
SafeRelease(g_pMeshTextures[i]);
}
}
}
SafeDelete(g_pMeshTextures);
SafeRelease(g_pMesh);
SafeRelease(g_pTexture);
SafeRelease(g_pVertexBuffer);
SafeRelease(g_pD3DDevice);
SafeRelease(g_pD3D);
}
/* *************************************************************
* Desc: 游戏循环
************************************************************* */
void GameLoop()
{
// Enter the game loop
MSG msg;
BOOL fMessage;
PeekMessage( & msg, NULL, 0U , 0U , PM_NOREMOVE);
while (msg.message != WM_QUIT)
{
fMessage = PeekMessage( & msg, NULL, 0U , 0U , PM_REMOVE);
if (fMessage)
{
// Process message
TranslateMessage( & msg); // 将虚拟键消息转换为字符消息
DispatchMessage( & msg); // 将转换后的消息传送给windows
}
else
{
// No message to process, so render the current scene
Render();
}
}
}
/* *************************************************************
* Desc: 消息处理函数
************************************************************* */
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0 ;
break ;
case WM_KEYUP:
switch (wParam)
{
case VK_ESCAPE:
// User has pressed the escape key, so quit
DestroyWindow(hWnd);
return 0 ;
break ;
}
break ;
}
return DefWindowProc(hWnd, msg, wParam, lParam); // 调用默认消息处理过程
}
/* *************************************************************
* Desc: WIN32入口函数
************************************************************* */
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
// Register the window class
/* WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"DX Project 3", NULL}; */
WNDCLASSEX wc;
// 指定了结构的大小
wc.cbSize = sizeof (WNDCLASSEX);
wc.style = CS_CLASSDC;
// 指定窗口类别的消息处理函数
wc.lpfnWndProc = WinProc;
// 指定窗口结构的额外空间
wc.cbClsExtra = 0L ;
wc.cbWndExtra = 0L ;
// 代表程序的实例句柄
wc.hInstance = GetModuleHandle(NULL);
// 图标
wc.hIcon = LoadIcon(NULL,MAKEINTRESOURCE(IDI_ERROR));
// 鼠标指针
wc.hCursor = LoadCursor(NULL,MAKEINTRESOURCE(IDC_CROSS));
// 背景
wc.hbrBackground = NULL;
// 菜单
wc.lpszMenuName = NULL;
// 窗口类的名称
wc.lpszClassName = " DX Project 3 " ;
// 包含了窗口类的小图标句柄
wc.hIconSm = NULL;
RegisterClassEx( & wc);
// 全屏模式
/* HWND hWnd = CreateWindow("DX Project 3", "3D游戏",
WS_POPUP, 0, 0,
GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
GetDesktopWindow(), NULL, wc.hInstance, NULL); */
// 窗口模式
HWND hWnd = CreateWindow( " DX Project 3 " , " 3D游戏 " ,
WS_OVERLAPPEDWINDOW & ~ WS_MAXIMIZEBOX & ~ WS_MINIMIZEBOX,
50 , 50 , 500 , 500 ,
GetDesktopWindow(), NULL, wc.hInstance, NULL);
// Initialize Direct3D
if (SUCCEEDED(InitialiseD3D(hWnd)))
{
// Show our window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
// Initialize Vertex Buffer
if (SUCCEEDED( /* InitVertexBuffer() */ InitMesh()))
{
// Start game running: Enter the game loop
GameLoop();
}
}
CleanUp();
UnregisterClass( " DX Project 3 " , wc.hInstance);
return 0 ;
}