Direct3D learning (4)

Direct3D learning (4)

學習D3d的教程,裏面第6章以後就不提供代碼了,自己按照他說的,進行了一些封裝。還是比較膚淺的。目前至少能運行了。

使用異常處理,純虛類接口,繼承,模板template等C++方法。

GameObjectAction是接口類,主要定義了一些基本的虛函數接口。

GameObject是基本類,包含了Direct3DDevice的指針,一個世界矩陣用於表示物體的移動和翻轉,angleX表示相對於x軸的角度,x表示中心相對於x的偏移,其他類似。繼承了GameObjectAction。

class GameApp是運行遊戲的一個類。它裏面定義了一個vector的GameObject,表示畫面中所有物體的集合。

class D3dCube是一個立方體類,(事實上也可以處理長方體),支持基本的移動旋轉等操作。

目前的實現很是簡單。但這畢竟是一個開始。以後一點點修改。

下載地址http://blog.blogchina.com/upload/2005-04-08/20050408152549160215.rar, 解壓後,記得修改工程的directX9的路徑。

下面是源代碼:

 

/*  用於異常處理。 暫時簡單處理了一下。
 * filename: gy_exception.h
 */

#ifndef _GY_EXCEPTION_H
#define _GY_EXCEPTION_H

namespace gy {

	const int ER_CODE = 2000;

	class Exception
	{
	public:
		Exception(int code = 0) : errno(code) { }
		~Exception() { }

		int errno;
	};

}

#endif

/*
 * filename: GameObject.h
 */
#ifndef _GY_GAMEOBJECT_H
#define _GY_GAMEOBJECT_H

#include < d3dx9math.h >
#include < d3d9.h >

namespace gy {

	#define SafeRelease(pObject) /
		if (pObject != NULL) {/
		pObject->Release(); /
		pObject = NULL; /
		}

	inline void Matrix_Initialize(D3DXMATRIX& mat)
	{
		mat = D3DXMATRIX(
			1.0f, 0.0f, 0.0f, 0.0f,
			0.0f, 1.0f, 0.0f, 0.0f,
			0.0f, 0.0f, 1.0f, 0.0f,
			0.0f, 0.0f, 0.0f, 1.0f);
	}

	class GameObjectAction
	{
	public:
		virtual void Render() = 0;
		virtual void MoveTo(float _x, float _y, float _z) = 0;
		virtual void RotateTo(float _anglex, float _angley, float _anglez) = 0;
		virtual void Translate(float _x, float _y, float _z) = 0;
		virtual void Rotate(float _anglex, float _angley, float _anglez) = 0;
	};

	class GameObject : public GameObjectAction
	{
	public:
		GameObject(LPDIRECT3DDEVICE9 p) {
			pD9 = p;
			//position = D3DXVECTOR3(0, 0, 0);
			Matrix_Initialize(worldmatrix);
			x = y = z = anglex = angley = anglez = 0;
		}
		virtual ~GameObject() {}

		// data
	protected:
		LPDIRECT3DDEVICE9 pD9;
		//D3DXVECTOR3 position;
		D3DXMATRIX worldmatrix;
		float anglex, angley, anglez;
		float x, y, z;
	};

}

#endif

/*
 * filename: D3dCube.h
 */


#ifndef _GY_D3DCUBE_H
#define _GY_D3DCUBE_H

#include "GameObject.h"
#include "gy_exception.h"

namespace gy {

	template < class CustomVertex >
	class D3dCube : public GameObject
	{
	public:
		D3dCube(LPDIRECT3DDEVICE9 pD3dDevice9, CustomVertex *array, size_t count, DWORD fvfflag);
		~D3dCube();
		void Render();
		void MoveTo(float _x, float _y, float _z);
		void Translate(float _x, float _y, float _z);
		void Rotate(float _anglex, float _angley, float _anglez);
		void RotateTo(float _anglex, float _angley, float _anglez);

	private:
		void DoTranslate();
		void DoRotate();
		
		LPDIRECT3DVERTEXBUFFER9 vertex;
		DWORD fvf;
		
	};

	template < class CustomVertex >
		D3dCube< CustomVertex >::D3dCube(LPDIRECT3DDEVICE9 p, CustomVertex* array, 
		size_t count, DWORD fvfflag) : GameObject(p)
	{
		void *pVertex;
		size_t length;

		vertex = NULL;

		length = sizeof(CustomVertex) * count;
		if (FAILED(pD9->CreateVertexBuffer(length, 0, fvfflag,D3DPOOL_DEFAULT, &vertex, NULL))) {
			throw(Exception(ER_CODE));
			return;
		}
		if (FAILED(vertex->Lock(0, length, (void**)&pVertex, 0))) {
			throw(Exception(ER_CODE));
			return;
		}
		memcpy(pVertex, array, length);
		vertex->Unlock();
		fvf = fvfflag;
	}

	template < class CustomVertex >
		D3dCube< CustomVertex >::~D3dCube()
	{
		SafeRelease(vertex);
	}

	template < class CustomVertex >
		void D3dCube< CustomVertex > :: DoRotate()
	{
		D3DXMATRIX mat, matX, matY, matZ;
		D3DXMatrixRotationX(&matX, anglex);
		D3DXMatrixRotationX(&matY, angley);
		D3DXMatrixRotationX(&matZ, anglez);
		D3DXMatrixMultiply(&mat, &matX, &matY);
		D3DXMatrixMultiply(&mat, &mat, &matZ);

		D3DXMatrixMultiply(&worldmatrix, &worldmatrix, &mat);
	}

	template < class CustomVertex >
		void D3dCube< CustomVertex >::DoTranslate()
	{
		D3DXMATRIX mat;
		D3DXMatrixTranslation(&mat, x, y, z);

		D3DXMatrixMultiply(&worldmatrix, &worldmatrix, &mat);
	}

	template < class CustomVertex >
		void D3dCube< CustomVertex >::Render()
	{
		DoTranslate();
		DoRotate();
		pD9->SetTransform(D3DTS_WORLD, &worldmatrix);
		pD9->SetStreamSource(0, vertex, 0, sizeof(CustomVertex));
		pD9->SetFVF(fvf);
		pD9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
		pD9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 8);
		pD9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 14, 2);

		Matrix_Initialize(worldmatrix);
	}

	template < class CustomVertex >
		void D3dCube< CustomVertex >::MoveTo(float _x, float _y, float _z)
	{
		x = _x;
		y = _y;
		z = _z;
	}

	template < class CustomVertex >
		void D3dCube< CustomVertex >::Translate(float _x, float _y, float _z)
	{
		x += _x;
		y += _y;
		z += _z;
	}

	template < class CustomVertex >
		void D3dCube< CustomVertex >::Rotate(float _anglex, float _angley, float _anglez)
	{
		anglex += _anglex;
		angley += _angley;
		anglez += _anglez;
	}

	template < class CustomVertex >
		void D3dCube< CustomVertex >::RotateTo(float _anglex, float _angley, float _anglez)
	{
		anglex = _anglex;
		angley = _angley;
		anglez = _anglez;
	}

}

#endif

/*
 * filename: GameApp.h
 */

#ifndef _GY_GAMEAPP_H
#define _GY_GAMEAPP_H

#include "GameObject.h"
#include "gy_exception.h"
#include < vector >

using namespace std;

namespace gy {

class GameApp
{
public:
	GameApp(HWND hWnd);
	~GameApp();
	void Loop();
	void AddObject(GameObject* pObject) {
		objects.push_back(pObject);
	}

	LPDIRECT3DDEVICE9 GetDevice() { return pD9; }
	LPDIRECT3D9 GetD3D() { return pD3D; }

private:
	void Render();
	void SetupCamera();
	void SetupPerspective();
	void Init(HWND hWnd);
	void End();

	// data
public:
	LPDIRECT3D9 pD3D;
	LPDIRECT3DDEVICE9 pD9;
	vector< GameObject* > objects;

};

}

#endif

/*
 * filename: GameApp.cpp
 */

#include "stdafx.h"

#include "GameApp.h"
#include < Mmsystem.h >

namespace gy {

	GameApp::GameApp(HWND hWnd)
	{
		Init(hWnd);
	}

	GameApp::~GameApp()
	{
		End();
	}

