基于Directx的三维图形立体变换的实现.doc_第1页
基于Directx的三维图形立体变换的实现.doc_第2页
基于Directx的三维图形立体变换的实现.doc_第3页
基于Directx的三维图形立体变换的实现.doc_第4页
基于Directx的三维图形立体变换的实现.doc_第5页
已阅读5页,还剩52页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Q260046902 专业做论文 V西南科技大学毕业设计(论文)题目名称:基于Directx的三维图形立体变换的实现年 级:2003级 本科 专科学生学号:20035247学生姓名:宋彦宾 指导教师:蒋体钢学生单位:信息工程学院 技术职称:副研究员学生专业:通信专业 教师单位:信息工程学院西 南 科 技 大 学 教 务 处 制基于Directx的三维图形立体变换的实现摘要:目前在世界上三维图形大量的被应用到日常生活中,它是许多媒体应用程序和游戏的主体部分,所以掌握最新的三维技术是很有必要的。本文首先研究了利用C和Directx9编程以及立体几何技术,数学变换和几何图形技术来制作三维立体图形的方法,掌握了利用API接口创建窗口实现消息传递以及对坐标系,缓存,矩阵坐标变换的知识。其次,利用3DS Max创建三维立体图形,加载到所编写的三位图形立体变换程序中,并进行调试。设计主要完成了对绘制出来的电视机的平移,旋转和缩放技术的处理,最后通过程序对图形进行渲染使其更具有可观性。关键词:API;Visual C#.Net;Direct3D;3DS MaxThe Realization of ThreeDimensional Graph Three-Dimensional Transformation Based on DirectxAbstract:In the world of nowadays, the three -dimensional graphics are applying to daily life in a large number. It is the main part of the game and applications of many media. So, its necessary to master the latest 3-D technology.Firstly, this thesis researches on using C # and the Directx9 programming as well as the three-dimensional geometric technology, the mathematical manipulation and the geometric figure technology to manufacture the three-dimensional graphics. Mastering the use of the API interfaces to create a window that can realize message transmission. Acquainting the knowledge on the coordinate system, the texture and the matrix coordinate transformation. Secondly, the 3D models of the system were created by 3dsmax, then prepared to load the stereo 3D graphics transformation process, and debugging. The translation, the rotation and scaling of TV which have mapped out were completed in this design. Finally, by embroidering in procedure, the graphics were more arresting.Key words: API, Visual C#.Net, Direct3D, 3DS Max目 录第1章 绪论11.1 三维技术的现状11.2 编程语言简介21.3 三维图形立体变换的设计分析21.3.1 设计需求分析21.3.2 设计性能要求2第2章 DirectX9.0技术32.1 DirectX9.0的概念32.1.1 Direct3D的构架32.1.2 设计规划42.2 DirectX 9.0函数简介52.2.1 窗口类的处理62.2.2 创建IDirect3D接口72.2.3 创建IDirect3DDevice界面82.2.4 开始渲染92.2.5 顶点属性与顶点格式102.2.6 顶点缓冲102.2.7 索引缓冲122.2.8 D3D中的图元简介132.2.9 向量142.2.10 矩阵的操作15第3章 主体程序的设计与实现193.1 三维图形立体变换的设计193.2 三维图形立体变换设计具体实现193.2.1 利用.X文件图像获取193.2.2 利用画点画线函数生成图像233.2.3 图像的缩放333.2.4 图像的旋转343.2.5 图像保存为.TXT文挡373.2.6 渲染功能实现383.2.7 光源和观察矩阵的实现393.2.8 键盘的控制393.3 程序运行的调试40总结414.1 设计开发小结414.2 项目改进方向和未来展望41致谢42参考文献43附录44西南科技大学本科生毕业论文 第1章 绪 论1.1 三维技术的现状在计算机屏幕上绘图的最基本单位是点,点构成线,线又构成多边形,还可以朝空间发展,构成立体图行,如正方体、立方体、锥体、球等。用高级语言绘图的尝试基本就到此为止了,以为学过计算机图形学的人都知道,绘制真实的图形非常复杂,诸如着色、光照、运动等操作都涉及到大量的数学变换,没有高深的数学理论和高超的编程技巧是无法构建出漂亮的三维场景的10。不过,现在已经有大量的软件能够完成一些复杂的图形操作,如做平面设计的Photoshop,做三维立体设计的AutoCAD,做三维动画设计的3DS Max等。使用这些软件,可以比较容易地绘制出精彩的图形效果,只要有艺术细胞,就不怕作不出想要的效果。说到DirectX,大部分读者都会认为这是一个专门为图形服务的API(Application Program Interface)应用程序接口。实际上,DirectX是用途极为广泛的API,它并不局限于显示领域。目前的DirectX中包含有Direct Graphics(Direct 3D+Direct Draw)、Direct Input、Direct Play、Direct Sound、Direct Show、Direct Setup、Direct Media Objects等多个组件,它提供了一整套的多媒体接口方案。只是由于目前DirectX版本的更新主要在3D图形技术上,因此DirectX才给人一种图形API的感觉。DirectX是为游戏而诞生,而且伴随着不同版本的DirectX推出,就会有相应的显卡产品支持。从DirectX1.0到DirectX3.0,微软让它的DirectX开始在游戏领域树立起3D的标杆,尽管当时的3D很粗糙,但是雏形已初步形成,到DirectX7开始,随着OpenGL和Glide势力日渐衰弱,DirectX的霸气初现。DIRECT3D是Microsoft公司推出的三维图形编程API,它主要用于三维游戏的编程。众多优秀的三维游戏都是由这个接口实现的。与OpenGL一样,Direct3D的实现主要使用C+和C语言。DIRECT3D主要运用到现在众多的网络游戏中,越优越的网络游戏运用到DIRECT3D技术越先进。在我国由于国产大型网络游戏软件在质量、性能、可玩性等方面较国外品牌明显缺乏竞争力,目前,韩国和日本等国的游戏产品在我国网络游戏市场竞争中已占据主动。业者认为,无论从经济利益还是文化角度出发,我国都应尽快打破网络游戏产品主要依赖国外进口的被动局面,真正建立起研发、运营销售一条龙的产业链条,从根本上促进网络游戏产业的成熟。1.2 编程语言简介C#语言自C/C+演变而来。但是,它现代、简单、完全面向对象和类型安全。如果您是C/C+程序员,学习曲线将会很平坦。许多C#语句直接借用您所喜爱的语言,包括表达式和操作符。假如不仔细看,简直会把它当成C+。关于C#最重要的一点:它是现代的编程语言。它简化和现代化了C+在类、名字空间、方法重载和异常处理等领域。屏弃了C+的复杂性,使它更易用、更少出错。对C#的易用有贡献的是减少了C+的一些特性,不再有宏、模板和多重继承。特别对企业开发者来说,上述功能只会产生更多的麻烦而不是效益。使编程更方便的新功能是严格的类型安全、版本控制、垃圾收集(garbage collect)等等。所有的这些功能的目标都是瞄准了开发面向组件的软件。简单、现代、面向对象、类型安全、版本控制、兼容和灵活是C#至关重要的各种要素20。1.3 三维图形立体变换的设计分析近年来,3D世界飞速的发展。虚拟制造技术具有诱人的应用前景,促使发达国家对其进行深入研究,并已出现许多成功的应用范例。3D技术已逐渐作为人们生活的一个重要部分而融入在人们的日常生活当中去。这次毕业设计是要利用Directx 9.0和C#语言编程实现对三维立体图形的旋转,平移和缩放等操作,并能对立体图行进行渲染,光源设置以及保存成.txt文档。1.3.1 设计需求分析现今的社会,电脑已经落入千家万户。我们这个设计只需要一台支持Directx 9. 0电脑以及相关的软件就可以实现,相关软件有C#,3DS MAX, Directx SDK。1.3.2 设计性能要求(1)绘制出一个三维立体的电视机(2)实现对电视机的旋转,平移和缩放.(3)实现对.TXT文档的打开,显示和保存.(4)对绘制的电视机进行渲染和光源设置52第2章 DirectX9.0技术2.1 DirectX9.0的概念DrectX9. 0包括8个主要组件。其中,DirectPlav提供多人网络游戏的功能和方便快捷的网络数据交互;DirectMusic则为音乐音轨、MIDI或者其他由DirectMusic Producer创作的非音乐音轨提供一套完整的解决方案;DirectShow可以对媒体数据流进行高质量的采集与回放;Direct Setup能够实现DirectX组件的自动安装;DirectX Media Objects提供数据流对象的读写支持,包括视频和音频解码器及其效果。DirectSound用于播放和捕获音频波形的高性能音频应用软件的开发;DirectInput支持各种输入设备如键盘、鼠标、操作杆等,并且完全支持力反馈技术。DirectX Graphics组合了过去DirectX版木中的DirectDraw 和 Direct3D两个组件,使其成为一个适用于所有图形程序的独立的应用程序接口,并简化了图形编程任务。2002年底,微软发布DirectX9.0。DirectX 9中PS单元的渲染精度已达到浮点精度,传统的硬件T&L单元也被取消。全新的VertexShader(顶点着色引擎)编程将比以前复杂得多,新的VertexShader标准增加了流程控制,更多的常量,每个程序的着色指令增加到了1024条12。 PS 2.0具备完全可编程的架构,能对纹理效果即时演算、动态纹理贴图,还不占用显存,理论上对材质贴图的分辨率的精度提高无限多;另外PS1.4只能支持28个硬件指令,同时操作6个材质,而PS2.0却可以支持160个硬件指令,同时操作16个材质数量,新的高精度浮点数据规格可以使用多重纹理贴图,可操作的指令数可以任意长,电影级别的显示效果轻而易举的实现。 VS 2.0通过增加Vertex程序的灵活性,显著的提高了老版本(DirectX8)的VS性能,新的控制指令,可以用通用的程序代替以前专用的单独着色程序,效率提高许多倍;增加循环操作指令,减少工作时间,提高处理效率;扩展着色指令个数,从128个提升到256个。 增加对浮点数据的处理功能,以前只能对整数进行处理,这样提高渲染精度,使最终处理的色彩格式达到电影级别。突破了以前限制PC图形图象质量在数学上的精度障碍,它的每条渲染流水线都升级为128位浮点颜色,让游戏程序设计师们更容易更轻松的创造出更漂亮的效果,让程序员编程更容易。2.1.1 Direct3D的构架在Direct3D架构中有两个可编程部分:顶点转换器(vertex shade)和象素转换器(pixel shade)。顶点转换器在产生各种顶点组件数据前被调用,是作用在向量级别上的几何变换操作。象素转换器在图元绘制后调用,作用于象素点级别.图2-1是Direct3D架构的示意图。顶点缓冲把顶点数据注入顶点转换器中,顶点转换器用Direct3DX中定义的指令执行几何变换操作。流入顶点转换器的数据并非一定要包含在顶点缓冲中, 但这是一种理想情况。经过处理的顶点数据包含了位置、颜色、纹理坐标等数据,它们用DrawPrimitive方法绘制。这时,已绘制图元的每个象素点被传到象素转换器中,象素转换器同样使用Direct3DX中定义的指令执行象素操作。象素转换器的输入部分还包括相关的存放纹理数据的纹理表面。最后输出象素被传到帧缓冲中,为下一次页面翻转做准备。顶点缓冲向量0向量1向量2.顶点转换器位置颜色纹理坐标0纹理坐标1纹理坐标2图元操作象素转换器输出象素纹 理向量数据几何变换顶点组件象素操作图2-1 Direct3D的构架2.1.2 设计规划为了代码功能的可重用性,首先将3D数据图表封装在一个命名为DX Chart的ActiveX控件中。由于只是为了达到利用DirectX开发包进行3D图形开发应用的演示目的,这里只实现柱形图的显示。DX Chart控件在应用中属于应用程序界面的一部分,直接负责显示图表。应用程序只需提供给它一个包含图表数据的.csv文件,而由DXChart 控件去和复杂的DirectX组件打交道。对于应用程序来说,DirectX是不可见的。图2-2表示了DX Chart的运行逻辑。可以看到,控件在运行时能够调整多个外观属性,充分利用Direct3D的三维特性以展示图表数据,方便用户浏览和理解数据内容11。控件初始化获得当前路径,作为默认文件保存目录初始化属性值(FileName,BasckColor)FileName是否有效等待输入初始化DirecX读.CSV文件构造柱形图表输入 右键弹出菜单载入数据文件背景颜色恢复方向坐标面板自动旋转显示背景和图表左键拖放旋转图表显示标注信息键盘输入平移,缩放旋转视图关闭窗口销毁DrectX对象释放资源NY图2-2 DX chart控件运行过程流程图2.2 DirectX 9.0函数简介2.2.1 窗口类的处理(1)窗口类WNDCLASSstyle:用来定义窗口的行为。如果打算共同使用GDI和D3D的话,可以使用CS_OWNDC作为参数。lpfnWndProc:一个函数指针,指向与这个窗口类绑定在一起的处理窗口消息的函数。cbClsExtra和cbWndExtra:为窗口和为分配内存空间。很少使用到这两个参数,一般设为0;hInstance:应用程序的实例句柄。可以使用GetModuleHandle()来得到它,也可以从Win32程序的入口函数WinMain那里得到它。当然,也可以把它设为NULL(不知有什么用)hIcon,hCursor,hbrBackground:设置默认的图标、鼠标、背景颜色。不过在这里设置这些其实并不怎么重要,因为可以在后面定制自己的渲染方法。lpszMenuName:用来创建菜单18lpszClassName:窗口类的名字。可以通过这个名字来创建以这个窗口类为模板的窗口。甚至可以通过这个名字来得到窗口的句柄。设置好窗口类结构的内容后,使用RegisterClass(const WNDCLASS *lpWndClass)函数来注册它。关闭窗口后可以用UnregisterClass(LPCSTR lpClassName, HINSTANCE hInstance)来撤销注册。(2)创建窗口CreateWindowlpClassName:窗口类的名字。即窗口类结构体中的lpszClassName成员。lpWindowName:如果应用程序有标题栏,这个就是标题栏上显示的内容。dwStyle:窗口的风格决定你的窗口是否有标题栏、最大最小化按钮、窗口边框等属性。在全屏的模式下,WS_POPUP|WS_VISIBLE是常用的设置,因为它产生一个不带任何东西的全屏窗口。在窗口的模式下,可以设置很多窗口的风格,这里不详细说明,不过WS_OVERLAPPED|WS_SYSMENU|WS_VISIBLE是一组常用的风格。x和y:窗口创建的位置。(x,y)表示窗口的左上角位置。nWidth和nHeight:用来设置窗口的宽度和高度,以像素为单位。如果想创建一个全屏的窗口,使用GetSystemMetrics(SM_CXSCREEN)和GetSystemMetrics(SM_CYSCREEN)可以得到当前显示器屏幕的大小hWndParent:指定这个新建窗口的父窗口。在D3D应用程序中很少用,一般设为NULLhMenu:菜单句柄。hInstance:应用程序的实例句柄。可以使用GetModuleHandle()来得到它,也可以从Win32程序的入口函数WinMain那里得到它。当然,也可以把它设为NULL(不知有什么用)lpParam:一个很神秘的参数。除非知道自己在做什么,否则还是把它设为NULL吧。(3)窗口消息处理过程窗口消息的处理函数是一个回调函数,回调函数就是由操作系统负责调用的函数。CALLBACK这个宏其实就是_stdcall,这是一种函数调用的方式,在这里不多说这些了,有兴趣的可以参考一些Windows编程的书籍,里面会有很详尽的说明。Windows里面有很多消息都是在自己的消息队列里等候。通过GetMessage和PeekMessage这两个函数使消息从队列里出去。队列出去的消息消息就正式进入了窗口消息处理过程,也即是窗口类中lpfnWndProc所指定的函数。一个消息处理函数有四个参数,下面分别说说:参数1:HWND p_hWnd一个窗口类是可以产生多个窗口的,如果一个应用程序里面有多个窗口,并且它们之中的一些窗口是共用一个窗口类的,那么就得用一个窗口句柄来指明究竟这个消息是哪个窗口发过来的。参数2:UINT p_msg这是一个消息类型,就是WM_KEYDOWN,WM_CLOSE,WM_TIMER这些。参数3:WPARAM p_wparam这个参数内容就是消息的主要内容。如果是WM_KEYDOWN消息,那么p_wparam就是用来告诉你究竟是哪个键被按下。参数4:LPARAM p_lparam这个参数的内容一般是消息的一些附加内容。最后说明一下DefWindowProc的作用。有时候把一个消息传到窗口消息处理函数里面,但是里面没有处理这个消息的内容。交给DefWindowProc处理就对了。2.2.2 创建IDirect3D接口DirectX是一组COM组件,COM是一种二进制标准,每一个COM里面提供了至少一个接口,而接口就是一组相关的函数,使用DirectX,其实就是使用那些函数。COM和C+中的类有点像,只不过COM使用自己的方法来创建实例。创建COM实例的一般方法是使用coCreateInstance函数。有关coCreateInstance的使用方法,可以参考有关COM方面的资料,这里暂时不详细说明了,因为DirectX提供了更简洁的方法来创建DirectX组件的实例。这里要讲的就是Direct3D组件的使用方法。为了使用D3D中的函数,要先定义一个指向IDirect3D9这个接口的指针,顺便说明一下为什么要定义这个指针。首先,要知道接口的内容就是一些纯虚拟函数,所以接口是不能被实例化的,但是可以定义一个指向接口的指针。其次,要知道利用多态性可以使用一个基类指针来访问派生类中的方法。既然接口是不能被实例化的,那么肯定是使用从接口派生出来的类(或结构)的方法怎么获到这个派生类的就是通过之前定义的接口指针(也即是基类指针)来获得。所需做的就是把一个接口指针的地址传给某个函数,让这个函数来帮助获到正确的派生类指针,这样就可以使用接口指针来做一些实际的东西了。实际上,只需要知道接口里面有什么方法以及它能完成什么工作就行了,至于这些方法是怎么实现的不必去关心。要做的就是定义一个接口指针,把它传给某个函数,函数使接口指针有意义,接着使用接口,就这么简单。定义完这个接口指针后,例如IDirect3D9 *g_pD3D;现在使用Direct3DCreate9这个函数来创建一个D3D接口:g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );Direct3DCreate9这个函数只有一个参数,它表明要创建接口的版本。创建接口后就可以创建D3D设备了。创建D3D设备需要的参数很多,如果把那些参数都挤在一个函数里面,那就太长了,所以就把一些参数放进结构体里面,只要先设定好这些结构体,再把这些结构体当作参数传给创建D3D设备的函数,那就清晰多了。2.2.3 创建IDirect3DDevice界面当把D3DPRESENT_PARAMETERS的参数都设置好后,就可以创建一个D3D设备了,和创建D3D接口一样,先定义一个接口指针IDirect3DDevice9 * g_pD3DDevice;然后使用D3D接口里面的CreateDevice函数来创建设备。CreateDevice的声明为:HRESULT CreatDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS *pPresentationParameters,IDirect3DDevice9* ppReturnedDeviceInterface;第一个参数说明要为哪个设备创建设备指标,一台机可以有好几个显卡,这个参数就是要指明为哪块显卡创建可以代表它的设备指标。显卡的编号可以使用D3D接口里面的函数来获得,例如GetAdapterCounter可以知道系统有几块显卡;GetAdapterIdentifier可以知道显卡的具体属性。一般设这个参数为D3DADAPTER_DEFAULT22。第二个参数指明正在使用设备类型。一般设为D3DEVTYPE_HAL。第三个参数指明要渲染的窗口。如果为全屏模式,则一定要设为主窗口。第四个参数是一些标记,可以指定用什么方式来处理顶点。第五个参数就要用到上面所讲的D3DPRESENT_PARAMETERS。第六个参数是返回的界面指针。2.2.4 开始渲染有了设备接口指针,就可以开始渲染画面了。渲染是一个连续不断的过程,所以必定要在一个循环中完成,没错,就是前面讲的那个消息循环。在渲染开始之前要用IDirect3DDevice9:Clear函数来清除后备缓冲区。HRESULT Clear(DWORD Count,const D3DRECT *pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil);Count:说明要清空的矩形数目。如果要清空的是整个客户区窗口,则设为0;pRects:这是一个D3DRECT结构体的一个数组,如果count中设为5,则这个数组中就得有5个元素。它可以只清除屏幕中的某一部分。Flags:一些标记组合,它指定要清除的目标缓冲区。只有三种标记:D3DCLEAR_STENCIL , D3DCLEAR_TARGET , D3DCLEAR_ZBUFFER。 分别为清除模板缓冲区、清除目标缓冲区(通常为后备缓冲区)、清除深度缓冲区。Color:清除目标区域所使用的颜色。float:设置Z缓冲的Z初始值。小于或等于这个Z初始值的Z值才会被改写,但它的值只能取0到1之间。Stencil:设置范本缓冲的初始值。它的取值范围是0到2的n次方减1。其中n是范本缓冲的深度。清除后备缓冲区后,就可以对它进行渲染了。渲染完毕,使用Present函数来把后备缓冲区的内容显示到屏幕上。2.2.5 顶点属性与顶点格式顶点可谓是3D世界中的基本元素。在计算机所能描绘的3D世界中,任何物体都是由多边形构成的,可以是三边形,也可以是四边形等。由于三边形,即三角形所具有的特殊性质决定其在3D世界中得到广泛的使用。构成三角形需要三个点。 定义完了顶点的结构后,就要告诉D3D我们定义的是什么格式。为了方便,通常会用#define来定义一个叫做描述“灵活顶点格式”(FVF:Flexible Vertex Format)的宏。例如:#define MYFVF D3DFVF_XYZ | D3DFVF_NORMAL。根据之前定义的顶点属性结构体,要定义相对应的宏。假如顶点结构中有位置属性,那么就要使用D3DFVF_XYZ;如果是变换顶点的话,就要使用D3DFVF_XYZRHW;如果使用了漫反射色属性的话,就要使用D3DFVF_DIFFUSE。这些值是可以组合使用的,像上面那样用“|”符号作为连结符。定义完灵活顶点格式后,使用IDirect3DDevice9:SetFVF函数来告诉D3D所定义的顶点格式,例如:g_pD3DDevice-SetFVF( MYFVF );2.2.6 顶点缓冲处理顶点信息的地方有两个,一个是在数组里,另一个是在D3D所定义的顶点缓冲里。也就是一个在所能直接操作的内存里,另一个在D3D管理的内存里。对于我们这些对操作系统底层了解不多的人来说,直接操作内存实在是太难了,所以还是交给D3D帮助处理,虽然不知道背后有些什么操作。要想把顶点信息交给D3D处理,就要先创建一个顶点缓冲区,可以使用IDirect3DDevice9-CreateVertexBuffer,它的原型是:HRESULT CreateVertexBuffer(UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9* ppVertexBuffer,HANDLE* pSharedHandle);Length:缓冲区的长度。通常是顶点数目乘以顶点大小,使用Sizeof( MYVERTEX )就可以知道顶点的大小了。Usage:高级应用。设为0就可以了。FVF:就是之前定义的灵活顶点格式。Pool:告诉D3D将顶点缓冲存储在内存中的哪个位置。高级应用,通常可取的三个值是:D3DPOOL_DEFAULT,D3DPOOL_MANAGED,D3DPOOL_SYSTEMMEM。多数情况下使用D3DPOOL_DEFAULT就可以了。ppVertexBuffer:返回来的指向IDirect3DVertexBuffer9的指针。之后对顶点缓冲进行的操作就是通过这个指针。到这里还要再提醒一下,对于这些接口指针,在使用完毕后,一定要使用Release来释放它。pSharedHandle:设为NULL就行了。得到一个指向IDirect3DVertexBuffer9的指针后,顶点缓冲也就创建完毕了。现在要做的就是把之前保存在数组中的顶点信息放在顶点缓冲区里面。首先,使用IDirect3DVertexBuffer9:Lock来锁定顶点缓冲区:HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void *ppbData,DWORD Flags);OffsetToLock:指定要开始锁定的缓冲区的位置。通常在起始位置0开始锁定。SizeToLock:指定在锁定的缓冲区的大小。设为0的话就是表示要锁定整个缓冲区。ppbData:用来保存返回的指向顶点缓冲区的指针。通过这个指针来向顶点缓冲区填充数据。Flags:高级应用。通常设为0。填充为顶点缓冲区后,使用IDirect3DDevice9:Unlock来解锁。最后在渲染的时候使用IDirect3DDevice9:SetStreamSource来告诉D3D要渲染哪个顶点缓冲区里面的顶点。HRESULT SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9 *pStreamData,UINT OffsetInBytes,UINT Stride);StreamNumber:设置数据流的数量。顶点缓冲最多可以使用16个数据流。确定所支持的数据流的数量,可以检查D3DCAPS中的MaxStreams成员的值。通常设为0,表示使用单数据流21。pStreamData:要与数据流绑定的数据。在这里要把顶点缓冲区与数据流绑定。OffsetInBytes:设置从哪个位置开始读数据。设为0表示从头读起。Stride:数据流里面数据单元的大小。在这里是每个顶点的大小。2.2.7 索引缓冲很多时候,相邻的三角形会共用一些顶点,例如组成四方形的两个三角形就共用了一条边,即共用了两个顶点信息。如果不使用索引,需要六个顶点的信息来绘制这个四方形,但实际上绘制一个四方形只要四个顶点信息就足够了。如果使用了索引就不一样了,在顶点缓冲区里可以只保存四个顶点的信息,然后通过索引来读取顶点信息。要使用索引得先创建一个索引缓冲。创建索引缓冲的函数是:IDirect3DDevice9:CreateIndexBufferHRESULT CreateIndexBuffer(UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9* ppIndexBuffer);Length:索引缓冲区的长度。通常使用索引数目乘以sizeof(WORD)或sizeof(DWORD)来设置,因为索引号的数据类型是字节(WORD)或双字节(DWORD),一个WORD只有两个字节,DWORD也就只有四个字节,比顶点的大小要小很多。Usage:和CreateVertexBuffer中的Usage设置一样。一般设为0。Format:设置索引格式。不是D3DFMT_INDEX16就是D3DFMT_INDEX32。Pool:又是和CreateVertexBuffer中的一样。一般设为D3DPOOL_DEFAULT。ppIndexBuffer:指向IDirect3DIndexBuffer9的指针。操作索引缓冲区就靠它。记得使用完后要Release。和填充顶点缓冲区一样,要填充索引缓冲区,要先使用IDirect3DIndexBuffer9:Lock来锁定缓冲区。HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void *ppbData,DWORD Flags);和IDirect3DVertexBuffer9:Lock一样的,填充完之后使用IDirect3DIndexBuffer9:UnLock来解锁。最后使用IDirect3DDevice9:SetIndices来告诉设备要使用哪个索引。HRESULT Setindices(IDirect3DindexBuffer9* pIndexData,UINT BaseVertexIndex);pIndexData:设置使用哪个索引缓冲。BaseVertexIndex:设置以顶点缓冲区中的哪个顶点为索引0。2.2.8 D3D中的图元简介在D3D中,一共有三种基本图元,分别是点、线和三角形。点是最简单的图元,由它可以构成一种叫点列(point list)的图元类型。线是由两个不重合的点构成的,一些不相连的线组成的集合就叫线列(line list),而一些首尾相连但不形成环路的线的集合就叫线带(line strips)。同理,单独的三角形集合就叫三角形列(triangle list),类似于线带的三角形集合就叫三角形带(triangle strips),另外,如果多个三角形共用一个顶点作为它们的一个顶点的话,那么这个集合就叫三角形扇(triangle fans)。基本上我们可以使用这些图元来画我们想要的任何物体。例如画一个四方形可以使用三角形带来画,画一个圆则使用三角形扇。2.2.9 向量向量就是包含大小(长度)和方向的一个量。向量有2维的,也有3维甚至4维的。在DX的所有结构体中,有一个结构体是用来表示3维向量的,它就是D3DVECTOR,这个结构体很简单,只有三个成员:x、y、z。一般来说,如果不涉及到向量运算的话,用这个结构体来定义一个向量就可以了。它可以用来表示方向以及顶点在3D世界中的位置等。如果要对那些向量进行一些运算的话,使用D3DVECTOR就很不方便了,因为在D3DVECTOR这个结构体中没有重载任何的运算符,如果想要做一个加法运算,就得分别对结构体中的每一个成员进行运算了。在DX里面有个叫D3DX的文件(包含d3dx.h头文件),它里面定义了很多方便我们进行数学计算的函数和结构。其中就有D3DXVECTOR2,D3DXVECTOR3,D3DXVECTOR4这三个结构体。看它们的名字就应该知道它们的作用了。对于2维和4维的结构体这里就不做了解了,其实它们也很简单,和D3DXVECTOR3差不多。不过要说明一点的是D3DXVECTOR3是从D3DVECTOR派生过来的,说明它和D3DVECTOR一样,有x、y、z这三个成员,除此之外,D3DXVECTOR3还重载了小部分算术运算符,这样就可以对D3DXVECTOR3的对象进行加减乘除以及判断是否相等的运算了。同时,由于D3DXVECTOR3是从D3DVECTOR派生过来的,所以两者的对象可以互相赋值,在这两种类型中随便转换。D3DX中有很多很有用的函数,它们可以帮助所需的运算。下面了解和D3DXVECTOR3有关的函数:计算点乘:FLOAT D3DXVec3Dot(CONST D3DXVECTOR3* pV1,CONST D3DXVECTOR3* pV2) 计算叉乘:D3DXVECTOR3* D3DXVec3Cross(D3DXVECTOR3* pOut,CONST D3DXVECTOR3* pV1,CONST D3DXVECTOR3* pV2) 计算模:FLOAT D3DXVec3Length(CONST D3DXVECTOR3* pV)标准化向量:D3DXVECTOR3* D3DXVec3Normalize(D3DXVECTOR3* pOut,CONST D3DXVECTOR3 pV)对于D3DXVECTOR3的加减乘除运算,上面已经讲了,用+ - * / 就行了。2.2.10 矩阵的操作(1)矩阵与矩阵运算在D3D中,定义矩阵的结构体是D3DMATRIX:typedef struct _D3DMATRIX union struct float _11, _12, _13, _14;float _21, _22, _23, _24;float _31, _32, _33, _34;float _41, _42, _43, _44;float m44; D3DMATRIX;看这个结构的样子,就应该很清楚怎么使用它来定义一个矩阵了。实际上直接使用D3DMATRIX的情况不多,因为在D3DX中有个更好的结构体,那就是D3DXMATRIX。和D3DXVECTOR3相似,D3DXMATRIX是从D3DMATRIX继承过来的,它重载了很多运算符,使得矩阵的运算很简单。矩阵的运算方法这里就不做过多介绍了,下面只介绍和矩阵性质有关的三个函数。产生一个单位矩阵:D3DXMATRIX *D3DXMatrixIdentity(D3DXMATRIX *pout);/返回结果求转置矩阵:D3DXMATRIX *D3DXMatrixTranspose(D3DXMATRIX *pOut,/返回的结果CONST D3DXMATRIX *pM );/目标矩阵求逆矩阵:D3DXMATRIX *D3DXMatrixInverse(D3DXMATRIX *pOut,/返回的结果FLOAT *pDeterminant,/设为0CONST D3DXMATRIX *pM );/目标矩阵(2)矩阵变换矩阵的基本变换有三种:平移,旋转和缩放。平移:D3DXMATRIX *D3DXMatrixTranslation(D3DXMATRIX* pOut,/返回的结果FLOAT x, /X轴上的平移量FLOAT y, /Y轴上的平移量FLOAT z) /Z轴上的平移量绕X轴旋转:D3DXMATRIX *D3DXMatrixRotationX(D3DXMATRIX* pOut, /返回的结果FLOAT Angle /旋转的弧度);绕Y轴旋转:D3DXMATRIX *D3DXMatrixRotationY(D3DXMATRIX* pOut, /返回的结果FLOAT Angle /旋转的弧度);绕Z轴旋转:D3DXMATRIX *D3DXMatrixRotationZ(D3DXMATRIX* pOut, /返回的结果FLOAT Angle /旋转的弧度);绕指定轴旋转:D3DXMATRIX *D3DXMatrixRotationAxis( D3DXMATRIX *pOut,/返回的结果CONST D3DXVECTOR3 *pV,/指定轴的向量FLOAT Angle/旋转的弧度);缩放:D3DXMATRIX *D3DXMatrixScaling(D3DXMATRIX* pOut, /返回的结果FLOAT sx, /X轴上缩放的量FLOAT sy, /Y轴上缩放的量FLOAT sz /Z轴上缩放的量);(3)世界空间与世界矩阵每个模型(3D物体)都有它自己的空间,空间的中心(原点)就是模型的中心。在模型空间里,只有模型上的不同点有位置的相对关系。世界空间就是物体(模型)所存在的地方。当把一个模型放进世界里面去,那么它就有了一个世界坐标,这个世界坐标是用来标记世界中不同的模型所处的位置的。在世界空间里,世界的中心就是原点(0, 0, 0),也就是显示器屏幕中间的那一点。可以在世界空间里摆放很多个模型,并且设置它们在世界空间中的坐标,这样模型与模型之间就有了相对的位置。可以通过利用世界矩阵来改变世界空间的坐标。这样,在世界空间里面的模型就可以移动、旋转和缩放了。(4)视图空间与视图矩阵世界空间建立起来后,不一定能看到模型,因为还没有“眼睛”。在视图空间里,可以建立在三维空间中的眼睛:摄像机。就是通过这个虚拟的摄像机来观察世界空间中的模型的。所以视图空间也叫摄像机空间。要建立起这个虚拟的摄像机,需要一个视图矩阵,产生视图矩阵的一个函数是: D3DXMATRIX *D3DXMatrixLookAtLH(D3DXMATRIX* pOut,CONST D3DXVECTOR3* pEye, CONST D3DXVECTOR3* pAt,CONST D3DXVECTOR3* pUp );pOut:返回的视图矩阵指针pEye:设置摄像机的位置pAt:设置摄像机的观察点pUp:设置方向“上”这个函数的后缀LH是表示左手系的意思,既然有了左手系一定能够猜出肯定有个叫D3DXMatrixLookAtRH的函数。至于左手系和右手系的区别,这里就不多说了,记住左手系中的Z正方向是指向显示器里面的就行了。视图矩阵其实就是定义了摄像机在世界空间中的位置、观察点、方向“上”这些信息。第3章 主体程序的设计与实现3.1 三维图形立体变换的设计在进行结构设计中,根据现代软件工程特点,重点考虑了以下原则:1易于扩充:基于服务提供者接口框架,功能易于扩充;安全性:在设计安全系统时,安全性是最基本的原则。安全性原则应覆盖系统设计、实现和部署的全过程。兼容性:按照标准规范进行设计和实现,确保系统兼容性。模块化:各功能模块独立,通过接口进行交互。以下就是本设计的工作流程图:控件的初始化电视机的绘制.X文件的引用图像的处理(矩阵变换)光源的设置图像的保存程序的调试图3-1 工作流程图3.2 三维图形立体变换设计具体实现3.2.1 利用.X文件图像获取图像获取是图像处理的先决条件,它主要有以下几个步骤实现:2(1)设备驱动与窗体连接要使用DX,那么第一件事情就是建

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论