大学毕业设计论文3D引擎设计VC++.docx
- 文档编号:29171721
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:43
- 大小:82.66KB
大学毕业设计论文3D引擎设计VC++.docx
《大学毕业设计论文3D引擎设计VC++.docx》由会员分享,可在线阅读,更多相关《大学毕业设计论文3D引擎设计VC++.docx(43页珍藏版)》请在冰豆网上搜索。
大学毕业设计论文3D引擎设计VC++
3D引擎设计
摘要
本文应用面向对象设计方法,开发一个实时渲染的图形引擎框架结构。
在结构中主要使用OpenGL函数接口,此结构也适用于Direct3D。
使用设计模,对框架进行抽象,分成以下子系统:
数学系统,核心系统,平台支持系统。
对于数学系统主要提供在渲染过程中需要用到的数学,和线性代数。
例如:
向量,矩阵等。
核心系统是整个结构的核心,消息处理,当前帧的渲染都在核心系统中,它负责调节,调用和维护其他的子系统。
平台支持,主要考虑到可能的夸平台原因而抽象出来的一层,为将来使用。
从比较低的级别上来看,图形引擎负责描绘对观察者可见的物体。
典型的就是使用图形API,例如:
OpenGL、Direct3D来进行渲染,描画相应的物体。
从比较高的级别上来看,引擎主要是封装了一些固定的算法,对场景的组织和对底层的隔离,让使用此框架进行应用开的开发人员不必考虑底层的细节问题。
本系统在Windows平台上使用VC++进行开发。
关键词3D引擎结构;场景组织;四叉树;动态细节度控制
Abstract
Thispaperusesobject-orientedmethodtodesigna3Dgraphicenginearchitectureforrealtimerendering.InthisframeworkmajoruseOpenGLAPI.ButtheidealapplyequallyaswellasDirect3D.Usedesignpatterntoabstractthestructureanddivideintosuchsubsystems:
Mathematicsubsystem,Coresubsystem、Platformsupplysubsystem.FortheMathematicsubsystem.themajorresponsibilityistoprovidetherequireofmathematicandlinearalgebra.Suchasvector;matrixetc.Coresubsystemisthecoreofthewholeframework,messageprocess,rendercurrentframeareallinthissubsystem.Ittakeresponsibilityforadjustment,schedulingandmaintainothersubsystems.Platformsupplysubsystemisinconsideringofboastplatformforthefuture.Atlow-level,agraphicsenginehastheresponsibilitytodrawtheobjectsthatarevisibletoanobserver.TypicallyusesagraphicsAPIsuchasOpenGLorDirect3Dtoimplementarendererwhosejobitistocorrectlydrawtheobjects.Athigh-level,agraphicsengineencapsulationssomealgorithm,organizescene,separatethedetailfromlowlevel,Letapplicationprogrammerswhousethisenginewithoutregardforthelowleveldetail.ExamplewithrenderAPItouse,developonwhichplatform,howtoorganizesceneandsomeimplicitalgorithm.ThissystemintheWindowsplatformusingVC++fordevelopment.
Keywords3Dengine;architecture;sceneorganize;quaternarytree;dynamicdetailcontrol
第1章绪论
1.1选题背景及目的
在上世纪90年代以前,电子游戏和图形程序的制作业还没有引擎这一概念,所有厂商在制作游戏和图形程序的时候都是以小组团队甚至是个人形势来独立制作图形程序,通过用各种编程语言来编写程序。
相对于使用引擎来制作图形程序,这种方式较为复杂跟繁琐,需要图形程序创作者花费很多时间。
但至今仍有许多业余的图形程序开发者或者部分游戏厂商在使用这种非引擎制作方式来设计制作图形程序。
制作者可以利用C,VC或者其他语言的环境下通过OpenGL或者DX的接口形式来表现图形程序。
由于在实际开放中的对时间的要求,以及时间对开发成本的影响.越来越需要程序能够拥有最大的复用性,和通用性。
复用性表现在,当需要开发类似功能的相关产品时,能够沿用以前的开发成果,或部分,或全部。
这需要程序有良好的结构。
通用性表现在,某一算法或程序应该不完全依赖于某个特定的数据类型或结构,C++中的STL就是一个例子,它把算法和数据类型进行了脱离,。
提高了通用性。
3D引擎是对图形图像编程中一些固定算法和结构的汇总,它好比一个大型的库(LIB),让图形图像程序的开发人员能够把更多的经历放在如何去表现图形上,而不必去考虑一些数据组织和算法的问题。
这样可以大大节省了开发的时间周期,提高开发的效率。
1.2课题研究的内容
首先给出wiki百科上对于引擎的定义:
引擎是电子游戏或者其他交互式实时图像应用程序的核心软件组件,它提供游戏运行的底层技术,简化了图形程序的开发过程,支持多种硬件平台和操作系统,包括游戏主机和运行Linux、MacOSX或Windows的桌面系统。
它主要包含以下功能模块:
二维或三维渲染引擎(即渲染器)、物理引擎、碰撞检测(碰撞响应)、声音、脚本、动画、人工智能、网络、流(steaming)、内存管理、线程以及场景组织。
引擎代表了所有图形程序的技术。
因此引擎可以重复使用,从而制作出不同的图形程序。
图形程序与引擎的关系就像一辆汽车和它的发动机,没有发动机,汽车自然动不了,但我们可以把发动机卸下来放到另一个新的车体内,就变成了另一辆车。
简单说,引擎就是一种工具软件,性质和Word一样,只不过我们用Word来写文章,用引擎来开发图形程序。
第2章概要设计
2.1系统整体结构描述
系统主要分为三个模块,引擎核心依赖于其他两相互独立的模块。
模块之间的依赖关系多少,直接决定了以后直接复用的可能,模块的功能要尽量的单一化,这里的数学子模块,和平台支持子模块是不依赖于引擎核的,在将来可能的需要中可以直接抽出单独的使用。
图2.1是系统整体结构图。
图2.1系统整体结构图
系统核心,是整个引擎的核心所在,整个消息的处理和场景的渲染都在这个模块中,所以相对其他两个模块来说他也是比较复杂的,他要负责管理其他两个模块的创建和销毁。
数学子模块,主要是实现一些在图形渲染中要用到的向量,矩阵,以及他们之间的运算,例如向量之间的点积、叉乘、矩阵和向量的积、矩阵的逆等。
对于3D程序数学子模块是必不可少的,因为整个3D系统都是建立在数学模型之上的,当然数学系统的好坏对整个系统据有很大的影响。
平台支持,主要是对不同平台提供的类似或相同的服务抽象一层统一的接口,因为你不可能要求LINUX和WINDOWS的系统API有相同的名字或参数。
有了这一层引擎的核心结构就能保持固定,不至于在支持新平台的时候重新修改整个引擎的相关函数。
2.2各个子模块描述
各个子模块在系统中相对独立,并且拥有自己的功能。
2.2.1数学子系统
数学子系统主要实现包括如下类,他们之间没有任何继承关系,只是为了表达数学符号,和特定的数学运算。
Vector2,Vector3,Vector4,Matrix2,Matrix3,Matrix4,Color,Plane,Quaternion
他们依次分别表示:
二元向量(或二维坐标),三元向量,四元向量,二阶矩阵,三阶矩阵,四阶矩阵,颜色,平面(Ax+By+Cz=D,保存A,B,C,D),四元数,几乎每一个数学类都重载了io操作,以便调试程序,检查是否正确,每个成员函数都使用inline修饰,以减少在调用他们时对栈的使用。
因为他们是工作在最底层的,几乎每一次变换都离不开调用数学库中的相关函数,使用inline也会整加目标应用程序的大小。
二元向量(或二位坐标),主要是用在纹理坐标的表示上,他重载了运算符+,=,*,/以及[](数组访问),方便调用者使用。
三元向量(或三维坐标),它是系统中使用最频繁的,主要用来表示系统中的点或是法线,相应的也重在了很多数学运算操作,比较重要的几个函数是单位化,点乘和叉乘。
四元向量,它有个特殊的分量w,在w为0时表示的是向量,在w为1时表示的是点,这主要是它对四阶矩阵右乘时表现出来的线性特性。
矩阵是3D引擎中最重要的一个数学符号,所有的坐标变换都是基于矩阵进行的。
二阶矩阵,在3D引擎中还是比较少的用到它,但是在只有屏幕坐标(二维X,Y)时会使用它。
三阶矩阵,使用最频繁的矩阵,坐标变换中的旋转和缩放都要使用到它。
这里重载了一些常规的运算符操作,以及转置,求逆矩阵和伴随矩阵等数学运算。
最重要是对旋转的支持,以及从旋转矩阵中(如果是)提取出相应的轴向量和旋转角度(逆时针为正),为了方便是使用还提供了欧拉角(旋转大于90度是会有问题)。
四阶矩阵,主要是为了对应3DAPI中使用的矩阵。
颜色,图形图像中少不了的元素,封装了一些简单的缩放和截取操作。
平面,使用方程AX+BY+CZ=D来表示一个平面,在这个类中的主要作用是在错裁剪时可以用来判断一个物体是否在可是的范围之内。
四元数(Quaternion)表示一个四元的量,它与Vector4不同,他表示的是复数的坐标,在它被单位化以后可以表示一个轴和绕这个轴旋转的角度,因为他在很多方面比较优秀所以常常代替矩阵来表示旋转,常在骨骼动画中进行插值使用,所以他封装了一些插值接口。
数学子模块中各个类的结构单一,没有任何依赖的关系,他们只是对特定的数学运算和数学符号的抽象。
2.2.2平台支持
平台依赖主要功能是实现对各个平台的支持,隔离平台之间的差异,使他的上一层(引擎核心)能够得到统一的结构,而不必去考虑这些差异。
主要类如下:
GLRender,CPlatform,CW32Window,CMsgProcesse,CWin32MsgProcesser
这个模块中还有其他很多类,但最主要的是5个类。
GLRender是对OpenGL在接口的封装,同理也可以对Direct3D进行封装。
这个类继承自引擎核心的CRender,GLRender是对CRender的OpenGL实现。
CPlatform是对系统平台的抽象,向上提供支持和系统服务并且统一接口,例如创建窗口,消息处理等等。
CMsgProcesser是一个消息处理类,抽象他的主要原因是,用户可能需要自己拦截和处理一些特定的消息,当然它是所有特定平台消息处理器的基类,CWin32MsgProcesser就是Windows平台的实现,他实现的是在Windows平台上消息的提取和分发处理。
最主要的是这里的消息映射机制,通过模仿MFC的消息映射宏产生一个消息映射链,以使得继承自这个类的所有子类可以对消息进行处理,并且可以把一些不关心的消息交给父类去处理。
2.2.3引擎核心
引擎核心模块是整个引擎的核心所在,从职责上来看,一个图形引擎就是要把给定的数据以特定的方法描画出来,这些主要数据包括,图形数据(点,和纹理)和空间数据(在何处描画)。
为了提高渲染的效率,我们首先应该对数据进行良好的组织,其次是分离出描绘部分,因为描绘的方法是变化的我们应该把具有相同描绘方法的归在一起,以提高渲染的效率。
主要类如下:
CSpatial,CRender,CNode,CQuadSquare,CGlobalState,CCamera,CRenderTarget,CGeometry,CEffec,CEngineCore
CSpatial是对空间位置的抽象,是那些需要空间位置的类的基类。
CRender是特定图形API结构的基类,对引擎核提统一的接口,隔离不同图形API的差异。
CNode是场景组织树,使用他来组织场景。
CQuadSquare四叉树,场景组织树的另一种,使用它来组织场景。
CGlobalState全局状态,他将影响到物体的描画。
CCamera镜头类,好比在拍电影中是用到的摄像机。
CRenderTarget渲染目标,是渲染结果的接受者,好比胶片。
CGeometry图形类,是被渲染的物体的数据集合所在,他包括点,法线,纹理坐标,应用在此图形上的灯光,特效(描绘方法)。
CEffect描绘方法,在渲染一个物体是,我们不能保证所有的物体都使用同样的方法去描绘,有的可能需要多个纹理,有的可能需要多个通道(Pass)。
最好的办法就是对变化的事物进行封装。
CEngineCore引擎的核心,他负责整个引擎的初始化和逆初始化,系统通过他为用户提供服务。
第3章类之间的继承和调用关系
3.1主要类之间的继承关系
CSpatial是个抽象类,他提供了一套更新函数接口,和表示位置信息的成员变量,还有一个指向父结点的指针,所有需要这些特性的类都应继承自它。
图3.1和3.2是类之间的继承关系图。
图3.1引擎核心继承关系图
图3.2平台支持继承关系图
3.2主要调用关系描述
首先系统启动,进入main(或WinMain)函数,在main(或WinMain)中实例化一个应用程序类EigineApp,在这个类中首先会初始化场景,并对引擎的状态进行设置,在这里用户可以创建自己的场景,设置渲染状态。
完成初始化后控制权交给CEngineCore类,进行消息处理和渲染大循环。
消息处理:
用户可以在EigineApp初始话时指定消息处理器(CMsgProcesser类的子类),来拦截自己感兴趣的消息。
在大循环中CEngineCore,首先会要求CPlatform类对消息进行处理,CPlatform类从自己的消息队列中抽出消息,封装好后交给指定的消息处理器进行消息处理,这样就来到了用户设定的消息处理器中。
渲染:
CEngineCore遍历所有的渲染目标,得到渲染目标对应的镜头(CCamera),通过这个CCamera设置CRender的镜头,再以这个镜头对场景树进行不可见剔除,并收集可见物体的渲染状态形成渲染队列,设置CRender渲染的队列,并要求CRender渲染,最后把渲染得到的结果放到指定的位置(纹理中或屏幕上)。
第4章详细设计
4.1数学子系统
对数学,和线性代数中一些特定符号,操作的表示和实现。
4.1.1向量
类的定义,和主要成员变量:
classVector3{
public:
union{
struct
{
Realm_fX,m_fY,m_fZ;
};
Realm_fVal[3];
};
…………………………….
staticconstVector3ZERO;//0点
staticconstVector3UNIT_X;//坐标(1,0,0)
staticconstVector3UNIT_Y;//坐标(0,1,0)
staticconstVector3UNIT_Z;//坐标(0,0,1)
staticconstVector3NEGATIVE_UNIT_X;//坐标(-1,0,0)
staticconstVector3NEGATIVE_UNIT_Y;//
staticconstVector3NEGATIVE_UNIT_Z;//
staticconstVector3UNIT_SCALE;//(1,1,1)
};
声明为union主要是为了可以通过两种形式访问成员变量,因为在与OpenGLAPI对接时,可能需要数组版的成员变量访问,其他一些成员是对一些特殊值的归类,方便用户使用。
主要函数接口说明:
Normalize()单位化一个向量。
Cross(constVector3&rkVector)求连个向量的叉乘。
Dot(constVector3&rkV)求向量的点积。
operator<<(std:
:
ostream&o,constVector3&v)在调试时使用,用来读取内部的信息查看程序是否运行正确。
其他还有一些对运算符的重载。
4.1.2矩阵
矩阵在图形学中经常使用,整个空间和坐标系统的建立都是基于矩阵,Direct3D(左手系)和OpenGL(右手系)内部使用的是4*4的矩阵,但大多数时候我们分开表示他们,用一个旋转矩阵(3阶方阵),一个缩放因子,和一个坐标原点来表示一个坐标系统。
类的定义和主要成员变量说明:
classMatrix3
{
protected:
union{
struct{
Realm_fMM[3][3];
};
Realm_fM[3*3];
};
};
主要函数接口说明:
Transpose()求转置矩阵。
Inverse(RealfTolerance=CMath:
:
EPSILON)求矩阵的逆,由于有的矩阵可能没有逆,既矩阵的置为零所以要给定一个参数,在矩阵的置小于这个参数时视为零处理(精度控制)。
ToAxisAngle(Vector3&rkAxis,Real&rfAngle)把一个旋转矩阵转换成一个轴和绕轴旋转的角度(逆时针为正)。
FromAxisAngle(constVector3&rkAxis,constRealfRadians)通过一个轴和角形成旋转矩阵。
还有一个使用频繁的函数就是用欧拉角表示旋转,欧拉角是把绕任意轴的旋转分解成分别绕X,Y,Z轴旋转的组合,但是欧拉角在绕某一个轴旋转超过90度时会出现万象死锁现象,失去一维自由度。
但是他容易理解和使用。
FromEulerAnglesXYZ(constRealfYAngle,constRealfPAngle,constRealfRAngle)
FromEulerAnglesXZY(constRealfYAngle,constRealfPAngle,,constRealfRAngle)
上面这一组函数是从欧拉角转换到旋转矩阵。
当然绕各轴的旋转顺序不同最终得到的旋转矩阵也会不同,所以提供了多个版本。
boolToEulerAnglesXYZ(Real&rfYAngle,Real&rfPAngle,Real&rfRAngle)
boolToEulerAnglesXZY(Real&rfYAngle,Real&rfPAngle,Real&rfRAngle)
上面这一组是从旋转矩阵变会到欧拉角表示的旋转,但是有万象死锁的原因,在绕某个轴旋转超过90度是会有多组结果。
Matrix4主要是为了与API对接,他的第一至三列分别表示X,Y,Z轴,最后一列表示这个坐标系的原点。
4.1.3四元数
四元数,在它被单位话后可以表示旋转,这点相对于用矩阵来表示旋转来说很优越,可以节省存储空间,还有一点就是他的插值,单位化后可以进行球面插值,平滑的从一个旋转过渡到另一个旋转。
类的定义和主要成员变量说明:
classQuaternion
{
Public:
union{
struct{
Realm_fX,m_fY,m_fZ,m_fW;
};
Realm_fVal[4];
};
//当sine值接近这个值时当来对待
staticconstRealms_fEpsilon;
staticconstQuaternionZERO;
staticconstQuaternionIDENTITY;
}
四元数和的四元向量(Vector4)成员变量相同,但是它表示的是一个复数,m_fW是它的实部,m_fX,m_fY,m_fZ是它的虚部。
主要函数接口说明:
Normalise()单位化
ToRotationMatrix(Matrix3&kRot)将四元数转换为旋转矩阵表示。
FromAngleAxis(constReal&rfAngle,constVector3&rkAxis)通过轴,角转换到四元数,ToAngleAxis是他的逆操作。
Slerp(RealfT,constQuaternion&rkP,constQuaternion&rkQ,boolshortestPath)球面插值,在两个四元数之间进行球面插值,shortestPath表示如果两个四元数之间的角度大于90度是否取反一个方向来得到最短路径。
Intermediate(constQuaternion&rkQ0,constQuaternion&rkQ1,constQuaternion&rkQ2,Quaternion&rka,Quaternion&rkB)利用样条线进行插值。
QuaternionSlerpExtraSpins(RealfT,constQuaternion&rkP,constQuaternion&rkQ,intiExtraSpins)先从rkP插值到rkQ然后再由rkQ到rkP并停止,fT是返回到rkQ的次数。
4.2引擎核心
4.2.1场景的组织
对场景的组织来说,面对的用户可能是比较专业的开发人员,或者只是想简单应用的一般开发人员。
对于专业的开发人员引擎要能够提供一些比较固定的组织场景算法,而对于一般用户来说,他可能不想了解太多的相关知识和算法。
所以提供给他的算法要更具有一般性.这两种情况要求引擎有足够的弹性去适应不同的用户。
对于固定算法来说,只要按照指定提供数据,剩下的引擎会自己处理。
关键在于数据的提供上。
此引擎提供了一个四叉树的场景管理算法。
四叉树算法描述:
我们可以认为一个地形是一个非常的大在X,Z轴方向进行延展的网格,例如有一个在X轴方向长512,在Z轴方向长512的灰度图,这样有512*512个像素,它们可以分别表示512*512个顶点的高度,设镜头在这个灰度图的中心点上,正朝这X轴的正向观看,视线张开的角度为90度,所以这时有一大半的地形无法看见,我们就可以用这个种方法对地形进行分割,直到找到在视线范围内的点,然后把他描画出来,同时对于那些远离视线的点我们可以用比较少点来对地形进行描画,因为在现实生活中远处的东西总是看的没近处的东西清楚。
一个3*3网格如图(从Y轴向下俯视):
图4.13*3网格图
首先对这个网格中所有的顶点(3*3个)进行检测如果他通过,那么在描画时就会包括它。
作为条件这个网格
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 大学 毕业设计 论文 引擎 设计 VC