您的位置:首页 > 其它

详细介绍Quake 2 BSP文件格式和应用

2011-11-18 13:12 369 查看
简介

  

  BSP文件格式是QUAKE 2用于存储地图的一种文件格式,说得具体点,就是用于渲染Q2世界的。尽管有其他的信息包含在BSP文件中,用于其他游戏部分(如敌人AI,等等),在这篇文章中,我不将讨论他们。如果你有这方面的知识,请告诉我,我的E-MAIL在下面。在这篇文章中难免有错误之处,请告诉我。

  为了更清楚的描述BSP文件格式,在这篇文章中将试图对Q2渲染引擎进行技术方面的描述。现在让我们假想这个渲染器使用的是基本的3D图形技术,包含BSP树结构。

  我们在这篇文章中描述的是Q2的BSP文件格式,这个文件格式由Kingpin使用(他建立了Q2引擎)。对于Q1和Q3的文件格式,虽然他们很相同,但还是有点不兼容。不管怎样,BSP的文件结构和技术不是很难,这篇文章将对于那些对这些格式赶兴趣的人。

  

  法律方面的问题

  

  协定

  

  在这篇文章中,我用C语言结构来描述这些问题。为了使描述简单并规范意义,我用int32 and uint32来表示有符号和无符号32位整形数;同样的符号将用于16位和32位整形数。下面为用于存储BSP文件格式的顶点和矢量的结构:

  struct point3f

  {

  float x;

  float y;

  float z;

  };

  struct point3s

  {

  int16 x;

  int16 y;

  int16 z;

  };

  第二版中一些地方,如保存内存,就不需要很高的精度。相比于12位的版本,他只需要6位。通常情况下,都是用整形,而非浮点。

  

  渲染

  

  在这一节中,我们将介绍数据结构中的一些术语,并描述一下在Q2中进行渲染的过程。

  Q2地图中划分成很多的凸区域,这些区域用BSP树页来表示。任何时候摄象机的位置随这些凸区域的水平方向改变。那一些树叶都相互的簇拥在一起,成一丛一丛的。这些丛如何构成是由建立BSP文件的工具决定。对于每个丛,他们都是以列表形式潜在,直观地存储。我们把这称为potentially visible set(PVS).

  要渲染Q2地图,首先篇历BSP树,以决定摄象机的导入。一旦知道摄象机导入的叶,相应的丛也导入了(记住一片叶包含一个丛)。对应于丛的PVS然后解压出摄象机对应的那些PVS的列表。叶然后存储根据视角平截面裁减的叶的范围。

  

  BSP树

  

  许多人在通过用Q2和相似的引擎时,没有把BSP树和相应的算法联系起来。通过上面的叙述,我们知道可视的界面是由PVS决定。BSP树用于分割地图并快速地决定哪一块应该显示。结果,在Q2中没有好的渲染算法,而不得不用其他数据结构代替(如OCTREE OR K-D TREE)。BSP树不管怎样是非常简单的,他也被用在Q2引擎中其他不用渲染的任务中。

  当讨论BSP树中存储叶结点的BSP树(leaf-based BSP trees)和存储内部结点的BSP树(node-based BSP trees)时。用在Q2中的BSP树的变化实际上是两方面的。这两方面是渲染和冲突检测。用于渲染时,他直接把存储在叶结点中的面渲染出来,因为他们是以PVS形式存储的。如果你没有执行冲突检测,存储在内部结点中的面将完全被忽约。

  

  文件头

  

  就我所知,所有的BSP文件是以字节的形式存储的,当用在大的终端平台上时,随着导入而变换。这使的相同的地图能够被使用不同平台的Q2用户共同使用。如果你在大的终端中导入BSP文件-------如Macintosh ,UNIX---你将不得不仔细的变换字节顺序。

  BSP文件格式是用目录结构组织的,文件中所有的数据包含“自由的浮动”(free floating)团。在文件开始处,有一个目录告诉团的开始的偏移和长度。这个目录后的文件开始的8个字节是用于描述这些团的位置和长度。

  BSP文件头的格式描述如下:

  struct bsp_lump

  {

  uint32 offset;      //从文件开始的数据的偏移(用字节表示)

  uint32 length;     //数据的长度(用字节表示)

  };

  struct bsp_header

  {

  uint32 magic;    //magic号(“IBSP”)

  uint32 version;   //BSP格式的版本(38)

  bsp_lump lump[19];  //团的目录

  };

  BSP文件开始的4个字节是一个标记,用于标识文件是否一个软件BSP文件。这些字节被拼为“IBSP”。接下来是32位无符号整形数,用于指定版本号。正如上面说的一样,本文件的版本号为38。

  接下来的表显示BSP文件中包含的不同的团,并且这些团的索引排列在文件头中。这些团的目的是用于标识不知道的问题标记(这个名字来源于QBSP源代码),不管怎样,他们是不用建构简单的Q2标准渲染器。

  

  索引名          描述

  0 Entities       MAP实体文本缓冲器

  1 Planes       平面队列

  2 Vertices      顶点队列

  3 Visibility       压缩的PVS数据和所有的丛目录

  4 Nodes       BSP树的内部结点数组

  5 Texture Information 表面材质运用队列

  6 Faces        表面队列

  7 Lightmaps     光图

  8 Leaves       BSP树的内部叶队列

  9 Leaf Face Table 索引查找表,用于参考叶中的表面队列

  10 Leaf Brush Table    ?

  11 Edges      边队列

  12 Face Edge Table 索引查找表,用于参考叶中的边队列

  13 Models     ?

  14 Brushes    ?

  15 Brush Sides  ?

  16 Pop       ?

  17 Areas      ?

  18 Area Portals      ?

  许多团是用结构队列的形式存储的,这些结构都是固定大小。例如,顶点团是一个POINT3F结构队列。由于每个POINT3F是12位,顶点值被12个顶点团分开进行计算。相似的计算也被用于面,结点,材质信息,表面,叶和边团。

  在下一节,我们将讨论团的结构和作用。

  

  顶点团

  

  顶点团是一列世界的所有的顶点。每个结点是3个float浮点值,相当于12个字节。你能计算这些顶点值通过把这些顶点团的长度分为12来计算。(You can compute the numbers of vertices by dividing the length of the vertex lump by 12. ^_^不好意思,可能翻译错了)

  Q2用一个协调系统通过Z-轴调整为向上。记住,就是你用其他的系统进行调节,你可能需要改变束缚盒和面方程式。

  

  边团

  在表面的顶点要共享,而且边也要共享。每一条边是存储在顶点队列中。存储量是两个16位的整形数,因此,在边队列中的边数是由边团的值除以4。这里要说的是可能有一条边被有卷绕着的线的两个面共享,因此对于一条边,没有特殊的方向。这一点将在表面团中讨论。

  

  表面团

  

  bsp_face结构队列中表面团的格式如下:

  

  struct bsp_face

  {

  uint16 plane;      //表面平行的面的索引

  uint16 plane_side;  //设置表面是否与面平行

  

  uint32 first_edge;  //第一条边的索引(在表面边队列中)

  uint16 num_edges; //连续的边的数量(在表面边队列中)

  

  uint16 texture_info;   //材质信息结构的索引

  uint8  lightmap_syles[4]; //光图的类型

  uint32 lightmap_offset;  //光图在光图团中的偏移

  };

  这个bsp_face结构的长度是20字节,面的数量可以由表面团除以20得到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: