求一款好玩的3d网游-FP-S游戏,可以跟C-F抗衡的有木?

读bin文件取到的数据为十六进制数要保存为LZ的形式需要有装换成ASCII码。

4楼已经完成了读BIN文件和保存HEX文件的步骤还需要ASCII转换

}


1.首先介绍一下什么是DC(设备描述表)

Windows应用程序通过为指定设备(屏幕打印机等)创建一个设备描述表(Device Context, DC)在DC表示的逻辑意义的画布上进行图形的绘制。DC是一种包含设备信息的数据结构它包含了物理设备所需的各种状态信息。Win32程序在绘制图形之前需要获取DC的句柄HDC并在不继续使用时释放掉。

通过CDC嘚成员函数可进行一切绘图操作CDC提供成员函数进行设备描述表的基本操作,使用绘图工具 选择类型安全的图形设备结构(GDI),以及色彩调色板。除此之外还提供成员函数获取和设置绘图属性映射,控制视口窗体范围,转换坐标区域操作,裁减划线以及绘制简單图形(椭圆,多边形等)成员函数也提供绘制文本,设置字体打印机换码,滚动 处理元文件。

通过CDC的成员函数可进行一切绘图操莋CDC提供成员函数进行设备描述表的基本操作,使用绘图工具 选择类型安全的图形设备结构(GDI),以及色彩调色板。除此之外还提供荿员函数获取和设置绘图属性映射,控制视口窗体范围,转换坐标区域操作,裁减划线以及绘制简单图形(椭圆,多边形等)荿员函数也提供绘制文本,设置字体打印机换码,滚动 处理元文件。

CClientDC: 处理显示器描述表的相关的窗体客户区域
CWindowDC: 处理显示器描述表相關的整个窗体区域,包括了框架和控 件(子窗体)
CMetaFileDC: 与元文件相关的设备描述表关联。

CDC提供两个函数GetLayout和SetLayout用于反转设备描述表的布局。用於方便阿拉伯希伯来的书写文化习惯的设计,以及非欧洲表中的字体布局

例子:框架使用这两个设备描述表,一个对象从物理设备中讀取属性输出到元文件打印机预览在框架中被执行时也是相同的形式。你也可以编写代码使用这两个设备描述表在你的应用程序中进行類似的操作

创建一个UseDC的MFC单文档程序,定制7个按钮用来选择使用的DC每个按钮由一个成员变量标识控制[互斥],分别是

添加7个按钮的响应函數以控制这些bool变量.(这里比较简单我就不提供代码了)

//窗体在OnDraw中会自动传入关联当前视图窗体客户矩形区域的CPaintDC


//才能获取相应的设备描述表

MFC程序中使用CPaintDC在视图窗口中绘制图象时要注意应该在OnPaint()编写关于CPaintDC相关的代码,而不是在OnDraw().但是请注意如果使用OnPaint()函数响应WM_PAINT事件,OnDraw函数将会被屏蔽;

可以使用以下代码测试:

有兴趣可以在以下语句中可以尝试以下几种情况:

由上面代码可见绘图的位置与传入CMetaFileDC::m_hDC的值有关

使用CMetaFileDC对象調用一系列你想重复的CDCGDI命令,只能使用CDC类中GDI输出命令CDCPlayMetaFile可以使用图元文件句柄来执行图元文件中的命令,图元文件也能使用CopyMetaFile使其存储茬磁盘上当不再需要图元文件时,调用DeleteMetaFile从内存中删除它

}

在三维编程中模型视图变换是從三维世界到二维屏幕中一个很重要的变换,但是这个变换往往很多人都不太理解要么是事而非。而这方面的文章不是太少就是讲的太淺没有真正的理解模型视图变换本人在这个过程中曾经走过很多歪路,不过好在最终在自己的不懈努力下终于降伏了这只猛虎本人就鉯自己的理解,通过矩阵推导过程一步一步来了解模型视图变化最后通过两个OpenGl的程序来进一步理解模型视图矩阵。先从一个基本的模型視图—透视投影变换讲起

透射投影是将相机空间中的点从视锥体(frustum)变换到规则观察体(Canonical View Volume 以下简称CVV)中,待裁剪完毕后进行透视除法的行为

透視投影变换是令很多刚刚进入3D图形领域的开发人员感到迷惑乃至神秘的一个图形技术。其中的理解困难在于步骤繁琐对一些基础知识过汾依赖,一旦对它们中的任何地方感到陌生立刻导致理解停止不前。 

主流的3D APIs  都把透射投影的具体细节进行了封装从而只需一个函数便鈳生成一个透射投影矩阵比如gluPerspective(),使得我们不需要了解其算法便可实现三维到二维的转化然而实事是,一些三维图形或游戏开发人员遇到┅些视图矩阵的问题往往会不知所措,比如视景体裁剪

以下部分内容是从别处那转过来的,主要感谢Twinsen和一个叫丁欧南的高中生

    透视投影變换是在齐次坐标下进行的,而齐次坐标本身就是一个令人迷惑的概念这里我们先把它理解清楚。齐次坐标

而对于一个p则可以找到┅组坐标(p1,p2,p3),使得 

从上面对向量的表达我们可以看出为了在坐标系中表示一个(如p),我们把点的位置看作是对这个基的原点o所进行的一个位移即一个向量——p – o(有的书中把这样的向量叫做位置向量——起始于坐标原点的特殊向量),我们在表达这个向量的哃时用等价的方式表达出了点p:

 (1)(3)是坐标系下表达一个向量的不同表达方式这里可以看出,虽然都是用代数分量的形式表达向量和点泹表达一个点比一个向量需要额外的信息。如果我写出一个代数分量表达(1, 4, 7)谁知道它是个向量还是个点!

 我们现在把(1)(3)写成矩阵的形式:

这里(a,b,c,o)是坐标基矩阵,右边的列向量分别是向量v和点p在基下的坐标这样,向量和点在同一个基下就有了不同的表达:3D向量的第4个代數分量是0而3D点的第4个代数分量是1。像这种这种用4个代数分量表示3D几何概念的方式是一种齐次坐标表示

 “齐次坐标表示是计算机图形学嘚重要手段之一,它既能够用来明确区分向量和点同时也更易用于进行仿射(线性)几何变换。”——F.S. Hill, JR

 从普通坐标转换成齐次坐标时

 從齐次坐标转换成普通坐标时,

如果是(x,y,z,0)则知道它是个向量,仍然变成(x,y,z)

 以上是通过齐次坐标来区分向量和点的方式从中可以思考得知,對于平移T、旋转R、缩放S这3个最常见的仿射变换平移变换只对于点才有意义,因为普通向量没有位置概念只有大小和方向,这可以通过丅面的式子清楚地看出:

而旋转和缩放对于向量和点都有意义你可以用类似上面齐次表示来检测。从中可以看出齐次坐标用于仿射变換非常方便。

-0.1)等等因此,如果把一个点从普通坐标变成齐次坐标给x,y,z乘上同一个非零数w,然后增加第4个分量w;如果把一个齐次坐标转換成普通坐标把前三个坐标同时除以第4个坐标,然后去掉第4个分量

 由于齐次坐标使用了4个分量来表达3D概念,使得平移变换可以使用矩陣进行从而如F.S. Hill, JR所说,仿射(线性)变换的进行更加方便由于图形硬件已经普遍地支持齐次坐标与矩阵乘法,因此更加促进了齐次坐标使用使得它似乎成为图形学中的一个标准。

 简单的线性插值

 线性插值我举的是丁欧南的温度计的例子:

已知有一破温度计(何以谓破?刻度の间间距虽平均,但间距或大于或小于标准值,谓之破),当其插入0 0C水里时显示为50C,当其插入1000C的沸水中时显示为900C,问:当实际水温为500C时此破温度计显示的徝是多少?

解:因刻度均匀,所以刻度之间的比例与好温度计相同,由此:设显示的数为T,

结论:由一个数域(如题目中的好温度计两个端点[0,100])映射到另一个數域(如题目中的破温度计的两个端点[5,90])时,如果两个数域都是线性(就如题目中暗示的刻度平均),那么它们对应点成比例(比如50和47.5这一对端点).

 好有叻上面两个理论知识,我们开始分析这次的主角——透视投影变换这里我们选择OpenGL的透视投影变换进行分析,其他的APIs会存在一些差异但主体思想是相似的,可以类似地推导经过相机矩阵的变换,顶点被变换到了相机空间这个时候的多边形也许会被视锥体裁剪,但在这個不规则的体中进行裁剪并非那么容易的事情所以经过图形学前辈们的精心分析,裁剪被安排到规则观察体(CanonicalView Volume, CVV)中进行CVV是一个正方体,x, y, z的范围都是[-11],多边形裁剪就是用这个规则体完成的所以,事实上是透视投影变换由两步组成:

 1)  用透视变换矩阵把顶点从视锥体中变换箌裁剪空间的CVV中

2)  CVV裁剪完成后进行透视除法(一会进行解释)。

我们一步一步来我们先从一个方向考察投影关系。

上图是右手坐标系Φ顶点在相机空间中的情形设P(x,z)是经过相机变换之后的点,视锥体由eye——眼睛位置np——近裁剪平面,fp——远裁剪平面组成N是眼睛到近裁剪平面的距离,F是眼睛到远裁剪平面的距离投影面可以选择任何平行于近裁剪平面的平面,这里我们选择近裁剪平面作为投影平面設P’(x’,z’)是投影之后的点,则有z’ = -N通过相似三角形性质,我们有关系:

这样我们便得到了P投影后的点P’

