DirectX3D游戏开发五 简单模型创建(索引缓存)

    欢迎来到EasyLiu的博客!

    参考:directxtutorial.com

    到目前为止我们仅仅创建了一些单个的三角形。我们知道3D模型是由很多三角形连接起来形成一个几何体的。在这节课中,我们讲一下怎样利用三角形来建立一下一些简单的集合图形,以及怎样移动、旋转和缩放他们。

    绘制一个四边形

    一个四边形可以看做是由两个三角形组成,如下所示:


    代码实现也比较简单:

HRESULT InitQuad()
{
	// Initialize three vertices for rendering a triangle
	CUSTOMVERTEX vertices[] =
	{
		{ -3.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), }, // x, y, z, color
		{ 3.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
		{ -3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0), },
		{ 3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255), },
	};
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(
		4 * sizeof(CUSTOMVERTEX),
		0,
		D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT,
		&g_pQuadVb,
		NULL)))
	{
		return E_FAIL;
	}

	// Now we fill the vertex buffer. To do this, we need to Lock() the VB to
	// gain access to the vertices. This mechanism is required becuase vertex
	// buffers may be in device memory.
	VOID* pVertices;
	if (FAILED(g_pQuadVb->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, vertices, sizeof(vertices));
	g_pQuadVb->Unlock();


	return S_OK;
}
    然后怎样显示呢?  

    代码如下:这里绘制图元的时候使用的是D3DPT_TRIANGLESTRIP(线段条带)而不是 D3DPT_TRIANGLELIST(三角形列表),至于图元类型下节再详细讲解!

   g_pd3dDevice->SetStreamSource(0, g_pQuadVb, 0, sizeof(CUSTOMVERTEX));
   g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

绘制一个立方体

    其实我们没有必要为每一个四边形创建四个顶点,当我们绘制一个立方体的时候,如果还按顶点索引的方式,将需要24个顶点,但是实际上立方体只有8个顶点。如果我们只需要创建8个顶点就会很简单,然后用这些顶点来组成6个四边形。

    我们可以使用索引缓存来解决这个问题。在DirectX中,一个索引是一个存储顶点序号的int型。它们是以一定的顺序

的表示出来,所以第一个顶点在缓冲区中顶点号0,第二个顶点是顶点号2,以此类推。

    索引缓存是一个存储顶点渲染顺序的位于内存中的缓冲区,不同于存储一个长包含坐标的列表,它是存储一个长的包含索引的列表。

    举个例子,如下所示的立方体:


    这个立方体有8个角,每个角有一个坐标,但是在这里这个立方体以索引号的形式标注了出来。

    我们还是用8个不同的顶点建立一个顶点缓存,每个顶点代表立方体的一个角,包括坐标和颜色,代码如下所示:

CUSTOMVERTEX vertices[] =
{
    { -3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },    // vertex 0
    { 3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 0), },     // vertex 1
    { -3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },   // 2
    { 3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },  // 3
    { -3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },     // ...
    { 3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
    { -3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
    { 3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 255), },
};
    但是以上代码没有创建任何三角形或者四边形,只是角而已。为了建立三角形,我们指定三个索引为一行。如果我们使用“0,1,2”以及"2,1,3“,我们将得到两个三角形,如下图所示,注意我们可以为每个面重复相同的操作,为每个面生成一个四边形。

   

    在我们说我们想要用哪些索引之前,我们需要创建一个索引缓存。需要调用函数CreateIndexBuffer来创建:

HRESULT CreateIndexBuffer(
    UINT Length,
    DWORD Usage,
    D3DFORMAT Format,
    D3DPOOL Pool,
    LPDIRECT3DINDEXBUFFER9 ppIndexBuffer,
    HANDLE* pSharedHandle);
    这个函数和CreateVertexBuffer函数类似,只是第三个不一样,在这里指定顶点格式比如D3DFMT_INDEX16。

    创建索引缓存的代码如下:

