在屏幕绘制一个旋转的线框立方体(使用顶点缓存和索引缓存)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DY_1024/article/details/84285476

首先里面还是有两个基本的文件:d3dUtility.h以及d3dUtility.cpp

里面的主要内容就是实现Direct3D的初始化,以及模板函数的的实现,和消息循环函数的声明,回调函数的声明。

具体的解释在博客:在屏幕绘制一个三角形以及Direct3D初始化例程中有详细的解释,这里就不在过多的重复。

我们主要来看主函数文件Cube.cpp里面是怎么实现,我们在代码中详细的讲解,下面是cube.cpp内容:

//包含头文件
#include "d3dUtility.h"

//定义一个设备类型的指针,准备指向设备
IDirect3DDevice9* Device = 0;

//定义两个数据,用来规定窗口的大小
const int Width = 640;
const int Height = 480;

//定义两个指针,一个准备指向顶点缓存(VertexBuffer),一个准备指向索引缓存(IndexBuffer)
IDirect3DVertexBuffer9* VB = 0;
IDirect3DIndexBuffer9*  IB = 0;

//定义一个顶点,里面有x,y,z坐标
struct Vertex
{
	Vertex() {}
	Vertex(float x, float y, float z)
	{
		_x = x;  _y = y;  _z = z;
	}
	float _x, _y, _z;
	static const DWORD FVF;
};
//顶点的灵活顶点格式的定义
const DWORD Vertex::FVF = D3DFVF_XYZ;

//资源的分配
bool Setup()
{
    //将我们刚才创建的顶点缓存VP进行实例化
	Device->CreateVertexBuffer(
		8 * sizeof(Vertex),    //开辟可以存放8个顶点的缓存用来给VP指
		D3DUSAGE_WRITEONLY,    //顶点缓存的使用格式,是几个枚举类型,这个枚举类型表示创建的顶点缓存只能写
		Vertex::FVF,     //将顶点的灵活顶点格式传进来
		D3DPOOL_MANAGED,    //内存池得类型
		&VB,                //定义的顶点缓存的指针
		0);                //不使用,文档里面说是给Window Vista使用

    //将我们刚才创建的索引缓存进行IP实例化
	Device->CreateIndexBuffer(
		36 * sizeof(WORD),    //开辟可以存放36个索引的空间给IP指
		D3DUSAGE_WRITEONLY,    //索引缓存的属性,同上面的顶点缓存的对应参数
		D3DFMT_INDEX16,        //索引缓存的位数,32位和16位,32位有些硬件不支持
		D3DPOOL_MANAGED,       //内存池的类型
		&IB,                   //定义的指向索引缓存的指针
		0);                    //不使用,文档里面说是给Window Vista使用


	//用顶点的结构定义一个指针,用来
	Vertex* vertices;
    //对方问的顶点进行上锁
	VB->Lock(0, 0, (void**)&vertices, 0);

	//对顶点进行赋值,正方形有8个点
	vertices[0] = Vertex(-1.0f, -1.0f, -1.0f);
	vertices[1] = Vertex(-1.0f, 1.0f, -1.0f);
	vertices[2] = Vertex(1.0f, 1.0f, -1.0f);
	vertices[3] = Vertex(1.0f, -1.0f, -1.0f);
	vertices[4] = Vertex(-1.0f, -1.0f, 1.0f);
	vertices[5] = Vertex(-1.0f, 1.0f, 1.0f);
	vertices[6] = Vertex(1.0f, 1.0f, 1.0f);
	vertices[7] = Vertex(1.0f, -1.0f, 1.0f);
    
    //解锁
	VB->Unlock();

	// 定义多维数据集的三角形
	WORD* indices = 0;
	IB->Lock(0, 0, (void**)&indices, 0);

    //里面存放的是vertices数组里面的索引,
	/* 前面要绘制两个三角形,
    第一个三角形,索引缓存0,1,2里面分别存放的是顶点vertices[0],vertices[1],vertices[2]
    第二个三角形,索引缓存3,4,5里面分别存放的是顶点vertices[0],vertices[2],vertices[3]
    索引缓存里面存放的是顶点缓存里面顶点的索引
    后面同理
    */
	indices[0] = 0; indices[1] = 1; indices[2] = 2;
	indices[3] = 0; indices[4] = 2; indices[5] = 3;

	// 后面
	indices[6] = 4; indices[7] = 6; indices[8] = 5;
	indices[9] = 4; indices[10] = 7; indices[11] = 6;

	// 左面
	indices[12] = 4; indices[13] = 5; indices[14] = 1;
	indices[15] = 4; indices[16] = 1; indices[17] = 0;

	// 右面
	indices[18] = 3; indices[19] = 2; indices[20] = 6;
	indices[21] = 3; indices[22] = 6; indices[23] = 7;

	// 上面
	indices[24] = 1; indices[25] = 5; indices[26] = 6;
	indices[27] = 1; indices[28] = 6; indices[29] = 2;

	// 下面
	indices[30] = 4; indices[31] = 0; indices[32] = 3;
	indices[33] = 4; indices[34] = 3; indices[35] = 7;

	IB->Unlock();


    //摄影机在世界坐标中的位置
	D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);
    //被观察的点在世界坐标的位置
	D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
    //世界坐标系中向上方向的向量
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
	D3DXMATRIX V;
    //通过这个接口获取世界矩阵
	D3DXMatrixLookAtLH(&V, &position, &target, &up);
    
    //设施世界矩阵
	Device->SetTransform(D3DTS_VIEW, &V);

    //用于接收投影矩阵的矩阵
	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
		&proj,
		D3DX_PI * 0.5f, // 视域体的视域角:90度
		(float)Width / (float)Height,//纵横比:为了减少正方形矩阵映射到矩形屏幕之后的畸变
		1.0f,        //到近平面的距离
		1000.0f);    //到原平面的距离

    //设施投影矩阵
	Device->SetTransform(D3DTS_PROJECTION, &proj);

    //设置绘制状态
	Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

	return true;
}

void Cleanup()
{
	d3d::Release<IDirect3DVertexBuffer9*>(VB);
	d3d::Release<IDirect3DIndexBuffer9*>(IB);
}

bool Display(float timeDelta)
{
	if (Device)
	{
        //定义两个矩阵
		D3DXMATRIX Rx, Ry;

		// 得到一个矩阵Rx:乘这个矩阵就相当于:在X轴上旋转45度
		D3DXMatrixRotationX(&Rx, 3.14f / 4.0f);

		// 每一帧增加y的旋转角度
		static float y = 0.0f;
        //得到一个矩阵Ry:乘以这个矩阵就相当于在Y轴旋转y度,y是一直在变化的
		D3DXMatrixRotationY(&Ry, y);
		y += timeDelta;

		//如果角度大于360度,也就是转了一圈,就将y轴的旋转角度重置为0
		if (y >= 6.28f)
			y = 0.0f;

		// 结合矩阵Rx以及Ry,
		D3DXMATRIX p = Rx * Ry;

        //设置世界矩阵
		Device->SetTransform(D3DTS_WORLD, &p);
    
        //清屏
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();
        
        //将顶点缓存和数据流链接
		Device->SetStreamSource(0, VB, 0, sizeof(Vertex));
        //设置索引缓存
		Device->SetIndices(IB);
        //设置灵活顶点格式
		Device->SetFVF(Vertex::FVF);

		//使用接口画出来
		Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);

		Device->EndScene();
        //在设备拥有的后台缓冲区中显示下一个内容
		Device->Present(0, 0, 0, 0);
	}
	return true;
}

//回调函数
//当窗口收到消息的时候应该做出什么动作
//这个函数功能就是:按键“ESC”,窗口退出
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);
}

//
int WINAPI WinMain(HINSTANCE hinstance,
	HINSTANCE prevInstance,
	PSTR cmdLine,
	int showCmd)
{
    //Direct3d初始化
	if (!d3d::InitD3D(hinstance,
		Width, Height, true, D3DDEVTYPE_HAL, &Device))
	{
		::MessageBox(0, "InitD3D() - FAILED", 0, 0);
		return 0;
	}
    
    //分配资源
	if (!Setup())
	{
		::MessageBox(0, "Setup() - FAILED", 0, 0);
		return 0;
	}

    //调用Display画出来
	d3d::EnterMsgLoop(Display);

	Cleanup();

	Device->Release();

	return 0;
}

猜你喜欢

转载自blog.csdn.net/DY_1024/article/details/84285476
今日推荐