【阅读笔记之十三】《DIRECTX.9.0.3D游戏开发编程基础》 网格(三)加载小汽车的XFile的demo

网格(三)加载小汽车X文件的一个demo

 

       前面我们已经学习了关于网格的一些知识,由于篇幅较大,所以,这里我们将示例单独拿出来作为一篇内容。

      1. 首先,当然是通用的头文件d3dUtility.h文件。我们直接来欣赏源代码。

//**********************************************************************************//
// Utility.h
//**********************************************************************************//

#ifndef __d3dUtilityH__
#define __d3dUtilityH__

#include<d3dx9.h>
#include<string>

namespace d3d
{
	//**********************初始化函数******************************************//
	bool InitiateD3D(HINSTANCE hInstance, int iWidth, int iHeight, bool windowed, 
						D3DDEVTYPE deviceType, IDirect3DDevice9** device);

	//**********************消息循环函数****************************************//
	int EnterMessageLoop(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;	// 删除对象
		}
	}

	//**********************常用颜色定义****************************************//
	const D3DXCOLOR		  WHITE(D3DCOLOR_XRGB(255, 255, 255) );
	const D3DXCOLOR      BLACK( D3DCOLOR_XRGB(  0,   0,   0) );
	const D3DXCOLOR        RED( D3DCOLOR_XRGB(255,   0,   0) );
	const D3DXCOLOR      GREEN( D3DCOLOR_XRGB(  0, 255,   0) );
	const D3DXCOLOR       BLUE( D3DCOLOR_XRGB(  0,   0, 255) );
	const D3DXCOLOR     YELLOW( D3DCOLOR_XRGB(255, 255,   0) );
	const D3DXCOLOR       CYAN( D3DCOLOR_XRGB(  0, 255, 255) );
	const D3DXCOLOR    MAGENTA( D3DCOLOR_XRGB(255,   0, 255) );

	//**********************光照初始化******************************************//
	D3DLIGHT9 IniateDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color);
	D3DLIGHT9 IniatePointLight(D3DXVECTOR3* position, D3DXCOLOR* color);
	D3DLIGHT9 IniateSpotLight(D3DXVECTOR3* direction, D3DXVECTOR3* position, D3DXCOLOR* color);

	//**********************材质************************************************//
	D3DMATERIAL9 IniateMaterial(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p);

	const D3DMATERIAL9 WHITE_MTRL  = IniateMaterial(WHITE, WHITE, WHITE, BLACK, 2.0f);
	const D3DMATERIAL9 RED_MTRL    = IniateMaterial(RED, RED, RED, BLACK, 2.0f);
	const D3DMATERIAL9 GREEN_MTRL  = IniateMaterial(GREEN, GREEN, GREEN, BLACK, 2.0f);
	const D3DMATERIAL9 BLUE_MTRL   = IniateMaterial(BLUE, BLUE, BLUE, BLACK, 2.0f);
	const D3DMATERIAL9 YELLOW_MTRL = IniateMaterial(YELLOW, YELLOW, YELLOW, BLACK, 2.0f);

}
#endif

          这个头文件是很通用的,这里也就不解释了。

 

        2. 接下来就是对d3dUtility.h文件中声明的变量和函数进行定义的d3dUtility.cpp了。我们直接欣赏源代码。

//*************************************************************************************//
// Utility.cpp
// 对在Utility.hpp中声明的函数定义
//*************************************************************************************//

#include"d3dUtility.h"

#define WINDOWCLASSNAME			TEXT("Direct3D9App")
#define REGISTERFAILED			TEXT("RegisterClass()-FAILED")
#define CREATEWINDOWFAILED		TEXT("CreateWindow()-FAILED")
#define DIRECT3DCREATE9FAILED	TEXT("Direct3DCreate9()-FAILED")
#define CREATEDEVICEFALIED		TEXT("CreateDevice()-FAILED")
#define WINDOWNAME				TEXT("WindowByJosh")

//***************************初始化函数*******************************************//
bool d3d::InitiateD3D(HINSTANCE hInstance, int iWidth, int iHeight, 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 = WINDOWCLASSNAME;

	if(!RegisterClass(&wc))
	{
		::MessageBox(0, REGISTERFAILED, 0, 0);
		return false;
	}

	HWND hWnd = 0;
	hWnd = ::CreateWindow(WINDOWCLASSNAME, WINDOWNAME, WS_EX_TOPMOST, 
							0, 0, iWidth, iHeight, 0, 0, hInstance, 0);
	if(!hWnd)
	{
		::MessageBox(0, CREATEWINDOWFAILED, 0, 0);
		return false;
	}
	::ShowWindow(hWnd, SW_SHOW);
	::UpdateWindow(hWnd);

	//************************初始化D3D**********************************//
	HRESULT hr = 0;

	// 1.创建Direct3D设备接口对象,即IDirect3D9对象
	IDirect3D9* d3d9;
	d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
	if(!d3d9)
	{
		::MessageBox(0, DIRECT3DCREATE9FAILED, 0, 0);
		return false;
	}

	// 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;

	// 3.填充D3DPRESENT_PARAMETERS结构
	D3DPRESENT_PARAMETERS d3dpp;
	d3dpp.BackBufferWidth            = iWidth;
	d3dpp.BackBufferHeight           = iHeight;
	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;

	// 4.创建Direct3D设备对象
	hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, deviceType, hWnd, vp, &d3dpp, device);
	if(FAILED(hr))
	{
		//尝试使用16bits深度缓存
		d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
		hr = d3d9->CreateDevice(
			D3DADAPTER_DEFAULT,
			deviceType,
			hWnd,
			vp,
			&d3dpp,
			device);
		if(FAILED(hr))
		{
			::MessageBox(hWnd, CREATEDEVICEFALIED, 0, 0);
			return false;
		}
	}

	d3d9->Release();	//释放接口对象

	return true;
}

//***************************消息循环函数*****************************************//
int d3d::EnterMessageLoop( 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.001f;

			ptr_display(timeDelta);
			lastTime = currTime;
		}
	}
	return msg.wParam;
}

//***************************光照初始化函数************************************************************//
D3DLIGHT9 d3d::IniateDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color)
{
	D3DLIGHT9 light;
	::ZeroMemory(&light, sizeof(D3DLIGHT9));

	light.Type = D3DLIGHT_DIRECTIONAL;
	light.Ambient = *color * 0.4f;
	light.Diffuse = *color;
	light.Specular = *color * 0.6f;
	light.Direction = *direction;

	return light;
}

D3DLIGHT9 d3d::IniatePointLight(D3DXVECTOR3* position, D3DXCOLOR* color)
{
	D3DLIGHT9 light;
	::ZeroMemory(&light, sizeof(D3DLIGHT9));

	light.Type = D3DLIGHT_POINT;
	light.Ambient = *color * 0.4f;
	light.Diffuse = *color;
	light.Specular = *color * 0.6f;
	light.Position = *position;
	light.Range = 1000.0f;
	light.Falloff = 1.0f;
	light.Attenuation0 = 1.0f;
	light.Attenuation1 = 0.0f;
	light.Attenuation2 = 0.0f;

	return light;

}

D3DLIGHT9 d3d::IniateSpotLight(D3DXVECTOR3* position, D3DXVECTOR3* direction, D3DXCOLOR* color)
{
	D3DLIGHT9 light;
	::ZeroMemory(&light, sizeof(D3DLIGHT9));

	light.Type      = D3DLIGHT_SPOT;
	light.Ambient   = *color * 0.4f;
	light.Diffuse   = *color;
	light.Specular  = *color * 0.6f;
	light.Position  = *position;
	light.Direction = *direction;
	light.Range        = 1000.0f;
	light.Falloff      = 1.0f;
	light.Attenuation0 = 1.0f;
	light.Attenuation1 = 0.0f;
	light.Attenuation2 = 0.0f;
	light.Theta        = 0.5f;
	light.Phi          = 0.7f;

	return light;
}

//***************************材质初始化函数*********************************************//
D3DMATERIAL9 d3d::IniateMaterial(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p)
{
	D3DMATERIAL9 material;

	material.Ambient = a;
	material.Diffuse = d;
	material.Specular = s;
	material.Emissive = e;
	material.Power = p;

	return material;
}


         3. 接下来就是我们的核心代码了。这里,我把它命名为MyGame.cpp。这里直接欣赏源代码。

//***********************************************************************************************//
// MyGame.cpp
//***********************************************************************************************//

#include "d3dUtility.h"
#include <vector>
#include <tchar.h>

//****************************全局变量**************************************//
const int Width  = 800;
const int Height = 600;

IDirect3DDevice9*				Device = 0;		// 设备接口对象

ID3DXMesh*						Mesh = 0;		//网格接口对象
std::vector<D3DMATERIAL9>		Materials(0);	//
std::vector<IDirect3DTexture9*> Textures(0);	//

