⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x3d.cpp

📁 x3d_new.rar
💻 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 + -