📄 quake3format.htm
字号:
<html>
<head>
<TITLE>GameTutorials - Quake 3 BSP Format</TITLE>
<META NAME="Description" CONTENT="GameTutorials brings you the best programming tutorials from beginner (NO experience) to advanced topics AND keeps you in touch with all the latest game industry news.">
<META NAME="Keywords" CONTENT="programming tutorials, video games, game tutorials, programming, C, C++, Windows, Win32, OpenGL, DirectX">
<link rel="stylesheet" href="../default.css">
</head>
<body bgcolor="#000000" text="#f0f0ff" link="#7396dc" marginwidth="0" marginheight="0" leftmargin="0" topmargin="0">
<!-- main table -->
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<!-- left column -->
<td valign="top" background="http://www.gametutorials.com/images/Left_Seamless.jpg" width="211" height="661">
<p align="center">
<map name="FPMap0">
<area href="http://www.gametutorials.com" shape="RECT" coords="50,270,127,300">
<area href="http://www.gametutorials.com/Tutorials/tutorials.htm" shape="RECT" coords="46,317,131,348">
<area href="http://www.gametutorials.com/forum/" shape="RECT" coords="46,374,134,402">
<area href="http://www.gametutorials.com/CodeDump/CodeDump_Pg1.htm" shape="RECT" coords="49,424,142,458">
<area href="http://www.gametutorials.com/D&G/D&G_Main.htm" shape="RECT" coords="50,480,157,513">
<area href="http://gametutorials.tech-engine.com/" shape="RECT" coords="47,536,138,571">
<area href="http://www.gametutorials.com/links.htm" shape="RECT" coords="49,594,137,627">
</map><img border="0" src="http://www.gametutorials.com/images/Left.jpg" usemap="#FPMap0" width="211" height="661"></p>
<p><br></p> <!-- Spacing -->
<p align="center"><font face="Verdana" size="1">Link to us:</font><br>
<a href="http://www.gametutorials.com/download/GT_Link.zip"><img border="0" src="http://www.gametutorials.com/images/GameTutorials_Link.jpg" width="88" height="31"></a></p>
</td>
<!-- center column -->
<td valign="top">
<table border="0" cellpadding="0" cellspacing="0" height="568">
<tr>
<td valign="top" height="207" width="609">
<p><img border="0" src="http://www.gametutorials.com/images/Title.jpg" width="609" height="207"></p>
</td>
</tr>
<tr>
<td valign="top" align="center" height="361">
<!-- main content area -->
<table border="0" cellpadding="0" cellspacing="0" style="BORDER-COLLAPSE: collapse" width="561">
<tr>
<td width="559">
<p align="center"><br><b><span style="FONT-SIZE: 20pt; mso-bidi-font-size: 10.0pt">Unofficial</span></b><span style="FONT-SIZE: 20pt; mso-bidi-font-size: 10.0pt"><b>
Quake
3 BSP Format<br>
</b>
</span><span style="mso-bidi-font-size: 10.0pt"><font size="3"><b>Author:
Ben "Digiben" Humphrey</b></font></span><b><span style="FONT-SIZE: 20pt; mso-bidi-font-size: 10.0pt"><O:P>
</O:P>
</span></b></p>
<p class="MsoBodyText">
</p>
<table width="571">
<tr bgColor="#2165ae">
<td height="17" width="563"><b><font size="5">Introduction</font></b></td>
</tr>
</table>
<p class="MsoNormal">This document was created as an aid to the <b>Quake3 BSP</b>
tutorial series featured on <a href="http://www.GameTutorials.com"><b>www.GameTutorials.com</b></a>.
<O:P>
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!
</p>
<p class="MsoNormal">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 <b>lumps</b>. 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.
</p>
<p class="MsoNormal">If you don't know what <b>BSP</b> stands for yet, it
means <b>Binary Space Partition(ing)</b>. 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 <b>front </b>and <b>back </b>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 <a href="http://www.GameInstitute.com"><b>www.GameInstitute.com</b></a>.
I personally took this class and was quite satisfied. It teaches all you
need to know about BSP trees.
</p>
<p class="MsoBodyText">
</p>
<table width="572">
<tr bgColor="#2165ae">
<td height="17" width="564"><b><font size="5">Lumps</font></b></td>
</tr>
</table>
<p class="MsoBodyText">
Like we mentioned before, lumps hold the length in bytes and offset into the
file for a given section. Below is an enum <b>eLumps</b> that holds all
the lumps and their order in the file:
</p>
<p class="MsoBodyText"><code>
enum <b> eLumps</b><br>
{<br> kEntities =
0, // Stores
player/object positions, etc...<br>
kTextures,
// Stores texture information<br>
kPlanes,
// Stores the splitting planes<br>
kNodes,
// Stores the BSP nodes<br>
kLeafs,
// Stores the leafs of the nodes<br>
kLeafFaces, //
Stores the leaf's indices into the faces<br>
kLeafBrushes, // Stores the
leaf's indices into the brushes<br>
kModels,
// Stores the info of world models<br>
kBrushes,
// Stores the brushes info (for collision)<br>
kBrushSides, // Stores
the brush surfaces info<br>
kVertices,
// Stores the level vertices<br>
kIndices, // Stores the level indices<br>
kShaders,
// Stores the shader files (blending, anims..)<br>
kFaces,
// Stores the faces for the level<br>
kLightmaps, //
Stores the lightmaps for the level<br>
kLightVolumes, // Stores extra
world lighting information<br>
kVisData,
// Stores PVS and cluster info (visibility)<br>
kMaxLumps
// A constant to store the number of lumps<br>
};<br>
<br>
<font face="Times New Roman" size="3">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.</font></code>
</p>
<p class="MsoBodyText"><code><font face="Times New Roman" size="3">Here is a
lump structure. The <b>offset</b> is the position into the file that is
the starting point of the current section. The <b>length</b> is the
number of bytes that this lump stores.</font></code>
</p>
<p class="MsoBodyText">
<code><br>
struct <b>tBSPLump</b><br>
{<br>
int offset;<br>
int length;<br>
};</code>
</p>
<p class="MsoBodyText">
<br>
Let's give an example of reading in the vertices (<b>kVertices</b>) for the
level. Once the lumps are read in, to find the number of vertices in the
level we do this:
</p>
<p class="MsoBodyText">
numOfVerts = lumps[kVertices].length / sizeof(tBSPVertex);
</p>
<p class="MsoBodyText">We index the <b>lumps[]</b> array with the <b>kVertices</b>
constant, then divide that lumps <b>length</b> by the size of the <b>tBSPVertex</b>
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 <b>offset</b>, and start reading in 77 <b>tBSPVertex
</b>structures into our dynamically allocated vertex array. I use <b>fread()</b>
and <b>fseek()</b> 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.
</p>
<p class="MsoBodyText">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.<br>
</p>
<p class="MsoBodyText">
</p>
<table width="570">
<tr bgColor="#2165ae">
<td height="17" width="562"><b><font size="5">BSP Header</font></b></td>
</tr>
</table>
<p class="MsoBodyText">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.
</p>
<p class="MsoBodyText">
<code>
<br>
struct <b> tBSPHeader</b><br>
{<br>
char strID[4]; // This should
always be 'IBSP'<br>
int version; // This
should be 0x2e for Quake 3 files<br>
};
</code>
</p>
<p class="MsoBodyText">
</p>
<table width="570">
<tr bgColor="#2165ae">
<td height="17" width="562"><b><font size="5">Vertices</font></b></td>
</tr>
</table>
<p class="MsoBodyText">
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 sizeof(<b>tBSPVertex</b>).
</p>
<p class="MsoBodyText">
<code>
<br>
struct <b> tBSPVertex</b><br>
{<br>
float vPosition[3]; // (x, y,
z) position. <br>
float vTextureCoord[2]; // (u, v) texture coordinate<br>
float vLightmapCoord[2]; // (u, v) lightmap coordinate<br>
float vNormal[3];
// (x, y, z) normal vector<br>
byte color[4];
// RGBA color for the vertex <br>
};<br>
</code>
</p>
<p class="MsoBodyText">
</p>
<table width="571">
<tr bgColor="#2165ae">
<td height="17" width="563"><b><font size="5">Faces</font></b></td>
</tr>
</table>
<p class="MsoBodyText">
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(<b>tBSPFace</b>).
</p>
<p class="MsoBodyText"><code>
<br>
struct <b>tBSPFace</b><br>
{<br>
int textureID; //
The index into the texture array <br>
int effect;
// The index for the effects (or -1 = n/a) <br>
int type;
// 1=polygon, 2=patch, 3=mesh, 4=billboard <br>
int startVertIndex; // The index
into this face's first vertex <br>
int numOfVerts; // The
number of vertices for this face <br> int startIndex; // The index into
the indices array<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -