Useful Links
- Jan Horns BSP loader (Basic IBSP Loading but shows the basics of loading the BSP files)
- Harry Painters Q3MapView (Advanced Q3 Map Loader)
- IBSP Spec
- RBSP Spec
- QCommon with RBSP support
Basic "Maths Code" used below
Code: type TVector3f = record X, Y, Z : single; end; type TVector2f = record X, Y : single; end;
The header is the first bit of info in the BSP file, StrID should be RBSP and Version should be 1. Note: In IBSP maps valid versions are 46 (Q3) and 47 (RTCW)
Code: type TBSPHeader = record strID : array[0..3] of char; // This should always be 'IBSP' Version : integer; // This should be 0x2e for Quake 3 files end;
The offset to all the "Sections" are stored in Lumps, they define the size of the "Section" and its offset.
Code: type TBSPLump = record Offset : integer; // The offset into the file for the start of this lump Length : integer; // The length in bytes for this lump end;
The Sections are layed out like the following:
Code: const kEntities = 0; // Stores player/object positions, etc... kTextures = 1; // Stores texture information kPlanes = 2; // Stores the splitting planes kNodes = 3; // Stores the BSP nodes kLeafs = 4; // Stores the leafs of the nodes kLeafFaces = 5; // Stores the leaf's indices into the faces kLeafBrushes = 6; // Stores the leaf's indices into the brushes kModels = 7; // Stores the info of world models kBrushes = 8; // Stores the brushes info (for collision) kBrushSides = 9; // Stores the brush surfaces info kVertices = 10; // Stores the level vertices kMeshVerts = 11; // Stores the model vertices offsets kEffects = 12; // Stores the effect shaders (face to brush) kFaces = 13; // Stores the faces for the level kLightmaps = 14; // Stores the lightmaps for the level kLightVolumes= 15; // Stores extra world lighting information (For meshes) kVisData = 16; // Stores PVS and cluster info (visibility) kLightArray = 17; // Unknown kMaxLumps = 18; // A constant to store the number of lumps
The first section is the entitys, they are stored in plain text and look like:
Code: { classname Bannana someproperty somevalue model 20 }
The 2nd is the textures which are stored like
Code: type TQ3FileTexture = record TextureName : array[0..63] of char; // The name of the shader flags : cardinal; // The surface flags (unknown) contents : cardinal; // The content flags (unknown) end;
3rd is planes
Code: type TBSPPlane = record Normal : TVector3f; // Plane normal. d : single; // The plane distance from origin end;
4th is Nodes
Code: type TBSPNode = record plane : integer; // The index into the planes array front : integer; // The child index for the front node back : integer; // The child index for the back node min : TVector3i; // The bounding box min position. max : TVector3i; // The bounding box max position. end;
5th is leafs
Code: type TBSPLeaf = record cluster : integer; // The visibility cluster area : integer; // The area portal min : TVector3i; // The bounding box min position. max : TVector3i; // The bounding box max position. leafface : integer; // The first index into the face array numOfLeafFaces : integer; // The number of faces for this leaf leafBrush : integer; // The first index for into the brushes numOfLeafBrushes : integer; // The number of brushes for this leaf end;
6th is Leaf faces, which is an Array Of Integer. The Leaf's leafface points to the start leaf of the Leaf Face array, which inturn points to the actual face id. (faces are still to come)
7th is the leaf brushes, which is an Array Of Integer. Its use is the same as the Leaf Faces array, but fro brushes.
8th is the models (Note: Models point to faces, all entitys that are visible(aka rendered) or use an area to detect things (like a trigger_multipul) use the models). Model 0 is always the level's model
Code: type TBSPModel = record min : TVector3f; // The min position for the bounding box max : TVector3f; // The max position for the bounding box. faceIndex : integer; // The first face index in the model numOfFaces : integer; // The number of faces in the model brushIndex : integer; // The first brush index in the model numOfBrushes : integer; // The number brushes for the model end;
9th is brushes
Code: type TBSPBrush = record brushside , // First brushside for brush numOfBrushsides , // Number of brushsides for brush Texture : integer; // Texture index end;
10th is brush sides. Note: this is the RBSP Version
Code: type TRBSPBrushSide=record plane , // Plane Index texture, Face : integer; // Texture Index end;
11th is the Vertex's. Note: this is the RBSP Version
Code: type TRBSPVertex = record Position : TVector3f; // (x, y, z) position. TextureCoord : TVector2f; // (u, v) texture coordinate LightmapCoord : array [0..3] of TVector2f; // (u, v) lightmap coordinate Normal : TVector3f; // (x, y, z) normal vector Color : array [0..3] of array [0..3] of Byte; // RGBA color for the vertex end;
12th is MeshVerts which is an array of integer. (Its used with the faces to work out which vertex's should be drawn, note the way Jan Horn does it is wrong, Mesh Verts should be used)
13th is Effects (which to my knowlage is just fog, its fog thats applyed to the face its self not the world using shaders and some maths to work out how solid it looks(Alpha))
Code: type TFileEffect = record Name : array[0..63] of char; // effect shader brushIndex : integer; // brush that generated this effect visibleSide : integer; // the brush side that ray tests need to clip against (-1 == none) end;
14th is Faces. Note: RBSP version
Code: type TRBSPFace = record textureID : integer; // The index into the texture array effect : integer; // The index for the effects (or -1 = n/a) FaceType : integer; // 1=polygon, 2=patch, 3=mesh, 4=billboard startVertIndex : integer; // The starting index into this face's first vertex numOfVerts : integer; // The number of vertices for this face meshVertIndex : integer; // The index into the first meshvertex numMeshVerts : integer; // The number of mesh vertices unknown1 : array [0..3] of byte; // lightmapStyles unknown2 : array [0..3] of byte; // vertexStyles lightmapID : array [0..3] of integer; // The texture index for the lightmap lMapCorner : array [0..3] of array[0..1] of integer; // The face's lightmap corner in the image lMapSize : array[0..1] of integer; // The size of the lightmap section lMapPos : TVector3f; // The 3D origin of lightmap. lMapVecs : array[0..1] of TVector3f; // The 3D space for s and t unit vectors. Normal : TVector3f; // The face normal. Size : array[0..1] of integer; // The bezier patch dimensions. end;
15th is lightmaps
Code: type TBSPLightmap = record imageBits : array[0..127, 0..127, 0..2] of byte; // The RGB data in a 128x128 image end;
16th is Light Volumes. If im correct there used for the lighting of the Models, i.e weapons, player models, since u can't use Lightmaps. Never implemented or seen it implemented in a Delphi app (hence the C code). Note: RBSP Version
Code: typedef struct { unsigned char ambient[BSP_STYLES][3]; unsigned char diffuse[BSP_STYLES][3]; unsigned char styles[BSP_STYLES]; unsigned char direction[2]; } dgridlight_t;
17th is Vis Data
Code: type TBSPVisData = record numOfClusters : integer; // The number of clusters bytesPerCluster : integer; // The amount of bytes (8 bits) in the cluster's bitset Bitsets : array of byte; // The array of bytes that holds the cluster bitsets end; //Reading it if (lumps[kVisData].length > 0 ) then begin BlockRead(F, clusters.numOfClusters, sizeof(integer)); BlockRead(F, clusters.bytesPerCluster, sizeof(integer)); size := clusters.numOfClusters * clusters.bytesPerCluster; SetLength(clusters.Bitsets, size); BlockRead(F, clusters.Bitsets[0],sizeof(byte)* size); end else SetLength(clusters.Bitsets, 0);
18th is LightArray (RBSP Only), i havn't seen it implemented in any 3rd party app, or seen the Type definition of it.
If anyone ever comes across the COD or EF2 specs plz inform me (There isn't any information i have found on EF2 format, and only some of the lumps of the COD format)
|