原创 2006年06月09日 23:24:00



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.


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树所需要所有知识。


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:


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.


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.

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:


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.


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.



struct tBSPHeader


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

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






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.



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





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).



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.



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. 


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.


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


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...



Quake 2 BSP 文件格式 (翻译)

Quake 2 BSP 文件格式 分类: OpenGL编程 2009-07-29 16:39 421人阅读评论(0)收藏举报 Quake 2 BSP 文件格式 (翻译自《Quake2 B...

Quake 2 BSP 文件格式 (翻译)

Quake 2 BSP 文件格式 分类: OpenGL编程 2009-07-29 16:39 421人阅读评论(0)收藏 举报 Quake 2 BSP 文件格式 (翻译自《Quake...

缅怀Quake 3引擎

Quake 3引擎从诞生起,就成为众多3D游戏开发者选择的基本引擎,时至今日,仍到处可见以Q3引擎作为游戏引擎的游戏。同时,该引擎在硬件发展过程中的地位也不容忽视。Gotfrag上一篇探讨Q3引擎的文...

如何编译quake3 arena ( transshipment )

  按照 John Carmack 的承诺 Quake III Arena 也终于开源了!在 Id Software 的网站上下就能购下载到。  不过似乎网上更流行的版本是从这里能够得到的一个名为 q...

QUAKE 3源代码审查:人工智能

QUAKE 3源代码审查:人工智能(第5部分,共5部分)>> 改装社区为每个以前的idTech引擎写了机器人系统。其中两人当时颇有名气: Quake1有Omicron。Quake2有角斗士...


1.这个例子设计内容:      1.加载quake3map,      2.为最优化渲染速度创建一个场景节点,      3.创建可交互的摄像机. ...
  • gqkly
  • gqkly
  • 2016年04月22日 21:52
  • 910


2006年中秋节写的帖子,有一些疏漏之处想改正一下,另把一些基础知识和英文缩写的注释提到正文前,原文不让编辑了,所以修改了一下发在这里。 很多人都说q3门槛高。尤其是当cs兴盛之后。 q3的高...
  • cbbbc
  • cbbbc
  • 2015年09月01日 09:55
  • 1563

QUAKE 3源代码评测:架构

QUAKE 3源代码评测:架构(第1部分,共5部分)>> 由于我在下一个合同前一个星期,我决定完成我的“循环ID”。后末日,末日iPhone,Quake1,Quake2中,德军iPhone和毁灭...


声明: 原文 http://www.cnblogs.com/vincent2600/archive/2011/09/12/2174056.html 如果不去读quake3代码,作为一个游...

QUAKE 3源代码审查:渲染器

QUAKE 3源代码评论:RENDERER(第2部分,共5部分)>> Quake III渲染器是Quake II硬件加速渲染器的演变:经典部分是建立在“二进制分区”/“潜在可见集”架构上,但...