骨骼动画1
建立一个空的D3D运行平台
Keep in touch :zpxocivuby@126.com
目的:指导别人建立一个D3D的运行平台,介绍一些几本的概念
任务:编写教程,编写代码
阅读对象:d3d入门者,c/c++熟练,windows编程熟练,VC IDE熟练
描述:
在进行我们的d3d游戏开发之路之前,我们要先建立一个可供我们运行的环境,做一些初始化的工作。
步骤:
1. 初始化一个d3d的各种设备
a) 建立一个windows窗口(用来……),窗口的基本的参数设置
b) 初始化D3D设备这里要分四步:
i. 建立一个IDirect3D9 的COM(很多书中将COM说得如何如何庞大如何如何复杂,我们都用不上^_^,因为我们不是在做组件,我们只是使用COM,你只要将COM当作是一个结构,以及有好多方法来控制该结构就行了。如果你是一个java程序员那么你可以认为它是一个接口interface)接口。
IDirect3D9* d3d9 = 0;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
ii. 得到硬件设备的能力信息(也就是说,我们在操作d3d设备的时候要知道该设备有那些能力,比如说有的设备有支持剪裁(Device supports blits),支持2级缓冲,光栅化等等),只有在用有能力的设备上才能使用各种“能力“不然……(就像我不会飞,你非要让我飞一样)。
这次我们只要得到设备是否支持Device can support transformation and lighting in hardware. (是否支持转换和光照)
iii. 建立我们的Device建立参数
这个参数的作用是用来告诉D3D你要建立一个什么样的设备。比如是不是全屏啊,颜色模式是什么啊,缓冲的数量是多少阿等等。具体信息可以查看MSDN的D3DPRESENT_PARAMETERS信息(坚持看MSDN啊!好处很多,说不完啊);
iv. 建立设备Device
d3d9->CreateDevice(
D3DADAPTER_DEFAULT,//适配器类型
D3DDEVTYPE_HAL, //设备类型(改参数是由第二步中得到设备能力来决定的)
hwnd,//窗口句柄,(什么?你说什么是句柄?你就当它是握在你手中的炒锅的锅柄,你可以方便的将炒锅(窗口)反过来翻过去(各种窗口操作)。当然句柄还有很多功能,在这里我们只用到这些,当使用到别的功能时我再说)。
D3DCREATE_HARDWARE_VERTEXPROCESSING,// D3DCREATE标记这里我们使用的是硬件处理顶点向量能力(改参数的确定需要第二步的判断。)这下知道第二步的重要性了吧
&d3dpp,//设备参数,第三步设定的参数
device);//返回的设备的指针(什么?什么是指针?你可能不太适合读这个文档,建议你把它丢弃。请注意我的阅读对象)
好了,我们终于建立了一个IDirect3DDevice9这个东东是我们以后进行D3D游戏开发的终极直接操作对象。(就像CS中的大狙^_^)。
2. 将要绘制的数据进行初始化(包括,顶点向量的初始化,顶点索引的初始化)
a) 建立顶点向量缓冲
b) 建立顶点索引缓冲
c) 充填缓冲数据
d) 设置视点(就是我们的观察点)
3. 进入绘制图像循环(在此绘制每一帧的图像,也就是我们常说的动画制作了)
在这里你就要做你想做的事了(do what you want to do!)哈哈,我们来做一个三角形转换的绘制循环
a) 首先你要在(数据进行初始化(包括,顶点向量的初始化,顶点索引的初始化))中设定三个顶点向量缓冲,以及一个顶点索引缓冲(什么?为什么要有顶点索引缓冲?这个问题问的好,我保证你是个聪明的baby。这个东东是用来告诉d3d哪些顶点是哪个三角形的你建立的三个顶点,当然可以知道是这三个顶点画三角形,但是如果你有四个,五个……你如何让d3d知道那几个顶点是那个三角形的点啊?所以要在顶点索引中确定三角形的索引顶点.)
建立一个向量缓冲
Device->CreateVertexBuffer(
4 * sizeof(Vertex),
D3DUSAGE_WRITEONLY,
Vertex::FVF,
D3DPOOL_MANAGED,
&VB,
0);
(^_^这个函数我会详细介绍现在你先不要管了)
设置向量点
Vertex* vertices;
VB->Lock(0, 0, (void**)&vertices, 0);//锁定向量缓冲
// vertices of a unit cube
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);
VB->Unlock();//解锁向量缓冲
建立顶点索引缓冲
Device->CreateIndexBuffer(
6 * sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&IB,
0)
(^_^参数信息请查MSDN好了)
设置索引值
WORD* indices = 0;
IB->Lock(0, 0, (void**)&indices, 0);
// front side
//其中indices[0]=0;的意思是第1个三角行的第0个顶点是在顶点向量的第0个值,就是vertices[0]的值.同理indices[1] = 1; 的意思是第1个三角行的第1个顶点是在顶点向量的第1个值,就是vertices[1]的值, 同理indices[2] = 2; 的意思是第1个三角行的第2个顶点是在顶点向量的第2个值,就是vertices[2]的值.那,这样这个三角形就定义好了
indices[0] = 0; indices[1] = 1; indices[2] = 2;
IB->Unlock();
你还可以再加一个三角形,但是现在只有三个顶点啊,三个顶点只能有一个三角形啊(不错!小学毕业了!^_^),没关系我们再加一个顶点
vertices[3] = Vertex( 1.0f, -1.0f, -1.0f);
同时向量索引也要加上几句
indices[3] = 0; indices[4] = 2; indices[5] = 3;
//( 加三句?三个点当然要加三句了)
//其中indices[3]=0;的意思是第2个三角行的第0个顶点是在顶点向量的第0个值,就是vertices[0]的值.同理indices[4] = 2; 的意思是第2个三角行的第1个顶点是在顶点向量的第2个值,就是vertices[2]的值, 同理indices[5] = 3; 的意思是第2个三角行的第2个顶点是在顶点向量的第3个值,就是vertices[3]的值.那,这样两个三角形就定义好了
b) 下面就是我们真正的动画作图了(^_^ cover me其实还不能动)
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);设置FVF(Flexible Vertex Format 灵活的向量格式)
记得刚才有点东西没讲吗?对了就是那句Device->CreateVertexBuffer();
我们来看看它的参数
HRESULT CreateVertexBuffer(
UINT Length,//长度一般为n*sizeof(Vertex)n是你要建立的顶点的数量,程序中我设了n=4(四个点)
DWORD Usage,// D3DUSAGE_WRITEONLY
Informs the system that the application writes only to the vertex buffer. Using this flag enables the driver to choose the best memory location for efficient write operations and rendering. Attempts to read from a vertex buffer that is created with this capability will fail. Buffers created with D3DPOOL_DEFAULT that do not specify D3DUAGE_WRITEONLY might suffer a severe performance penalty(通知系统只能向顶点写模式,它要求必须选择最适合的内存单元,有效的提供给设备写操作和渲染。如果尝试失败就建立一个默认的模式)
DWORD FVF,//灵活向量模式
D3DPOOL Pool,//池管理类型D3DPOOL_MANAGED
IDirect3DVertexBuffer9** ppVertexBuffer,// 返回的顶点向量缓冲
HANDLE* pHandle//NULL
);
其中有一个参数要注意FVF这个参数的英文的意思是Flexible Vertex Format 灵活的向量格式为什么呢?大家有没有注意到第一个参数的sizeof(Vertex) Vertex类型,这个类型不是D3D的类型,是我们自定义的类型这个类型是这样的:
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;
里面有四个内容,_x,_y,_z, FVF.我们再看它的构造函数Vertex(float x, float y, float z)只构造了_x,_y,_z,而FVF是在外部定义的常量,说明FVF不是Vertex的有效使用数据,它只不过是一个描述信息罢了,那么是描述什么的呢?
我们建立了Vertex,并且又向D3D传递了这个参数,是不是应该告诉D3D该结构是什么样的格式呢?对了,FVF就是要告诉D3D这个信息,这里我们让FVF=D3DFVF_XYZ是说这个格式是由xyz三个定点的用户自定义格式。当然还有其他的格式比如说xyzRGB(r,g,b)三顶点和一个顶点颜色格式D3DFVF_XYZ|D3DFVF_DIFFUSE等等。你可以参考D3DFVF的MSDN信息
// Draw cube.
Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, //绘制类型
0,
0,
4, //顶点数量
0,
2);//三角形数量
请参阅MSDN 文档
Device->EndScene();
Device->Present(0, 0, 0, 0);
好了到此,我们这节的任务圆满完成了^_^看看源代码吧,我都有注释的
我得运行环境是VC7.1可能有的人打不开工程,没事你可以用VC6建立一个空的Windows项目将文件引入,RUN,OK!good luck!
申明:代码是引用Frank Luna他老人家的代码,我无意窜取他的劳动果实,只是懒得重新写代码所以拿来用一下。过后我会自己再写个比较复杂的,之所以用他老人家的代码是因为直接明了,没有那么多的类阿,模式啊什么的。代码中我会添加注释信息
下一节要讲(^_^),黑客帝国(Matrix) 什么不叫黑客帝国?叫矩阵?电影里说的啊,你问导演吧!