I made this to get my head around the structure of a BSP file and its lumps.
Updates:
- 2023-12-20: now has data from all 15 lumps
- 2023-12-22: cleaned up. lump references explicitly marked, and implied to be index into lump struct
So basically, the highest level data is the models lump. Its items have indices into the BSP tree and to the faces that comprise the model. You can safely and completely bypass the BSP traversal by directly retrieving the faces, but that means you're drawing absolutely everything. The world is the first BSP model, and every brush entity is its own BSP model referenced by its index into this lump.
The BSP tree has a lot of academic literature so I'll just skip it.
One unique property BSP leaf is the contents, describing whether the volume is air, water, ladder, etc. The marksurfaces info translates to face entries. There doesn't seem to be an offset of leafs from the Model struct so tracking the sum of all previous models might be required.
A face defines a plane, its edges, texture information, and lighting style. There is only a pointer into the lightmap data; the exact shape and size of the data is inferred from the plane, its closest axial orientation, texinfo vectors, and the styles (non-255 value means there's 1 lightstyle of the calculated size, up to 4 lightmaps)
An entity can have the model reference the internal BSP model of a BSP file with the
*N
notation. Interestingly it can also reference external BSPs, in which case it'd load only model 0 of that BSP afaik.
This is just tentative information as of writing. My end goal is to understand enough to be able to completely translate a BSP file into a 3D scene for rendering. I would update this page as I learn things as I go.
References
But really, reading the BSP specs and how a lot of the struct fields are indices into the next struct really reads like relational model of a db, and with 14 lumps interacting this way I really, really needed a visual aid to understand how it all relates with each other, which strangely for the 27+ years of BSP's existence has not existed in any form. Hence the chart, and this journo entry I made to put it in.
https://www.youtube.com/@MattsRamblings
PVS from the top
https://www.youtube.com/watch?v=TMeUxF4mHJA
You might find this code helpful.
https://www.codeproject.com/Articles/32751/Half-Life-Game-Level-Viewer