	void GameApp::Init(HWND hWnd)
	{
		pD3D = Direct3DCreate9(D3D_SDK_VERSION);
		if (pD3D == NULL) {
			throw(Exception(ER_CODE));
			return;  // use throw in future
		}
		D3DDISPLAYMODE d3ddm;
		if (FAILED( pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) {
			throw(Exception(ER_CODE));
			return;
		}
		D3DPRESENT_PARAMETERS d3dpp;
		ZeroMemory(&d3dpp, sizeof(d3dpp));
		d3dpp.Windowed = TRUE;

		d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
		d3dpp.BackBufferFormat = d3ddm.Format;
		if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
			D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pD9))) {
			throw(Exception(ER_CODE));
			return;
		}
		// remove in future
		// set cullmode use anti-circle-way
		pD9->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
		pD9->SetRenderState(D3DRS_LIGHTING, FALSE);
		return;
	}

	void GameApp::End()
	{
		for (size_t i = 0; i < objects.size(); ++i) {
			if (objects[i] != NULL) {
				delete objects[i];
				objects[i] = NULL;
			}
		}
		SafeRelease(pD9);
		SafeRelease(pD3D);
	}

	void GameApp::SetupCamera()
	{
		//Here we will setup the camera.
		//The camera has three settings: "Camera Position", "Look at Position" and
		//"Up Direction"
		//We have set the following:
		//Camera Position: (0, 0, -30)
		//Look at Position: (0, 0, 0)
		//Up direction: Y-Axis.
		D3DXMATRIX matView;
		D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f,-100.0f), //Camera Position
			&D3DXVECTOR3(0.0f, 0.0f, 0.0f), //Look At Position
			&D3DXVECTOR3(0.0f, 1.0f, 0.0f)); //Up Direction
		pD9->SetTransform(D3DTS_VIEW, &matView);
	}

	void GameApp::SetupPerspective()
	{
		//Here we specify the field of view, aspect ration and near and
		//far clipping planes.
		D3DXMATRIX matProj;
		D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 500.0f);
		pD9->SetTransform(D3DTS_PROJECTION, &matProj);
	}

	void GameApp::Render()
	{
		if (pD9 == NULL) {
			return;
		}
		pD9->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
		pD9->BeginScene();

		SetupCamera();
		SetupPerspective();

		for (size_t i = 0; i < objects.size(); ++i) {
			if (objects[i] != NULL) {
				objects[i]->RotateTo(timeGetTime()/400.0f, 0.0f, 0.0f);
				objects[i]->Render();
			}
		}

		pD9->EndScene();
		pD9->Present(NULL, NULL, NULL, NULL);
	}

	void GameApp::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) {
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}else {
				Render();
			}
			//Sleep(33);  // 30fps = 1000/33 fps
		}
	}
}

/*
 * filename: d3d.cpp
 */

#include "stdafx.h"

#include "GameApp.h"
#include "D3dCube.h"

using namespace gy;

struct CUSTOMVERTEX
{
	FLOAT x, y, z;
	DWORD color;
};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)

CUSTOMVERTEX cvVertex[] = {
	//Top Face
	{-5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 0 - Blue 
	{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 1 - Red 
	{5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 2 - Red 
	{5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 3 - Green 

	//Face 1
	{-5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 4 - Red 
	{-5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 5 - Blue 
	{5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 6 - Green 
	{5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 7 - Red 

	//Face 2
	{5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 8 - Blue 
	{5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 9 - Green

	//Face 3
	{-5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 10 - Green 
	{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 11 - Red 

	//Face 4
	{-5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 12 - Red 
	{-5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 13 - Blue

	//Bottom Face
	{5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 14 - Green 
	{5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 15 - Blue 
	{-5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 16 - Red 
	{-5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 17 - Green

};

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:
			DestroyWindow(hWnd);
			return 0;
			break;
		}
		break;
	default:
		break;
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE , LPSTR , int )
{
	WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L, 
		GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
		"DX Project 1", NULL};
	RegisterClassEx(&wc);
	HWND hWnd = CreateWindow("DX Project 1", "www.andypike.com: Tutorial 1", 
		WS_OVERLAPPEDWINDOW, 50, 50, 500, 500,
		GetDesktopWindow(), NULL, wc.hInstance, NULL);

	try {
		GameApp theGameApp(hWnd);

		ShowWindow(hWnd, SW_SHOWDEFAULT);
		UpdateWindow(hWnd);

		D3dCube< CUSTOMVERTEX > *cube = new D3dCube< CUSTOMVERTEX >(theGameApp.GetDevice(), cvVertex, 
			sizeof(cvVertex)/sizeof(CUSTOMVERTEX), D3DFVF_CUSTOMVERTEX);

		theGameApp.AddObject(cube);

		cube = new D3dCube< CUSTOMVERTEX >(theGameApp.GetDevice(), cvVertex, 
			sizeof(cvVertex)/sizeof(CUSTOMVERTEX), D3DFVF_CUSTOMVERTEX);
		cube->MoveTo(20.0f, 0.0f, 0.0f);

		theGameApp.AddObject(cube);


		theGameApp.Loop();
	}catch(Exception e) {
		cout << "Catch Error: " << e.errno << endl;
	}

    UnregisterClass("DX Project 1", wc.hInstance);
    
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章