[翻译]quake3bsp

来源:互联网 发布:仿淘宝网站模板 编辑:程序博客网 时间:2024/04/28 20:21

Introduction

介绍

This document was created as an aid to the Quake3 BSP  tutorial series featured on www.GameTutorials.com.      The information is what I have found, and it's possibly that it's incorrect or just blatently wrong.  I suggest you use this as a reference and a guide, not the end all file format doc for the Quake3 .bsp file format.  With that out of the way, let's load some sweet levels!

这篇文章是为GAMETURORIALSCOMQUAK3 BSP系列教程提供指导而写的。文章内提供的信息都是我发现的,而且很可能是不准确或完全错误的。所以我建议你把它作为一个参考或指导,而不是QUAKE3 BSP文件格式标准指南。扯远了,还是让我们开始载入美丽的关卡吧。

The Quake3 level format, .bsp, stores most of the information about the level.  There are other files such as .shader, .arena and .aas, which store bot and texture shader information.  The .bsp file is stored in what is called a IBSP format.  That means that the length and offsets of different sections in the file are stored in what's know as lumps.  The older version of Quake use this same lump format, but different information is stored in each version of Quake.  If you can read in Quake 3 levels, it's not a lot of changes to write a Quake 2 level loader.

QUAKE3关卡文件格式,。BSP储存了关于关卡的绝大部分信息。还有一些文件,如。SHADER、。ARENA和。ASS储存着机器人、纹理和着色器等信息。BSP文件是以一种叫IBSP文件格式的方式储存的,这意味着不同段的长度和偏移值是按LUMPS的方式组织的。QUAKE的早期版本使用了同样的LUMP格式,但是不同的QUAKE版本存储了不同的信息。如果你对QUAKE3的关卡格式入了门,那么你也可以毫不费力的写一个QUAKE2的关卡读取器。

If you don't know what BSP stands for yet, it means Binary Space Partition(ing).  You would create a BSP tree.  That means that there is a parent node, and at most, 2 children attached to each parent.  These children are called the front and back children.  I won't attempt to teach you how to create or manage a BSP tree here, but there is a BSP FAQ that SGI put out floating around the internet somewhere that has a ton of information.  Better yet, I suggest you take the BSP class at www.GameInstitute.com.  I personally took this class and was quite satisfied.  It teaches all you need to know about BSP trees.

如果你还不知道BSP代表了什么,那么让我来告诉你。他是二叉数空间分割的简写。你要建一个BSP树,那么就有了一个父节点,而且通常每个父节点都是连接着两个子节点。这些子节点分别叫做前子节点和后子节点。在这里,我不想教会你如果创建或管理一棵二叉树,但是你可以在SGI在互联网上创建的BSP FAQ中的成千上万的信息中找到你所需要的。如果还不够,我建议你去GAMEINSTITUTECOM看一下BSP教程。我个人认为这个教程还是很不错的,它能教会你掌握BSP树所需要所有知识。

Lumps

Like we mentioned before, lumps hold the length in bytes and offset into the file for a given section.  Below is an enum eLumps that holds all the lumps and their order in the file:

就像我们前面提到的,LUMPS以字节形式储存着文件中每一个段的长度和偏移值。下面是一个ELUMPS枚举体,它包含了所有LUMPS在文件中顺序:

enum eLumps
{
    kEntities = 0,     // Stores player/object positions, etc...
    kTextures,         // Stores texture information
    kPlanes,           // Stores the splitting planes
    kNodes,            // Stores the BSP nodes
    kLeafs,            // Stores the leafs of the nodes
    kLeafFaces,        // Stores the leaf's indices into the faces
    kLeafBrushes,      // Stores the leaf's indices into the brushes
    kModels,           // Stores the info of world models
    kBrushes,          // Stores the brushes info (for collision)
    kBrushSides,       // Stores the brush surfaces info
    kVertices,         // Stores the level vertices
    kMeshVerts,        // Stores the model vertices offsets
    kShaders,          // Stores the shader files (blending, anims..)
    kFaces,            // Stores the faces for the level
    kLightmaps,        // Stores the lightmaps for the level
    kLightVolumes,     // Stores extra world lighting information
    kVisData,          // Stores PVS and cluster info (visibility)
    kMaxLumps          // A constant to store the number of lumps
};

Each on of these sections has a offset and a size in bytes that need to be read in.  In the next sections we will examine the structures needed to read in each lump.

每一个段都以字节形式存储着载入信息所需要的偏移值和长度。在接下来的段落中,我们会为每个LUMP中的结构体举例。

Here is a lump structure.  The offset is the position into the file that is the starting point of the current section.  The length is the number of bytes that this lump stores.

这是一个LUMP结构体。OFFSET是当前段在文件中从文件头开始的位置。LENGTH以字节储存着这个LUMP的大小。
struct tBSPLump
{
    int offset;
    int length;
};


Let's give an example of reading in the vertices (kVertices) for the level.  Once the lumps are read in, to find the number of vertices in the level we do this:

让我们举例来装载关卡的顶点(KVERTICES)。在我们载入了LUMP之后,为了要找到关卡的顶点数,我们需要这么做:

numOfVerts = lumps[kVertices].length / sizeof(tBSPVertex);

We index the lumps[] array with the kVertices constant, then divide that lumps length by the size of the tBSPVertex structure in bytes, which we will define later on.  It just so happens it's 44 bytes.  If the length is 3388, then 3388 / 44 = 77.  We now know there is 77 vertices in the .bsp file.  We then need to position the file pointer to the lump's offset, and start reading in 77 tBSPVertex structures into our dynamically allocated vertex array.  I use fread() and fseek() for the file manipulation.  This is of course, ONLY if you are not reading from the .zip file.  I am strictly speaking of loading the .bsp file unzipped.

我们用KVERTICES常数来在LUMPS[]数组中索引,然后再用以字节为单位的TBSPVERTEX结构的大小去除。这个结构我们会在后边定义,它刚刚是44字节。如果我们得到长度数值是3388,那么3388/44 = 77。我们就知道了在BSP文件中一共有77个顶点。接着我们把文件的指针指向LUMPOFFSET的位置,然后在我们动态分配的顶点数组中载入这77TBSPVERTEX结构。我个人使用FREAD()和FSEEK()来进行文件操作。在这里补充一下,上面我所说的仅仅是装载未压缩的BSP文件。

Now that we understand the basics of lumps, let's move on to the header structure, along with the rest of the structures for each lump read in.

现在我们基本了解的LUMP,那么让我们继续随着读入的LUMP中结构体的其余部分,来到文件头结构。

BSP Header

 

The very first thing that needs to be read in for the .bsp file is the header.  The header contains a 4 character ID, then an integer that holds the version.

要装载BSP文件我们第一件要做的事就是载入文件头。文件头包含了一个四字节的ID和一个整型版本号。

 

struct tBSPHeader

{

    char strID[4];     // This should always be 'IBSP'

    int version;       // This should be 0x2e for Quake 3 files

};

 

 

Vertices

 

This structure stores the vertex information.  There is a position, texture and lightmap coordinates, the vertex normal and color.  To calculate the number of vertices in the lump you divide the length of the lump by the.

这个结构储存着顶点信息,包括位置、纹理和光照贴图坐标、顶点法线和颜色。为了计算顶点数,你需要用LUMP的长度除以sizeof(tBSPVertex)

 

struct tBSPVertex

{

    float vPosition[3];      // (x, y, z) position.

    float vTextureCoord[2];  // (u, v) texture coordinate

    float vLightmapCoord[2]; // (u, v) lightmap coordinate

    float vNormal[3];        // (x, y, z) normal vector

    byte color[4];           // RGBA color for the vertex

};

 

 

Faces

This structure holds the face information for each polygon of the level.  It mostly holds indices into all the vertex and texture arrays.  To calculate the number of faces in the lump you divide the length of the lump by the sizeof(tBSPFace).

这个结构存储着关卡中每一个多边形的面信息。它几乎包含了所有顶点和纹理数组的索引。为了计算面数,你需要用LUMP的长度除以sizeof(tBSPFace)

 

struct tBSPFace

{

    int textureID;        // The index into the texture array

    int effect;           // The index for the effects (or -1 = n/a)

    int type;             // 1=polygon, 2=patch, 3=mesh, 4=billboard

    int vertexIndex;      // The index into this face's first vertex

    int numOfVerts;       // The number of vertices for this face

    int meshVertIndex;    // The index into the first meshvertex

    int numMeshVerts;     // The number of mesh vertices

    int lightmapID;       // The texture index for the lightmap

    int lMapCorner[2];    // The face's lightmap corner in the image

    int lMapSize[2];      // The size of the lightmap section

    float lMapPos[3];     // The 3D origin of lightmap.

    float lMapVecs[2][3]; // The 3D space for s and t unit vectors.

    float vNormal[3];     // The face normal.

    int size[2];          // The bezier patch dimensions.

};

 

 

If the face type is 1 (normal polygons), the vertexIndex and numOfVerts can be used to index into the vertex array to render triangle fans.

如果面的类型是1(一般多边形),那么vertexIndexnumOfVerts可以用来为渲染三角形索引顶点数组。

 

If the face type is 2 (bezier path), the vertexIndex and numOfVerts act as a 2D grid of control points, where the grid dimensions are described by the size[2] array.  You can render the bezier patches with just the vertices and not fill in the curve information, but it looks horrible and blocky. 

如果面的类型是2(贝塞尔曲面),那么vertexIndexnumOfVerts则作为一个2D控制点网格。这个网格的维度是用size[2]数组来描述。你可以仅用顶点来渲染二次曲面,而不不必填充曲面信息。但是它看起来可没那么美观。

The point of the curved surfaces are to be able to create a more defined surface, depending on the specs of the computer that is running that application.  Some computers with horrible speed and video cards would make the smallest amount of polygons from the curve, where as the fast computers using Geforce cards could use the highest amount of polygons to form a perfect curve.

曲面上的点可以建立更多的表面,这取决与计算机运行程序的速度。有些计算机有着惊人的速度而且有些显卡可以为曲面生成最小的多边形。比如高速计算机使用Geforce显卡可以使用最大数量的多边形来生成一个完美的曲面。

If the face type is 3 (mesh vertices), the vertexIndex and numOfVerts also work the same as if the type is 1

如果面的类型是3(网格顶点),那么vertexIndexnumOfVerts像在类型中一样被使用。

If the face type is 4, the vertexIndex is the position of the billboard.  The billboards are used for light effects such as flares, etc...

如果面的类型是4,那么vertexIndex就是告示牌的位置,这些告示牌通常来实现光的效果,比如火焰等等。

未完待续...
原创粉丝点击