// create the indices using an int array
	short indices[] =
	{
		0, 1, 2,    // side 1
		2, 1, 3,
		4, 0, 6,    // side 2
		6, 0, 2,
		7, 5, 6,    // side 3
		6, 5, 4,
		3, 1, 7,    // side 4
		7, 1, 5,
		4, 5, 0,    // side 5
		0, 5, 1,
		3, 7, 2,    // side 6
		2, 7, 6,
	};

	// create an index buffer interface called i_buffer
	g_pd3dDevice->CreateIndexBuffer(36 * sizeof(short), // 3 per triangle, 12 triangles
		0,
		D3DFMT_INDEX16,
		D3DPOOL_MANAGED,
		&g_pCubeIndex,
		NULL);

	VOID* pVoid;
	// lock i_buffer and load the indices into it
	g_pCubeIndex->Lock(0, 0, (void**)&pVoid, 0);
	memcpy(pVoid, indices, sizeof(indices));
	g_pCubeIndex->Unlock();
    把顶点缓存和索引缓存合起来就是如下代码:

CUSTOMVERTEX vertices[] =
	{
		{ -3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },    // vertex 0
		{ 3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 0), },     // vertex 1
		{ -3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },   // 2
		{ 3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },  // 3
		{ -3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },     // ...
		{ 3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
		{ -3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{ 3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 255), },
	};
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(
		8 * sizeof(CUSTOMVERTEX),
		0,
		D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT,
		&g_pCubeVb,
		NULL)))
	{
		return E_FAIL;
	}

	VOID* pVertices;
	if (FAILED(g_pCubeVb->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, vertices, sizeof(vertices));
	g_pCubeVb->Unlock();

	// create the indices using an int array
	short indices[] =
	{
		0, 1, 2,    // side 1
		2, 1, 3,
		4, 0, 6,    // side 2
		6, 0, 2,
		7, 5, 6,    // side 3
		6, 5, 4,
		3, 1, 7,    // side 4
		7, 1, 5,
		4, 5, 0,    // side 5
		0, 5, 1,
		3, 7, 2,    // side 6
		2, 7, 6,
	};

	// create an index buffer interface called i_buffer
	g_pd3dDevice->CreateIndexBuffer(36 * sizeof(short), // 3 per triangle, 12 triangles
		0,
		D3DFMT_INDEX16,
		D3DPOOL_MANAGED,
		&g_pCubeIndex,
		NULL);

	VOID* pVoid;
	// lock i_buffer and load the indices into it
	g_pCubeIndex->Lock(0, 0, (void**)&pVoid, 0);
	memcpy(pVoid, indices, sizeof(indices));
	g_pCubeIndex->Unlock();
    那么怎么显示呢?代码如下:

// select the vertex and index buffers to use
		g_pd3dDevice->SetStreamSource(0, g_pCubeVb, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->SetIndices(g_pCubeIndex);
		// draw the cube
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
使用到了两个新函数:SetIndices:为Direct3D设备设置索引缓存,DrawIndexedPrimitive:使用顶点缓存绘制图形,具体各个参数的含义不细讲。

    绘制一个金字塔

    我们还可以绘制一些别的形状,比如绘制一个金字塔,如下所示:


   代码如下:

   初始化代码:

HRESULT InitPyramid(){
	// create the vertices using the CUSTOMVERTEX
	CUSTOMVERTEX vertices[] =
	{
		// base
		{ -3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{ 3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
		{ -3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
		{ 3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },

		// top
		{ 0.0f, 7.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
	};

	// create a vertex buffer interface called v_buffer
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(5 * sizeof(CUSTOMVERTEX),
		0,
		D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT,
		&g_pPyramidVb,
		NULL)))
	{
		return E_FAIL;
	}

	VOID* pVertices;
	if (FAILED(g_pPyramidVb->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, vertices, sizeof(vertices));
	g_pPyramidVb->Unlock();

	// create the indices using an int array
	short indices[] =
	{
		0, 2, 1,    // base
		1, 2, 3,
		0, 1, 4,    // sides
		1, 3, 4,
		3, 2, 4,
		2, 0, 4,
	};

	// create a index buffer interface called i_buffer
	if (FAILED(g_pd3dDevice->CreateIndexBuffer(18 * sizeof(short),
		0,
		D3DFMT_INDEX16,
		D3DPOOL_DEFAULT,
		&g_pPyramidIndex,
		NULL)))
	{
		return E_FAIL;
	}
	VOID* pVoid;
	// lock i_buffer and load the indices into it
	if (FAILED(g_pPyramidIndex->Lock(0, 0, (void**)&pVoid, 0)))
	{
		return E_FAIL;
	}
	memcpy(pVoid, indices, sizeof(indices));
	g_pPyramidIndex->Unlock();

	return S_OK;
}
显示代码:

//draw the pyramid
		g_pd3dDevice->SetTransform(D3DTS_WORLD, &(matRotateY*matTranslateC));
		// select the vertex and index buffers to use
		g_pd3dDevice->SetStreamSource(0, g_pPyramidVb, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->SetIndices(g_pPyramidIndex);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 5, 0, 6);

绘制一个飞机

代码如下:

HRESULT InitHyperCraft(){
	// create the vertices using the CUSTOMVERTEX
	struct CUSTOMVERTEX vertices[] =
	{
		// fuselage
		{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
		{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
		{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },

		// left gun
		{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
		{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },

		// right gun
		{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
		{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
	};

	// create a vertex buffer interface called v_buffer
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(10 * sizeof(CUSTOMVERTEX),
		0,
		D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT,
		&g_pHyperCraftVb,
		NULL)))
	{
		return E_FAIL;
	}
	VOID* pVertices;
	if (FAILED(g_pHyperCraftVb->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, vertices, sizeof(vertices));
	g_pHyperCraftVb->Unlock();

	// create the indices using an int array
	short indices[] =
	{
		0, 1, 2,    // fuselage
		2, 1, 3,
		3, 1, 0,
		0, 2, 3,
		4, 5, 6,    // wings
		7, 8, 9,
	};

	// create a index buffer interface called i_buffer
	g_pd3dDevice->CreateIndexBuffer(18 * sizeof(short),
		0,
		D3DFMT_INDEX16,
		D3DPOOL_DEFAULT,
		&g_pHyperCraftIndex,
		NULL);

	VOID* pVoid;
	// lock i_buffer and load the indices into it
	if (FAILED(g_pHyperCraftIndex->Lock(0, 0, (void**)&pVoid, 0)))
	{
		return E_FAIL;
	}
	memcpy(pVoid, indices, sizeof(indices));
	g_pHyperCraftIndex->Unlock();

	return S_OK;
}

显示代码:

//draw the hypercraft
		g_pd3dDevice->SetTransform(D3DTS_WORLD, &(matRotateY*matTranslateD));
		// select the vertex and index buffers to use
		g_pd3dDevice->SetStreamSource(0, g_pHyperCraftVb, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->SetIndices(g_pHyperCraftIndex);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 10, 0, 6);

通过把以上形状放在一个窗口中显示,同时使形状都绕自身的y轴旋转,达到的效果如下所示:


main.c源代码如下:

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib,"winmm.lib") 

#include <d3d9.h>
#include <d3dx9.h>
#include "Windows.h"
#include <mmsystem.h>
#pragma warning( disable : 4996 ) // disable deprecated warning 
#include <strsafe.h>
#pragma warning( default : 4996 )

// define the screen resolution
const  int  SCREEN_WIDTH = 800;
const  int  SCREEN_HEIGHT = 800;

LPDIRECT3D9             g_pD3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device
LPDIRECT3DVERTEXBUFFER9 g_pQuadVb = NULL; // Buffer to hold quad vertices

LPDIRECT3DVERTEXBUFFER9 g_pCubeVb = NULL; // Buffer to hold cube vertices
LPDIRECT3DINDEXBUFFER9  g_pCubeIndex = NULL;//buffer to hold cube index

LPDIRECT3DVERTEXBUFFER9 g_pPyramidVb = NULL;//buffer to hold pyramid vertices
LPDIRECT3DINDEXBUFFER9  g_pPyramidIndex = NULL;//buffer to hold pyramid index

LPDIRECT3DVERTEXBUFFER9 g_pHyperCraftVb = NULL;
LPDIRECT3DINDEXBUFFER9  g_pHyperCraftIndex = NULL;
// A structure for our custom vertex type
struct CUSTOMVERTEX
{
	FLOAT x, y, z;
	DWORD color;        // The vertex color
};

// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)


HRESULT InitD3D(HWND hWnd)
{
	// Create the D3D object.
	if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
		return E_FAIL;

	//fill D3DCAPS9 struct with the capabilities of the primary display adapter
	D3DCAPS9 caps;
	g_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
	//can we use hardware vertex processing?
	DWORD vp = 0;
	if (caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT)
	{
		//yes,support hardware vertex processing
		vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
	}
	else
	{
		//no,
		vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
	}

	// Set up the structure used to create the D3DDevice
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.hDeviceWindow = hWnd;
	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
	d3dpp.BackBufferWidth = SCREEN_WIDTH;
	d3dpp.BackBufferHeight = SCREEN_HEIGHT;
	d3dpp.EnableAutoDepthStencil = TRUE;    // automatically run the z-buffer for us
	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;    // 16-bit pixel format for the z-buffer

	// Create the D3DDevice
	if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
		vp,
		&d3dpp, &g_pd3dDevice)))
	{
		return E_FAIL;
	}

	// Device state would normally be set here

	g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);    // turn off the 3D lighting
	g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);    // both sides of the triangles
	g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);    // turn on the z-buffer
	return S_OK;
}

HRESULT InitQuad()
{
	// Initialize three vertices for rendering a triangle
	CUSTOMVERTEX vertices[] =
	{
		{ -3.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), }, // x, y, z, color
		{ 3.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
		{ -3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0), },
		{ 3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255), },
	};
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(
		4 * sizeof(CUSTOMVERTEX),
		0,
		D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT,
		&g_pQuadVb,
		NULL)))
	{
		return E_FAIL;
	}

	// Now we fill the vertex buffer. To do this, we need to Lock() the VB to
	// gain access to the vertices. This mechanism is required becuase vertex
	// buffers may be in device memory.
	VOID* pVertices;
	if (FAILED(g_pQuadVb->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, vertices, sizeof(vertices));
	g_pQuadVb->Unlock();


	return S_OK;
}
HRESULT InitCube()
{
	CUSTOMVERTEX vertices[] =
	{
		{ -3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },    // vertex 0
		{ 3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 0), },     // vertex 1
		{ -3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },   // 2
		{ 3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },  // 3
		{ -3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },     // ...
		{ 3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
		{ -3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{ 3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 255), },
	};
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(
		8 * sizeof(CUSTOMVERTEX),
		0,
		D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT,
		&g_pCubeVb,
		NULL)))
	{
		return E_FAIL;
	}

	VOID* pVertices;
	if (FAILED(g_pCubeVb->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, vertices, sizeof(vertices));
	g_pCubeVb->Unlock();

	// create the indices using an int array
	short indices[] =
	{
		0, 1, 2,    // side 1
		2, 1, 3,
		4, 0, 6,    // side 2
		6, 0, 2,
		7, 5, 6,    // side 3
		6, 5, 4,
		3, 1, 7,    // side 4
		7, 1, 5,
		4, 5, 0,    // side 5
		0, 5, 1,
		3, 7, 2,    // side 6
		2, 7, 6,
	};

	// create an index buffer interface called i_buffer
	if (FAILED(g_pd3dDevice->CreateIndexBuffer(36 * sizeof(short), // 3 per triangle, 12 triangles
		0,
		D3DFMT_INDEX16,
		D3DPOOL_DEFAULT,
		&g_pCubeIndex,
		NULL)))
	{
		return E_FAIL;
	}

	VOID* pVoid;
	// lock i_buffer and load the indices into it
	if (FAILED(g_pCubeIndex->Lock(0, 0, (void**)&pVoid, 0)))
	{
		return E_FAIL;
	}
	memcpy(pVoid, indices, sizeof(indices));
	g_pCubeIndex->Unlock();

	return S_OK;
}
HRESULT InitPyramid(){
	// create the vertices using the CUSTOMVERTEX
	CUSTOMVERTEX vertices[] =
	{
		// base
		{ -3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{ 3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
		{ -3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
		{ 3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },

		// top
		{ 0.0f, 7.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
	};

	// create a vertex buffer interface called v_buffer
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(5 * sizeof(CUSTOMVERTEX),
		0,
		D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT,
		&g_pPyramidVb,
		NULL)))
	{
		return E_FAIL;
	}

	VOID* pVertices;
	if (FAILED(g_pPyramidVb->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, vertices, sizeof(vertices));
	g_pPyramidVb->Unlock();

	// create the indices using an int array
	short indices[] =
	{
		0, 2, 1,    // base
		1, 2, 3,
		0, 1, 4,    // sides
		1, 3, 4,
		3, 2, 4,
		2, 0, 4,
	};

	// create a index buffer interface called i_buffer
	if (FAILED(g_pd3dDevice->CreateIndexBuffer(18 * sizeof(short),
		0,
		D3DFMT_INDEX16,
		D3DPOOL_DEFAULT,
		&g_pPyramidIndex,
		NULL)))
	{
		return E_FAIL;
	}
	VOID* pVoid;
	// lock i_buffer and load the indices into it
	if (FAILED(g_pPyramidIndex->Lock(0, 0, (void**)&pVoid, 0)))
	{
		return E_FAIL;
	}
	memcpy(pVoid, indices, sizeof(indices));
	g_pPyramidIndex->Unlock();

	return S_OK;
}
HRESULT InitHyperCraft(){
	// create the vertices using the CUSTOMVERTEX
	struct CUSTOMVERTEX vertices[] =
	{
		// fuselage
		{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
		{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
		{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },

		// left gun
		{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
		{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },

		// right gun
		{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
		{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
	};

	// create a vertex buffer interface called v_buffer
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(10 * sizeof(CUSTOMVERTEX),
		0,
		D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT,
		&g_pHyperCraftVb,
		NULL)))
	{
		return E_FAIL;
	}
	VOID* pVertices;
	if (FAILED(g_pHyperCraftVb->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, vertices, sizeof(vertices));
	g_pHyperCraftVb->Unlock();

	// create the indices using an int array
	short indices[] =
	{
		0, 1, 2,    // fuselage
		2, 1, 3,
		3, 1, 0,
		0, 2, 3,
		4, 5, 6,    // wings
		7, 8, 9,
	};

	// create a index buffer interface called i_buffer
	g_pd3dDevice->CreateIndexBuffer(18 * sizeof(short),
		0,
		D3DFMT_INDEX16,
		D3DPOOL_DEFAULT,
		&g_pHyperCraftIndex,
		NULL);

	VOID* pVoid;
	// lock i_buffer and load the indices into it
	if (FAILED(g_pHyperCraftIndex->Lock(0, 0, (void**)&pVoid, 0)))
	{
		return E_FAIL;
	}
	memcpy(pVoid, indices, sizeof(indices));
	g_pHyperCraftIndex->Unlock();

	return S_OK;
}

HRESULT  InitModel(){
	return InitCube()|InitQuad()|InitPyramid()|InitHyperCraft();
}
VOID SetupMatrices()
{
	D3DXVECTOR3 vEyePt(0.0f, 0.0f, -30.0f);//摄像头位置,决定了场景中物体的大小
	D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);//摄像头朝向
	D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);//垂直方向为y轴,这个一般是y轴
	D3DXMATRIXA16 matView;
	D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);
	g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);


	D3DXMATRIXA16 matProj;
	D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, 1.0f, 100.0f);
	g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
}
VOID Render()
{
	// Clear the backbuffer to a blue color
	g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

	// Begin the scene
	if (SUCCEEDED(g_pd3dDevice->BeginScene()))
	{

		SetupMatrices();//设置转换矩阵
		g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);	//设置顶点格式

		D3DXMATRIXA16 matTranslateA;    // a matrix to store the translation for triangle A
		D3DXMATRIXA16 matTranslateB;   // a matrix to store the translation for triangle B
		D3DXMATRIXA16 matTranslateC;   // a matrix to store the translation for triangle C
		D3DXMATRIXA16 matTranslateD;   // a matrix to store the translation for triangle D
		
		D3DXMATRIXA16 matRotateY;      // a matrix to store the rotation for each triangle
		UINT iTime = timeGetTime() % 2000;//获取当前时间
		FLOAT fAngle = iTime * (2.0f * D3DX_PI) / 2000.0f;//1000ms旋转360度

		D3DXMatrixRotationY(&matRotateY, fAngle);    // the front side
		// build MULTIPLE matrices to translate the model and one to rotate
		D3DXMatrixTranslation(&matTranslateA, 7.0f, 7.0f, 0.0f);
		D3DXMatrixTranslation(&matTranslateB, -7.0f, 7.0f,0.0f);
		D3DXMatrixTranslation(&matTranslateC, -7.0f, -7.0f,0.0f);
		D3DXMatrixTranslation(&matTranslateD, 4.0f, -4.0f, 0.0f);


		//draw the quad
		g_pd3dDevice->SetTransform(D3DTS_WORLD, &(matRotateY*matTranslateA));//矩阵相乘的顺序有区别,这里先旋转再平移,就改变了旋转中心!
		g_pd3dDevice->SetStreamSource(0, g_pQuadVb, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

		// draw the cube
		g_pd3dDevice->SetTransform(D3DTS_WORLD, &(matRotateY*matTranslateB));
		// select the vertex and index buffers to use
		g_pd3dDevice->SetStreamSource(0, g_pCubeVb, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->SetIndices(g_pCubeIndex);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);

		//draw the pyramid
		g_pd3dDevice->SetTransform(D3DTS_WORLD, &(matRotateY*matTranslateC));
		// select the vertex and index buffers to use
		g_pd3dDevice->SetStreamSource(0, g_pPyramidVb, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->SetIndices(g_pPyramidIndex);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 5, 0, 6);

		//draw the hypercraft
		g_pd3dDevice->SetTransform(D3DTS_WORLD, &(matRotateY*matTranslateD));
		// select the vertex and index buffers to use
		g_pd3dDevice->SetStreamSource(0, g_pHyperCraftVb, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->SetIndices(g_pHyperCraftIndex);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 10, 0, 6);

		// End the scene
		g_pd3dDevice->EndScene();
	}

	// Present the backbuffer contents to the display
	g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}
//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
	if (g_pQuadVb != NULL)
		g_pQuadVb->Release();

	if (g_pCubeVb!=NULL)
		g_pCubeVb->Release();

	if (g_pd3dDevice != NULL)
		g_pd3dDevice->Release();

	if (g_pD3D != NULL)
		g_pD3D->Release();
}
//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_DESTROY:
		Cleanup();
		PostQuitMessage(0);
		return 0;
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}
//-----------------------------------------------------------------------------
// Name: wWinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, INT)
{
	UNREFERENCED_PARAMETER(hInst);

	// Register the window class
	WNDCLASSEX wc =
	{
		sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
		GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
		L"D3D Tutorial", NULL
	};
	RegisterClassEx(&wc);

	// Create the application's window
	HWND hWnd = CreateWindow(L"D3D Tutorial", L"D3D Tutorial 08: Model",
		WS_OVERLAPPEDWINDOW, 100, 100, SCREEN_WIDTH, SCREEN_HEIGHT,
		NULL, NULL, wc.hInstance, NULL);

	// Initialize Direct3D
	if (SUCCEEDED(InitD3D(hWnd)))
	{
		// Create the vertex buffer
		if (SUCCEEDED(InitModel()))
		{
			// Show the window
			ShowWindow(hWnd, SW_SHOWDEFAULT);
			UpdateWindow(hWnd);

			// Enter the message loop
			MSG msg;
			ZeroMemory(&msg, sizeof(msg));
			while (msg.message != WM_QUIT)
			{
				if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
				{
					TranslateMessage(&msg);
					DispatchMessage(&msg);
				}
				else
					Render();
			}
		}
	}

	UnregisterClass(L"D3D Tutorial", wc.hInstance);
	return 0;
}







    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值