//******************************Setup函数**********************************//
bool Setup()
{
	HRESULT hr = 0;

	// 加载XFile
	ID3DXBuffer* adjBuffer  = 0;
	ID3DXBuffer* mtrlBuffer = 0;
	DWORD		 numMtrls	= 0;

	hr = D3DXLoadMeshFromX( TEXT("car.x"), D3DXMESH_MANAGED, Device, &adjBuffer,
								&mtrlBuffer, 0, &numMtrls, &Mesh );
	if(FAILED(hr))
	{
		::MessageBox(0, TEXT("D3DXLoadMeshFromX()-FAILED"), 0, 0);
		return false;
	}

	// 从XFile文件中取出材质,并加载纹理文件(XFile文件中只提供纹理文件名)
	if( (mtrlBuffer != 0) && (numMtrls != 0))
	{
		D3DXMATERIAL* materials = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();
		for(int i=0; i<numMtrls; i++)
		{
			materials[i].MatD3D.Ambient = materials[i].MatD3D.Diffuse;
			Materials.push_back( materials[i].MatD3D );

			if(materials[i].pTextureFilename != 0)
			{
				IDirect3DTexture9* texture = 0;
				D3DXCreateTextureFromFile(Device, _T("mtrls[i].pTextureFilename"), &texture);

				Textures.push_back( texture );
			}
			else
			{
				Textures.push_back(0);
			}
		}
	}
	d3d::Release<ID3DXBuffer*>(mtrlBuffer);

	// 网格优化
	hr = Mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE,
		(DWORD*) adjBuffer->GetBufferPointer(), 0, 0, 0);

	d3d::Release<ID3DXBuffer*>(adjBuffer);

	if(FAILED(hr))
	{
		::MessageBox(0, TEXT("OptimizeInplace()-FAILED"), 0, 0);
		return false;
	}

	// 设置纹理过滤器
	Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

	// 设置光照
	D3DXVECTOR3 dir(1.0f, -1.0f, 1.0f);
	D3DXCOLOR col(1.0f, 1.0f, 1.0f, 1.0f);
	D3DLIGHT9 light = d3d::IniateDirectionalLight(&dir, &col);

	Device->SetLight(0, &light);
	Device->LightEnable(0, true);
	Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
	Device->SetRenderState(D3DRS_SPECULARENABLE, true);

	// 设置摄像机
	D3DXVECTOR3 pos(4.0f, 4.0f, -13.0f);
	D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

	D3DXMATRIX V;
	D3DXMatrixLookAtLH(&V, &pos, &target, &up);
	Device->SetTransform(D3DTS_VIEW, &V);

	// 设置投影矩阵
	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI * 0.5f,
								(float)Width / (float)Height, 1.0f, 1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);

	return true;

}

//*******************************CleanUp函数*******************************//
void CleanUp()
{
	d3d::Release<ID3DXMesh*>(Mesh);

	for(int i = 0; i < Textures.size(); i++)
		d3d::Release<IDirect3DTexture9*>( Textures[i] );
}

//*******************************Display函数*******************************//
bool Display( float timeDelta)
{
	if(Device)
	{
		static float y = 0.0f;
		D3DXMATRIX yRot;
		D3DXMatrixRotationY(&yRot, y);
		
		y += timeDelta;
		if( y>= 6.28f )
			y = 0.0f;

		D3DMATRIX World = yRot;
		Device->SetTransform(D3DTS_WORLD, &World);
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();

		for(int i = 0; i < Materials.size(); i++)
		{
			Device->SetMaterial( &Materials[i] );
			Device->SetTexture(0, Textures[i]);
			Mesh->DrawSubset(i);
		}	

		Device->EndScene();
		Device->Present(0, 0, 0, 0);
	}

	return true;
}

//*******************************WndProc***********************************//
LRESULT CALLBACK d3d::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);
}

//*******************************WinMain***********************************//
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
	if(!d3d::InitiateD3D(hinstance,
		Width, Height, true, D3DDEVTYPE_HAL, &Device))
	{
		::MessageBox(0, TEXT("InitD3D() - FAILED"), 0, 0);
		return 0;
	}
		
	if(!Setup())
	{
		::MessageBox(0, TEXT("Setup() - FAILED"), 0, 0);
		return 0;
	}

	d3d::EnterMessageLoop( Display );

	CleanUp();

	Device->Release();

	return 0;
}


       4. 把这三个文件输入,并且将car.x文件放在工程的根目录下,就可以编译运行了。下面,给出运行的效果图,如下。

 

 

 

      好了,最后,我们就完成了一个三维的小汽车旋转的效果了。

      另外需要说明的是,X文件一般可以由Maya,3DS MAX等软件建模转换而来。还有,在DirectX SDK中,微软也提供的一些实例当中也有一些模型的X文件,我这里的目录是E:\Microsoft DirectX SDK\Samples\Media。

      初学者看这些代码多少会有些云里雾里。这个时候不要急功近利,把一个demo看懂看透,我相信就可以以一反三了。

      学习游戏编程是必须要学习3D建模的,这里给出Maya的下载链接和本示例完整工程的下载。

      Maya:http://www.cngr.cn/dir/211/280/2012042182573.html

      Maya视频教学(零基础):http://pcedu.pconline.com.cn/videoedu/3dsmax/0910/1861304.html

      本示例完整工程下载:http://download.csdn.net/download/chenwu_843402773/4938339

 

                                                                                                                        ———— by   Josh

                                                                                                                        2012年12月28日

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值