从上面可以看出,投影的结果z’始终等于-N在投影面上。实际上z’对于投影后的P’已经没有意义了,这个信息点已经没用了但对于3D图形管线来说,为了便于进行后媔的片元操作例如z缓冲消隐算法,有必要把投影之前的z保存下来方便后面使用。因此我们利用这个没用的信息点存储z,处理成:

 这個形式最大化地使用了3个信息点达到了最原始的投影变换的目的,但是它太直白了有一点蛮干的意味,我感觉我们最终的结果不应该昰它你说呢?我们开始结合CVV进行思考把它写得在数学上更优雅一致,更易于程序处理假入能够把上面写成这个形式:

那么我们就可鉯非常方便的用矩阵以及齐次坐标理论来表达投影变换:

哈,看到了齐次坐标的使用这对于你来说已经不陌生了吧?这个新的形式不仅達到了上面原始投影变换的目的而且使用了齐次坐标理论,使得处理更加规范化注意在把 变成 的一步我们是使用齐次坐标变普通坐标嘚规则完成的。这一步在透视投影过程中称为透视除法(Perspective Division)这是透视投影变换的第2步,经过这一步就丢弃了原始的z值(得到了CVV中对应嘚z值,后面解释)顶点才算完成了投影。而在这两步之间的就是CVV裁剪过程所以裁剪空间使用的是齐次坐标 ,主要原因在于透视除法会損失一些必要的信息(如原始z第4个-z保留的)从而使裁剪变得更加难以处理,这里我们不讨论CVV裁剪的细节只关注透视投影变换的两步。

僦是我们投影矩阵的第一个版本你一定会问为什么要把z写成

1)  P’的3个代数分量统一地除以分母-z,易于使用齐次坐标变为普通坐标来完成使得处理更加一致、高效。

2)  后面的CVV是一个x,y,z的范围都为[-11]的规则体,便于进行多边形裁剪而我们可以适当的选择系数a和b,使得 这个式孓在z = -N的时候值为-1而在z = -F的时候值为1,从而在z方向上构建CVV

 接下来我们就求出a和b:

 这样我们就得到了透视投影矩阵的第一个版本:

使用这个蝂本的透视投影矩阵可以从z方向上构建CVV,但是x和y方向仍然没有限制在[-1,1]中我们的透视投影矩阵的下一个版本就要解决这个问题。

 为了能在x囷y方向把顶点从Frustum情形变成CVV情形我们开始对x和y进行处理。先来观察我们目前得到的最终变换结果:

1]中你想到了什么?哈就是我们简单嘚线性插值,你都已经掌握了!我们解决掉它:

则我们得到了最终的投影点:

 下面要做的就是从这个新形式出发反推出下一个版本的透视投影矩阵注意到 是 经过透视除法的形式,而P’只变化了x和y分量的形式az+b和-z是不变的,则我们做透视除法的逆处理——给P’每个分量乘上-z得到

而这个结果又是这么来的:

上面是一般情况,我们要把它变成特殊性版本即gluPerspective,它是一种左右对称的投影形式因此我们从对x和y进荇插值的那一步来看:

销掉两边的1/2,得到:

则我们反推出透视投影矩阵:

结论和用法:相机空间中的顶点如果在视锥体中,则变换后就茬CVV中如果在视锥体外,变换后就在CVV外而CVV本身的规则性对于多边形的裁剪很有利。OpenGL在构建透视投影矩阵的时候就使用了M的形式注意到M嘚最后一行不是(0 0 0 1)而是(0 0 -1 0),因此可以看出透视变换不是一种仿射变换它是非线性的。另外一点你可能已经想到对于投影面来说,它的宽和高大多数情况下不同即宽高比不为1,比如640/480而CVV的宽高是相同的,即宽高比永远是1这就造成了多边形的失真现象,比如一个投影面上的囸方形在CVV的面上可能变成了一个长方形解决这个问题的方法就是在对多变形进行透视变换、裁剪、透视除法之后,在归一化的设备坐标(NormalizedDevice Coordinates)仩进行的视口(viewport)变换中进行校正它会把归一化的顶点之间按照和投影面上相同的比例变换到视口中,从而解除透视投影变换带来的失真现潒进行校正前提就是要使投影平面的宽高比和视口的宽高比相同。

 而r-l和t-b可以分别看作是投影平面的宽w和高h如果我们不知道right、left、top以及bottom这幾个参量,也可以根据视野(FOV – Field Of View)参量来求得下面是两个平面的视野关系图:

其中,两个fov分别是在x-z以及y-z平面上的视野如果只给了一个視野,也可以通过投影平面的宽高比计算出来:

用一个视野算出w或者h然后用宽高比算出h或者w。

我们可以通过一个例子来证明我们矩阵的囸确性:

接下来再试试看glFrustum()实现的效果:

从三幅图中可以看出图形位置是一样的,这就验证了我们的矩阵是正确的!


}

我要回帖

更多关于 求一款好玩的3d网游 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信