Skip to content

Instantly share code, notes, and snippets.

@ImanolFotia
Created October 4, 2018 07:07
Show Gist options
  • Save ImanolFotia/eac956e4f4da3164be283d6791ca9365 to your computer and use it in GitHub Desktop.
Save ImanolFotia/eac956e4f4da3164be283d6791ca9365 to your computer and use it in GitHub Desktop.
#pragma once
#include <glm/glm.hpp>
//Check out https://developer.valvesoftware.com/wiki/Source_BSP_File_Format for further reference
// little-endian "VBSP" 0x50534256
#define IDBSPHEADER (('P' << 24) + ('S' << 16) + ('B' << 8) + 'V')
#define LZMA_ID (('A' << 24) | ('M' << 16) | ('Z' << 8) | ('L'))
#define HEADER_LUMPS 64
#define MAX_MAP_VISIBILITY 0x1000000
#define OVERLAY_BSP_FACE_COUNT 64
#define MAX_BRUSH_LIGHTMAP_DIM_WITHOUT_BORDER 32
// This is one more than what vbsp cuts for to allow for rounding errors
#define MAX_BRUSH_LIGHTMAP_DIM_INCLUDING_BORDER 35
// We can have larger lightmaps on displacements
#define MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER 125
#define MAX_DISP_LIGHTMAP_DIM_INCLUDING_BORDER 128
// This is the actual max.. (change if you change the brush lightmap dim or disp lightmap dim
#define MAX_LIGHTMAP_DIM_WITHOUT_BORDER MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER
#define MAX_LIGHTMAP_DIM_INCLUDING_BORDER MAX_DISP_LIGHTMAP_DIM_INCLUDING_BORDER
#define MAX_LIGHTSTYLES 64
// upper design bounds
#define MIN_MAP_DISP_POWER 2 // Minimum and maximum power a displacement can be.
#define MAX_MAP_DISP_POWER 4
#define MAX_MAP_OVERLAYS 512
#define MAX_DISP_CORNER_NEIGHBORS 4
#define MAX_MAP_MODELS 1024
#define MAX_MAP_BRUSHES 8192
#define MAX_MAP_ENTITIES 8192
#define MAX_MAP_TEXINFO 12288
#define MAX_MAP_TEXDATA 2048
#define MAX_MAP_DISPINFO 2048
#define MAX_MAP_DISP_VERTS ( MAX_MAP_DISPINFO * ((1<<MAX_MAP_DISP_POWER)+1) * ((1<<MAX_MAP_DISP_POWER)+1) )
#define MAX_MAP_DISP_TRIS ( (1 << MAX_MAP_DISP_POWER) * (1 << MAX_MAP_DISP_POWER) * 2 )
#define MAX_DISPVERTS NUM_DISP_POWER_VERTS( MAX_MAP_DISP_POWER )
#define MAX_DISPTRIS NUM_DISP_POWER_TRIS( MAX_MAP_DISP_POWER )
#define MAX_MAP_AREAS 256
#define MAX_MAP_AREA_BYTES (MAX_MAP_AREAS/8)
#define MAX_MAP_AREAPORTALS 1024
// Planes come in pairs, thus an even number.
#define MAX_MAP_PLANES 65536
#define MAX_MAP_NODES 65536
#define MAX_MAP_BRUSHSIDES 65536
#define MAX_MAP_LEAFS 65536
#define MAX_MAP_VERTS 65536
#define MAX_MAP_VERTNORMALS 256000
#define MAX_MAP_VERTNORMALINDICES 256000
#define MAX_MAP_FACES 65536
#define MAX_MAP_LEAFFACES 65536
#define MAX_MAP_LEAFBRUSHES 65536
#define MAX_MAP_PORTALS 65536
#define MAX_MAP_CLUSTERS 65536
#define MAX_MAP_LEAFWATERDATA 32768
#define MAX_MAP_PORTALVERTS 128000
#define MAX_MAP_EDGES 256000
#define MAX_MAP_SURFEDGES 512000
#define MAX_MAP_LIGHTING 0x1000000
#define MAX_MAP_VISIBILITY 0x1000000 // increased BSPVERSION 7
#define MAX_MAP_TEXTURES 1024
#define MAX_MAP_WORLDLIGHTS 8192
#define MAX_MAP_CUBEMAPSAMPLES 1024
#define MAX_MAP_OVERLAYS 512
#define MAX_MAP_WATEROVERLAYS 16384
#define MAX_MAP_TEXDATA_STRING_DATA 256000
#define MAX_MAP_TEXDATA_STRING_TABLE 65536
// this is stuff for trilist/tristrips, etc.
#define MAX_MAP_PRIMITIVES 32768
#define MAX_MAP_PRIMVERTS 65536
#define MAX_MAP_PRIMINDICES 65536
class SourceBSP
{
typedef Vector glm::vec3;
typedef byte char;
typedef Color glm::vec4;
enum GAME_VERSIONS
{
Vampire_The_Masquerade_Bloodlines = 17, //modified: dface_t
Half_Life_2_Beta = 17, //leaked beta
Half_Life_2_Beta = 18, //leaked beta
Sin Episodes = 19,
Half_Life_2 = 19,
Half_Life_2 = 20, //19 when released, partially 20 since Source 2007/2009 update
Half_Life_2_Deathmatch = 19,
Half_Life_2_Deathmatch = 20, //19 when released, partially 20 since Source 2007/2009 update
Counter_Strike_Source = 19,
Counter_Strike_Source = 20,
Day_of_Defeat_Source = 19,
Day_of_Defeat_Source = 20,
Half_Life_2_Episode_One = 20,
Half_Life_2_Episode_Two = 20,
Half_Life_2_Lost_Coast = 20,
Garrys_Mod = 20,
Team_Fortress_2 = 20, //modified ( newly compiled maps ): StaticPropLump_t ( version = 10 ), LZMA compressed game lumps, entity info and PAK files
Portal = 20,
Left_4_Dead = 20, //modified: StaticPropLump_t ( version = 8 ) and dworldlight_t
Zeno_Clash = 20, //modified: StaticPropLump_t ( version = 7 )
Dark_Messiah = 20, //modified: dheader_t, StaticPropLump_t, texinfo_t, dgamelump_t, dmodel_t
Vindictus = 20, //many modified structs
The_Ship = 20, //modified: StaticPropLump_t
Bloody_Good_Time = 20, //modified: StaticPropLump_t
Black_Mesa = 20, //modified: StaticPropLump_t ( version = 11 )
Left_4_Dead_2 = 21, //modified: lump_t, old dbrushside_t
Alien_Swarm = 21,
Portal_2 = 21, //modified: StaticPropLump_t ( version = 9 ), dbrushside_t and other structs
Counter_Strike_Global_Offensive = 21, //modified: StaticPropLump_t ( version = 10 )
Dear_Esther = 21, //modified: StaticPropLump_t
Insurgency = 21,
The_Stanley_Parable = 21,
The_Beginners_Guide = 21,
Dota_2 = 22, //early betas, modified: dbrushside_t, ddispinfo_t
Dota_2 = 23, //modified: dbrushside_t, ddispinfo_t, doverlay_t
Contagion = 27,
Titanfall = 29 //heavily modified
}
enum LUMPS
{
LUMP_ENTITIES = 0, //Map entities
LUMP_PLANES = 1, //Plane array
LUMP_TEXDATA = 2, //Index to texture names
LUMP_VERTEXES = 3, //Vertex array
LUMP_VISIBILITY = 4, //Compressed visibility bit arrays
LUMP_NODES = 5, //BSP tree nodes
LUMP_TEXINFO = 6, //Face texture array
LUMP_FACES = 7, //Face array
LUMP_LIGHTING = 8, //Lightmap samples
LUMP_OCCLUSION = 9, //Occlusion polygons and vertices
LUMP_LEAFS = 10, //BSP tree leaf nodes
LUMP_FACEIDS = 11, //Correlates between dfaces and Hammer face IDs. Also used as random seed for detail prop placement.
LUMP_EDGES = 12, //Edge array
LUMP_SURFEDGES = 13, //Index of edges
LUMP_MODELS = 14, //Brush models (geometry of brush entities)
LUMP_WORLDLIGHTS = 15, //Internal world lights converted from the entity lump
LUMP_LEAFFACES = 16, //Index to faces in each leaf
LUMP_LEAFBRUSHES = 17, //Index to brushes in each leaf
LUMP_BRUSHES = 18, //Brush array
LUMP_BRUSHSIDES = 19, //Brushside array
LUMP_AREAS = 20, //Area array
LUMP_AREAPORTALS = 21, //Portals between areas
LUMP_PORTALS = 22, //Polygons defining the boundary between adjacent leaves?
LUMP_UNUSED0 = 22, //Unused
LUMP_PROPCOLLISION = 22, //Static props convex hull lists Source 2009
LUMP_CLUSTERS = 23, //Leaves that are enterable by the player
LUMP_UNUSED1 = 23, //Unused Source 2007
LUMP_PROPHULLS = 23, //Static prop convex hulls Source 2009
LUMP_PORTALVERTS = 24, //Vertices of portal polygons
LUMP_UNUSED2 = 24, //Unused Source 2007
LUMP_PROPHULLVERTS = 24, //Static prop collision vertices Source 2009
LUMP_CLUSTERPORTALS = 25, //Polygons defining the boundary between adjacent clusters?
LUMP_UNUSED3 = 25, //Unused Source 2007
LUMP_PROPTRIS = 25, //Static prop per hull triangle index start/count Source 2009
LUMP_DISPINFO = 26, //Displacement surface array
LUMP_ORIGINALFACES = 27, //Brush faces array before splitting
LUMP_PHYSDISP = 28, //Displacement physics collision data Source 2007
LUMP_PHYSCOLLIDE = 29, //Physics collision data
LUMP_VERTNORMALS = 30, //Face plane normals
LUMP_VERTNORMALINDICES = 31, //Face plane normal index array
LUMP_DISP_LIGHTMAP_ALPHAS = 32, //Displacement lightmap alphas (unused/empty since Source 2006)
LUMP_DISP_VERTS = 33, //Vertices of displacement surface meshes
LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS = 34, //Displacement lightmap sample positions
LUMP_GAME_LUMP = 35, //Game-specific data lump
LUMP_LEAFWATERDATA = 36, //Data for leaf nodes that are inside water
LUMP_PRIMITIVES = 37, //Water polygon data
LUMP_PRIMVERTS = 38, //Water polygon vertices
LUMP_PRIMINDICES = 39, //Water polygon vertex index array
LUMP_PAKFILE = 40, //Embedded uncompressed Zip-format file
LUMP_CLIPPORTALVERTS = 41, //Clipped portal polygon vertices
LUMP_CUBEMAPS = 42, //env_cubemap location array
LUMP_TEXDATA_STRING_DATA = 43, //Texture name data
LUMP_TEXDATA_STRING_TABLE = 44, //Index array into texdata string data
LUMP_OVERLAYS = 45, //info_overlay data array
LUMP_LEAFMINDISTTOWATER = 46, //Distance from leaves to water
LUMP_FACE_MACRO_TEXTURE_INFO = 47, //Macro texture info for faces
LUMP_DISP_TRIS = 48, //Displacement surface triangles
LUMP_PHYSCOLLIDESURFACE = 49, //Compressed win32-specific Havok terrain surface collision data. Deprecated and no longer used.
LUMP_PROP_BLOB = 49, //Static prop triangle and string data Source 2009
LUMP_WATEROVERLAYS = 50, //Source 2006 info_overlay's on water faces?
LUMP_LIGHTMAPPAGES = 51, //Alternate lightdata implementation for Xbox Source 2006
LUMP_LEAF_AMBIENT_INDEX_HDR = 51, //Index of LUMP_LEAF_AMBIENT_LIGHTING_HDR Source 2007
LUMP_LIGHTMAPPAGEINFOS = 52, //Alternate lightdata indices for Xbox Source 2006
LUMP_LEAF_AMBIENT_INDEX = 52, //Index of LUMP_LEAF_AMBIENT_LIGHTING Source 2007
LUMP_LIGHTING_HDR = 53, //HDR lightmap samples
LUMP_WORLDLIGHTS_HDR = 54, //Internal HDR world lights converted from the entity lump
LUMP_LEAF_AMBIENT_LIGHTING_HDR = 55, //Per-leaf ambient light samples (HDR)
LUMP_LEAF_AMBIENT_LIGHTING = 56, //Per-leaf ambient light samples (LDR)
LUMP_XZIPPAKFILE = 57, //XZip version of pak file for Xbox. Deprecated.
LUMP_FACES_HDR = 58, //HDR maps may have different face data
LUMP_MAP_FLAGS = 59, //Extended level-wide flags. Not present in all levels.
LUMP_OVERLAY_FADES = 60, //Fade distances for overlays
LUMP_OVERLAY_SYSTEM_LEVELS = 61, //System level settings (min/max CPU & GPU to render this overlay)
LUMP_PHYSLEVEL = 62, //To do
LUMP_DISP_MULTIBLEND = 63 //Displacement multiblend info
}
enum CONTENTS
{
CONTENTS_EMPTY = 0, //No contents
CONTENTS_SOLID = 0x1, //an eye is never valid in a solid
CONTENTS_WINDOW = 0x2, //translucent, but not watery (glass)
CONTENTS_AUX = 0x4,
CONTENTS_GRATE = 0x8, //alpha-tested "grate" textures. Bullets/sight pass through, but solids don't
CONTENTS_SLIME = 0x10,
CONTENTS_WATER = 0x20,
CONTENTS_MIST = 0x40,
CONTENTS_OPAQUE = 0x80, //block AI line of sight
CONTENTS_TESTFOGVOLUME = 0x100, //things that cannot be seen through (may be non-solid though)
CONTENTS_UNUSED = 0x200, //unused
CONTENTS_UNUSED6 = 0x400, //unused
CONTENTS_TEAM1 = 0x800, //per team contents used to differentiate collisions between players and objects on different teams
CONTENTS_TEAM2 = 0x1000,
CONTENTS_IGNORE_NODRAW_OPAQUE = 0x2000, //ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW
CONTENTS_MOVEABLE = 0x4000, //hits entities which are MOVETYPE_PUSH (doors, plats, etc.)
CONTENTS_AREAPORTAL = 0x8000, //remaining contents are non-visible, and don't eat brushes
CONTENTS_PLAYERCLIP = 0x10000,
CONTENTS_MONSTERCLIP = 0x20000,
CONTENTS_CURRENT_0 = 0x40000, //currents can be added to any other contents, and may be mixed
CONTENTS_CURRENT_90 = 0x80000,
CONTENTS_CURRENT_180 = 0x100000,
CONTENTS_CURRENT_270 = 0x200000,
CONTENTS_CURRENT_UP = 0x400000,
CONTENTS_CURRENT_DOWN = 0x800000,
CONTENTS_ORIGIN = 0x1000000, //removed before bsping an entity
CONTENTS_MONSTER = 0x2000000, //should never be on a brush, only in game
CONTENTS_DEBRIS = 0x4000000,
CONTENTS_DETAIL = 0x8000000, //brushes to be added after vis leafs
CONTENTS_TRANSLUCENT = 0x10000000, //auto set if any surface has trans
CONTENTS_LADDER = 0x20000000,
CONTENTS_HITBOX = 0x40000000
}
enum SURFACES
{
SURF_LIGHT = 0x1 //value will hold the light strength
SURF_SKY2D = 0x2 //don't draw, indicates we should skylight + draw 2d sky but not draw the 3D skybox
SURF_SKY = 0x4 //don't draw, but add to skybox
SURF_WARP = 0x8 //turbulent water warp
SURF_TRANS = 0x10 //texture is translucent
SURF_NOPORTAL = 0x20 //the surface can not have a portal placed on it
SURF_TRIGGER = 0x40 //FIXME: This is an xbox hack to work around elimination of trigger surfaces, which breaks occluders
SURF_NODRAW = 0x80 //don't bother referencing the texture
SURF_HINT = 0x100 //make a primary bsp splitter
SURF_SKIP = 0x200 //completely ignore, allowing non-closed brushes
SURF_NOLIGHT = 0x400 //Don't calculate light
SURF_BUMPLIGHT = 0x800 //calculate three lightmaps for the surface for bumpmapping
SURF_NOSHADOWS = 0x1000 //Don't receive shadows
SURF_NODECALS = 0x2000 //Don't receive decals
SURF_NOCHOP = 0x4000 //Don't subdivide patches on this surface
SURF_HITBOX = 0x8000 //surface is part of a hitbox
}
enum DISP_FLAGS
{
DISPTRI_TAG_SURFACE = 0x1,
DISPTRI_TAG_WALKABLE = 0x2,
DISPTRI_TAG_BUILDABLE = 0x4,
DISPTRI_FLAG_SURFPROP1 = 0x8,
DISPTRI_FLAG_SURFPROP2 = 0x10
}
struct dheader_t
{
int ident;
int version;
lump_t lump[HEADER_LUMPS];
int revision;
};
struct lump_t
{
int offset;
int lenght;
int version;
char fourCC[4];
};
struct lzma_header_t
{
unsigned int id;
unsigned int actualSize; //Always little endian
unsigned int lzmaSize; //Always little endian
unsigned char properties[5];
};
struct dplane_t
{
Vector normal;
float dist; //from origin
int type;
};
struct dedge_t
{
unsigned short v[2];
};
struct dface_t
{
unsigned short planenum;
byte side;
byte onNode; //1 node, 0 leaf
int firstedge;
short numedges;
short texinfo;
short dispinfo;
short surfaceFogVolumeID;
byte styles[4];
int lightofs;
float area; // face area in units^2
int LightmapTextureMinsInLuxels[2];
int LightmapTextureSizeInLuxels[2];
int origface; // parent face
unsigned short numPrims; //# primitives
unsigned short firstPrimID;
unsigned int smoothingGroups;
};
struct dbrush_t
{
int firstside;
int numsides;
int contents;
};
struct dbrushside_t
{
unsigned short planenum;
short texinfo;
short dispinfo;
short bevel;
};
struct dnode_t
{
int planenum;
int children[2];
short mins[3];
short maxs[3];
unsigned short firstface;
unsigned short numfaces;
short area;
short padding;
};
struct dleaf_t
{
int contents;
short cluster;
short area;
short flags;
short mins[3];
short maxs[3];
unsigned short firstleafface;
unsigned short numleaffaces;
unsigned short firstleafbrush;
unsigned short numleafbrushes;
short leafWaterDataID; // -1 for not in water
//!!! NOTE: for maps of version 19 or lower uncomment this block
/*
CompressedLightCube ambientLighting; // Precaculated light info for entities.
short padding; // padding to 4-byte boundary*/
};
struct texinfo_t
{
float textureVecs[2][4]; // [s/t][xyz offset]
float lightmapVecs[2][4]; // [s/t][xyz offset]
int flags;
int texdata;
};
struct dtexdata_t
{
Vector reflectivity;
int nameStringTableID;
int width;
int height;
int view_width;
int view_height;
};
struct dmodel_t
{
Vector mins;
Vector maxs;
Vector origin;
int headnode;
int firstface;
int numfaces;
}
struct dvis_t
{
int numclusters;
int byteofs[numclusters][2];
};
struct dgamelumpheader_t
{
int lumpCount;
dgamelump_t gamelump[lumpCount];
};
struct dgamelump_t
{
int id;
unsigned short flags;
unsigned short version;
int fileofs;
int filelen;
};
struct StaticPropDictLump_t
{
int dicEntries;
char name[dicEntries];
};
struct StaticPropLeafLump_t
{
int leafEntries;
unsigned short leaf[leafEntries];
};
struct StaticPropLump_t
{
Vector Origin;
Vector Angles;
float UniformScale;
unsigned short PropType;
unsigned short FirstLeaf;
unsigned short LeafCount;
unsigned char Solid;
unsigned char Flags;
int Skin;
float FadeMinDist;
float FadeMaxDist;
Vector LightingOrigin;
float ForcedFadeScale;
unsigned short MinDXLevel;
unsigned short MaxDXLevel;
unsigned char MinCPULevel;
unsigned char MaxCPULevel;
unsigned char MinGPULevel;
unsigned char MaxGPULevel;
Color DiffuseModulation;
float unknown;
bool DisableX360;
};
struct ddispinfo_t
{
Vector startPosition;
int DispVertStart;
int DistTriStart;
int power;
int minTess;
float smoothingAngle;
int content;
unsigned short MapFace;
int LightmapAlphaStart;
int LightmapSamplePositionStart;
CDispNeighbor EdgeNeighbors[4]; // Indexed by NEIGHBOREDGE_ defines.
CDispCornerNeighbor CornerNeighbors[4]; // Indexed by CORNER_ defines.
unsigned int AllowedVerts[10];
};
struct CDispNeighbor
{
CDispSubNeighbor m_SubNeighbors[2];
};
struct CDispCornerNeighbors
{
unsigned short m_Neighbors[MAX_DISP_CORNER_NEIGHBORS]; // indices of neighbors.
unsigned char m_nNeighbors;
};
struct CDispSubNeighbor
{
unsigned short m_iNeighbor; // This indexes into ddispinfos.
// 0xFFFF if there is no neighbor here.
unsigned char m_NeighborOrientation; // (CCW) rotation of the neighbor wrt this displacement.
// These use the NeighborSpan type.
unsigned char m_Span; // Where the neighbor fits onto this side of our displacement.
unsigned char m_NeighborSpan; // Where we fit onto our neighbor.
};
struct dDispVert
{
Vector vec;
float dist;
float alpha;
};
struct dDispTri
{
unsigned short Tags;
};
struct dcubemapsample_t
{
int origin[3];
int size;
};
struct doverlay_t
{
int Id;
short TexInfo;
unsigned short FaceCountAndRenderOrder;
int Ofaces[OVERLAY_BSP_FACE_COUNT];
float U[2];
float V[2];
Vector UVPoints[4];
Vector Origin;
Vector BasisNormal;
};
struct ColorRGBEExp32
{
byte r, g, b;
signed char exponent;
};
struct dleafambientlighting_t
{
CompressedLightCube cube;
byte x, y, z;
byte pad;
};
struct CompressedLightCube
{
ColorRGBExp32 m_Color[6];
};
struct dleafambientindex_t
{
unsigned short ambientSamplerCount;
unsigned short firstAmbientSample;
};
struct soccluder_t
{
int count;
doccluderdata_t data[count];
int polyDataCount;
doccluderpolydata_t polyData[polyDataCount];
int vertexIndexCount;
int vertexIndices[vertexIndexCount];
};
struct doccluderdata_t
{
int flags;
int firstpoly;
int polycount;
Vector mins;
Vector maxs;
int area;
};
struct doccluderpolydata_t
{
int firstvertexindex;
int vertexcount;
int planenum;
};
struct dphysmodel_t
{
int modelIndex;
int dataSize;
int keyDataSize;
int solidCount;
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment