📄 x3d.cpp
字号:
// x3d.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "x3d.h"
#include <windowsx.h>
#include <stdio.h>
#include <d3d9.h>
#pragma comment(lib, "d3d9.lib")
#include <d3dx9math.h>
#include "Camera.h"
#include "Light.h"
#include "Terrain.h"
#define MAX_LOADSTRING 100
#define EYESHOT 50
#define TERRAIN_SIZE 128
// 全局变量:
HINSTANCE hInst; // 当前实例
HWND hWndMain;
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
// D3D相关变量
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pDevice = NULL;
D3DCAPS9 g_pDeviceCaps;
CTerrain g_Terrain;
CCamera g_Camera;
CLight g_Light;
// 其他
BOOL g_bOnRButton;
BOOL g_bOnLButton;
WORD g_wRelaX;
WORD g_wRelaY;
int g_fmIndex = 0;
BOOL g_bLight = FALSE;
BOOL g_bActive = TRUE;
BOOL g_bUpdateDetail = TRUE;
DWORD g_dwFillMode[] = {
D3DFILL_POINT,
D3DFILL_WIREFRAME,
D3DFILL_SOLID,
};
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK Setup(HWND, UINT, WPARAM, LPARAM);
// D3D相关函数
HRESULT InitD3D(void);
void TermD3D(void);
void SetupObjects(void);
void UpdateFrame(void);
void Render(void);
void SetupMatrices(void);
// 消息相关
void OnCommand(HWND hWnd, unsigned short uID, unsigned short uEvent);
void OnKeyDown(HWND hWnd, DWORD dwKeyCode);
void OnKeyUp(HWND hWnd, DWORD dwKeyCode);
void OnLButtonDown(HWND hWnd, int x, int y);
void OnLButtonUp(HWND hWnd, int x, int y);
void OnRButtonDown(HWND hWnd, int x, int y);
void OnRButtonUp(HWND hWnd, int x, int y);
void OnMButtonDown(HWND hWnd, int x, int y);
void OnMButtonUp(HWND hWnd, int x, int y);
void OnMouseMove(HWND hWnd, int x, int y);
void OnMouseWheel(HWND hWnd, short zDelta);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;
// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_X3D, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_X3D);
// 执行d3d初始化
if(FAILED(InitD3D()))return FALSE;
// 设置场景对象
SetupObjects();
// 主消息循环:
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else if(g_bActive)
{
UpdateFrame();
Render();
}
}
TermD3D();
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
// 注释:
//
// 仅当希望在已添加到 Windows 95 的
// “RegisterClassEx”函数之前此代码与 Win32 系统兼容时,
// 才需要此函数及其用法。调用此函数
// 十分重要,这样应用程序就可以获得关联的
// “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_X3D);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCTSTR)IDC_X3D;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// 函数: InitInstance(HANDLE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中
hWndMain = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 500, 400, NULL, NULL, hInstance, NULL);
if (!hWndMain)
{
return FALSE;
}
ShowWindow(hWndMain, nCmdShow);
UpdateWindow(hWndMain);
return TRUE;
}
//
// 函数: WndProc(HWND, unsigned, WORD, LONG)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_ACTIVATEAPP:
g_bActive = (BOOL)wParam;
break;
case WM_COMMAND:
OnCommand(hWnd, LOWORD(wParam), HIWORD(wParam));
break;
case WM_KEYDOWN:
OnKeyDown(hWnd, (DWORD)wParam);
break;
case WM_KEYUP:
OnKeyUp(hWnd, (DWORD)wParam);
break;
case WM_LBUTTONDOWN:
OnLButtonDown(hWnd, LOWORD(lParam), HIWORD(lParam));
break;
case WM_LBUTTONUP:
OnLButtonUp(hWnd, LOWORD(lParam), HIWORD(lParam));
break;
case WM_RBUTTONDOWN:
OnRButtonDown(hWnd, LOWORD(lParam), HIWORD(lParam));
break;
case WM_RBUTTONUP:
OnRButtonUp(hWnd, LOWORD(lParam), HIWORD(lParam));
break;
case WM_MOUSEMOVE:
OnMouseMove(hWnd, LOWORD(lParam), HIWORD(lParam));
break;
case WM_MOUSEWHEEL:
OnMouseWheel(hWnd, GET_WHEEL_DELTA_WPARAM(wParam));
break;
case WM_ERASEBKGND:
return TRUE;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
// “关于”框的消息处理程序。
LRESULT CALLBACK Setup(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return FALSE;
case WM_COMMAND:
switch(wParam)
{
case IDOK:
{
char szText[100];
Edit_GetText(GetDlgItem(hDlg, IDC_TRIANGLE_COUNT), szText, 100);
int iCount = atoi(szText);
EndDialog(hDlg, LOWORD(wParam));
}
return TRUE;
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
}
return FALSE;
}
HRESULT InitD3D()
{
if(NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
return E_FAIL;
D3DDISPLAYMODE dp;
if(FAILED(g_pD3D->GetAdapterDisplayMode(0, &dp)))
return E_FAIL;
D3DPRESENT_PARAMETERS pp;
ZeroMemory(&pp, sizeof(pp));
pp.BackBufferFormat = dp.Format;
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
pp.hDeviceWindow = hWndMain;
pp.Windowed = TRUE;
pp.EnableAutoDepthStencil = TRUE;
pp.AutoDepthStencilFormat = D3DFMT_D16;
if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWndMain,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&pp,
&g_pDevice)))
{
return E_FAIL;
}
// 区的设备属性
if(FAILED(g_pDevice->GetDeviceCaps(&g_pDeviceCaps)))
return E_FAIL;
// 变换矩阵
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, 4.0f/3.0f, 1.0f, 1000.f);
g_pDevice->SetTransform(D3DTS_PROJECTION, &matProj);
// 渲染状态
g_pDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
g_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
g_pDevice->SetRenderState(D3DRS_LIGHTING, g_bLight);
g_pDevice->LightEnable(0, TRUE);
return S_OK;
}
void TermD3D()
{
if(g_pD3D)
{
g_pD3D->Release();
g_pD3D = NULL;
}
if(g_pDevice)
{
g_pDevice->Release();
g_pDevice = NULL;
}
}
void UpdateFrame()
{
if(g_bUpdateDetail)
{
g_Terrain.UpdateDetail(&g_Camera, EYESHOT);
g_bUpdateDetail = FALSE;
}
}
void Render()
{
g_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0);
if(SUCCEEDED(g_pDevice->BeginScene()))
{
g_pDevice->SetLight(0, g_Light);
g_pDevice->SetTransform(D3DTS_WORLD, g_Terrain.GetMatrix());
g_Terrain.Render();
g_pDevice->EndScene();
}
g_pDevice->Present(NULL, NULL, NULL, NULL);
}
void SetupObjects()
{
srand(GetTickCount());
// 地形
g_Terrain.SetDevice(g_pDevice);
g_Terrain.SetDeviceCaps(&g_pDeviceCaps);
D3DXMatrixTranslation(g_Terrain.GetMatrix(), 0, 0, 0);
g_Terrain.Create(TERRAIN_SIZE);
g_Terrain.RandomHeight(0.75f, 0.15f, 2);
// 摄像机
g_Camera.SetDevice(g_pDevice);
g_Camera.SetPosition(&D3DXVECTOR3(TERRAIN_SIZE / 2.0f, g_Terrain.GetMaxHeight(), TERRAIN_SIZE / 2.0f));
g_Camera.SetTarget(&D3DXVECTOR3(0.0f, 0.f, 0.0f));
g_Light.SetPosition(g_Camera.GetPosition());
g_Light.SetDirection(&g_Camera.GetDirection());
}
void OnCommand(HWND hWnd, unsigned short uID, unsigned short uEvent)
{
// 分析菜单选择:
switch (uID)
{
case ID_SETUP:
DialogBox(hInst, (LPCTSTR)IDD_SETUP, hWnd, (DLGPROC)Setup);
break;
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
}
}
void OnKeyDown(HWND hWnd, DWORD dwKeyCode)
{
switch(dwKeyCode)
{
case VK_LEFT:
g_Camera.Move(-10.0f, 0.0f);
break;
case VK_RIGHT:
g_Camera.Move(10.0f, 0.0f);
break;
case VK_UP:
g_Camera.Move(0.0f, 10.0f);
break;
case VK_DOWN:
g_Camera.Move(0.0f, -10.0f);
break;
}
}
void OnKeyUp(HWND hWnd, DWORD dwKeyCode)
{
switch(dwKeyCode)
{
case 'F':
{
g_Terrain.SetFillMode(g_dwFillMode[g_fmIndex]);
if(g_fmIndex < sizeof(g_dwFillMode) / sizeof(DWORD) - 1)
g_fmIndex++;
else
g_fmIndex = 0;
}
break;
case 'L':
{
g_bLight = !g_bLight;
g_pDevice->SetRenderState(D3DRS_LIGHTING, g_bLight);
if(g_bLight)
{
g_pDevice->LightEnable(0, g_bLight);
g_pDevice->SetRenderState(D3DRS_AMBIENT, 0);
}
else
{
g_pDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(128, 128, 128));
}
}
break;
case 'N':
{
g_Terrain.SetDrawNormal(!g_Terrain.IsDrawNormal());
}
break;
case 'R':
{
g_Terrain.RandomHeight(0.75f, 0.15f, 2);
D3DXMatrixTranslation(g_Terrain.GetMatrix(), 0, 0, 0);
g_Camera.SetPosition(&D3DXVECTOR3(TERRAIN_SIZE / 2.0f, g_Terrain.GetMaxHeight(), TERRAIN_SIZE / 2.0f));
g_Camera.SetTarget(&D3DXVECTOR3(0.0f, 0.f, 0.0f));
g_bUpdateDetail = TRUE;
}
break;
}
}
void OnLButtonDown(HWND hWnd, int x, int y)
{
SetCapture(hWnd);
g_wRelaX = x;
g_wRelaY = y;
g_bOnLButton = TRUE;
}
void OnLButtonUp(HWND hWnd, int x, int y)
{
if(!g_bOnRButton)
ReleaseCapture();
g_bOnLButton = FALSE;
}
void OnRButtonDown(HWND hWnd, int x, int y)
{
SetCapture(hWnd);
g_wRelaX = x;
g_wRelaY = y;
g_bOnRButton = TRUE;
}
void OnRButtonUp(HWND hWnd, int x, int y)
{
if(!g_bOnLButton)
ReleaseCapture();
g_bOnRButton = FALSE;
}
void OnMButtonDown(HWND hWnd, int x, int y)
{
}
void OnMButtonUp(HWND hWnd, int x, int y)
{
}
void OnMouseMove(HWND hWnd, int x, int y)
{
if(g_bOnRButton)
{
float fYaw = (x - g_wRelaX) / 100.f;
float fPitch = (y - g_wRelaY) / 100.f;
g_Camera.Rotate(fYaw, fPitch, 0.f, true);
g_Light.SetDirection(&g_Camera.GetDirection());
}
if(g_bOnLButton)
{
g_Camera.GotoDest((g_wRelaY - y) / 10.f);
g_Light.SetPosition(g_Camera.GetPosition());
g_bUpdateDetail = TRUE;
}
g_wRelaX = x;
g_wRelaY = y;
}
void OnMouseWheel(HWND hWnd, short zDelta)
{
g_Camera.GotoDest(zDelta / 10.f);
g_Light.SetPosition(g_Camera.GetPosition());
g_bUpdateDetail = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -