Difference between revisions of "Source BSP File Format/Game-Specific"

From Valve Developer Community
Jump to: navigation, search
({{game link|Vindictus}}: Two more structs)
Line 231: Line 231:
 
unsigned int AllowedVerts[10]; // active verticies
 
unsigned int AllowedVerts[10]; // active verticies
 
};</source>
 
};</source>
 +
 
The CDispNeighbor and CDispCornerNeighbors structures have changed as well, once again using ints instead of shorts.
 
The CDispNeighbor and CDispCornerNeighbors structures have changed as well, once again using ints instead of shorts.
 +
 +
 +
The overlay structure also follows the change from short to int:
 +
<source lang="cpp">struct doverlay_t
 +
{
 +
int Id;
 +
int TexInfo;
 +
unsigned int FaceCountAndRenderOrder;
 +
int Ofaces[OVERLAY_BSP_FACE_COUNT];
 +
float U[2];
 +
float V[2];
 +
Vector UVPoints[4];
 +
Vector Origin;
 +
Vector BasisNormal;
 +
};</source>
 +
 +
 +
So does the areaportal structure:
 +
<source lang="cpp">struct dareaportal_t
 +
{
 +
unsigned int portalKey; // binds the area portal to a func_areaportal entity with the same portalnumber key
 +
unsigned int otherarea; // The area this portal looks into.
 +
unsigned int firstClipPortalVert; // Portal geometry.
 +
unsigned int clipPortalVerts;
 +
int planenum;
 +
};</source>
  
  

Revision as of 11:25, 18 February 2013

This page documents some game-specific differences in the BSP file format, compared to the format used for the traditional engine branches.

<Alien Swarm> Alien Swarm and [Portal 2] Portal 2

Both games use a slightly different dbrushside_t structure:

struct dbrushside_t
{
	unsigned short		planenum;	// facing out of the leaf
	short			texinfo;
	short			dispinfo;	// displacement info (BSPVERSION 7)
	byte			bevel;		// is the side a bevel plane? (BSPVERSION 7)
	byte			thin;		// is a thin side?
};

<Dark Messiah of Might and Magic> Dark Messiah of Might and Magic

Dark Messiah maps have a strange version number, it is possibly split into two shorts:

struct dheader_dm_t
{
	int	ident;                // BSP file identifier
	short	version;              // BSP file version (20)
	short	unknown;              // always 4?
	lump_t	lumps[HEADER_LUMPS];  // lump directory array
	int	mapRevision;          // the map's revision (iteration, version) number
};


Static props use a modified StaticPropLumpV6_t structure, which contains additional 72 bytes for unknown purposes at the end:

struct StaticPropLumpV6_dm_t
{
	Vector			m_Origin;
	QAngle			m_Angles;
	unsigned short		m_PropType;
	unsigned short		m_FirstLeaf;
	unsigned short		m_LeafCount;
	unsigned char		m_Solid;
	unsigned char		m_Flags;
	int			m_Skin;
	float			m_FadeMinDist;
	float			m_FadeMaxDist;
	Vector			m_LightingOrigin;
	float			m_flForcedFadeScale;
	unsigned short		m_nMinDXLevel;
	unsigned short		m_nMaxDXLevel;
	byte			m_unknown[72];
};

Furthermore, the DirectX levels seem to have different ranges.


Models using dmodel_t have one additional integer field between origin and headnode:

struct dmodel_dm_t
{
	Vector	mins, maxs;		// bounding box
	Vector	origin;			// for sounds or lights
	int	unknown;		// always 0?
	int	headnode;		// index into node array
	int	firstface, numfaces;	// index into face array
};


Texinfos using texinfo_t have additional 24 bytes between lightmapVecs and flags:

struct texinfo_dm_t
{
	float	textureVecs[2][4];	// [s/t][xyz offset]
	float	lightmapVecs[2][4];	// [s/t][xyz offset] - length is in units of texels/area
	byte	unknown[24];
	int	flags;			// miptex flags	overrides
	int	texdata;		// Pointer to texture name, size, etc.
}

<Left 4 Dead 2> Left 4 Dead 2

The fields in lump_t have a different order:

struct lump_t
{
	int	version;	// lump format version
	int	fileofs;	// offset into file (bytes)
	int	filelen;	// length of lump(bytes)
	char	fourCC[4];	// lump ident code
};

<The Ship> The Ship / Bloody Good Time

Static props use a modified StaticPropLumpV5_t structure, which contains null-padded target name strings.

struct StaticPropLumpV5_ship_t
{
	Vector		m_Origin;
	QAngle		m_Angles;
	unsigned short	m_PropType;
	unsigned short	m_FirstLeaf;
	unsigned short	m_LeafCount;
	unsigned char	m_Solid;
	unsigned char	m_Flags;
	int		m_Skin;
	float		m_FadeMinDist;
	float		m_FadeMaxDist;
	Vector		m_LightingOrigin;
	float		m_flForcedFadeScale;
	char		m_TargetName[128];
};

Vampire: The Masquerade – Bloodlines

Version 17 BSP files contain a substantially modified dface_t structure. The known elements are:

// MAXLIGHTMAPS changed from 4 to 8 
// 4 lightstyle for day + 4 for night = 8 ( nightime lightmapping system )

struct dface_bsp17_t
{
	colorRGBExp32	m_AvgLightColor[MAXLIGHTMAPS]; // For computing lighting information
	unsigned short	planenum;
	byte		side;	// faces opposite to the node's plane direction
	byte		onNode; // 1 of on node, 0 if in leaf
	int		firstedge;		// we must support > 64k edges
	short		numedges;	
	short		texinfo;
	short		dispinfo;
	short		surfaceFogVolumeID;
	byte		styles[MAXLIGHTMAPS];	// lighting info
	byte		day[MAXLIGHTMAPS];		// Nightime lightmapping system
	byte		night[MAXLIGHTMAPS];		// Nightime lightmapping system
	int		lightofs;		// start of [numstyles*surfsize] samples
	float		area;
	int		m_LightmapTextureMinsInLuxels[2];
	int		m_LightmapTextureSizeInLuxels[2];
	int		origFace;    // reference the original face this face was derived from
	unsigned int	smoothingGroups;
};

The extra data seems to be related to lighting of the face, and makes the length of the structure 104 bytes per face. Both the face lump and the original face lump in version 17 files use this structure.

Vindictus

Vindictus uses a different dgamelump_t format:

struct dgamelump_t
{
	int		id;		// gamelump ID
	int		flags;		// flags
	int		version;	// gamelump version
	int		fileofs;	// offset to this gamelump
	int		filelen;	// length
};


Nodes and Leaves are also different, mainly changing to use ints instead of shorts:

struct dnode_t
{
	int		planenum;	// index into plane array
	int		children[2];	// negative numbers are -(leafs + 1), not nodes
	int		mins[3];	// for frustum culling
	int		maxs[3];
	int		firstface;	// index into face array
	int		numfaces;	// counting both sides
	int		unknown;	// seems to always be 0
};

The Leaves structure, among other things, does away with the area field, and flags has its own integer field.

struct dleaf_t
{
	int			contents;		// OR of all brushes (not needed?)
	int			cluster;		// cluster this leaf is in
	int			flags;			// flags
	int			mins[3];		// for frustum culling
	int			maxs[3];
	unsigned int		firstleafface;		// index into leaffaces
	unsigned int		numleaffaces;
	unsigned int		firstleafbrush;		// index into leafbrushes
	unsigned int		numleafbrushes;
	int			leafWaterDataID;	// -1 for not in water
};


Faces use a 72 byte long structure, again the biggest difference is changing from shorts to ints:

struct dface_t
{
	unsigned int	planenum;		// the plane number
	byte		side;			// faces opposite to the node's plane direction
	byte		onNode;			// 1 of on node, 0 if in leaf
	short		unknown0;		// always 0?
	int		firstedge;		// index into surfedges
	int		numedges;		// number of surfedges
	int		texinfo;		// texture info
	int		dispinfo;		// displacement info
	int		surfaceFogVolumeID;	// ?
	byte		styles[4];		// switchable lighting info
	int		lightofs;		// offset into lightmap lump
	float		area;			// face area in units^2
	int		LightmapTextureMinsInLuxels[2];	// texture lighting info
	int		LightmapTextureSizeInLuxels[2];	// texture lighting info
	unsigned int	origFace;		// original face this was split from
	unsigned int	numPrims;		// primitives
	unsigned int	firstPrimID;
	unsigned int	smoothingGroups;	// lightmap smoothing group
};


Brush sides have an identical format, except using ints instead of shorts:

struct dbrushside_t
{
	unsigned int	planenum;
	int		texinfo;
	int		dispinfo;
	int		bevel;
};


Edges are also identical except for using ints:

struct dedge_t
{
	unsigned int	v[2];
};


The displacement info lump is much more complex, doing away with the 176 byte format of the conventional Source engine in favor of a 232 byte structure:

struct ddispinfo_t
{
	Vector			startPosition;		// start position used for orientation
	int			DispVertStart;		// Index into LUMP_DISP_VERTS.
	int			DispTriStart;		// Index into LUMP_DISP_TRIS.
	int			power;			// power - indicates size of surface (2^power	1)
	float			smoothingAngle;		// lighting smoothing angle
	int			unknown0;
	int			contents;		// surface contents
	unsigned int		MapFace;		// Which map face this displacement comes from.
	int			LightmapAlphaStart;	// Index into ddisplightmapalpha.
	int			LightmapSamplePositionStart;	// Index into LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS.
	CDispNeighbor		EdgeNeighbors[4];	// Indexed by NEIGHBOREDGE_ defines.
	CDispCornerNeighbors	CornerNeighbors[4];	// Indexed by CORNER_ defines.
	unsigned int		AllowedVerts[10];	// active verticies
};

The CDispNeighbor and CDispCornerNeighbors structures have changed as well, once again using ints instead of shorts.


The overlay structure also follows the change from short to int:

struct doverlay_t
{
	int		Id;
	int		TexInfo;
	unsigned int	FaceCountAndRenderOrder;
	int		Ofaces[OVERLAY_BSP_FACE_COUNT];
	float		U[2];
	float		V[2];
	Vector		UVPoints[4];
	Vector		Origin;
	Vector		BasisNormal;
};


So does the areaportal structure:

struct dareaportal_t
{
	unsigned int	portalKey;		// binds the area portal to a func_areaportal entity with the same portalnumber key
	unsigned int	otherarea;		// The area this portal looks into.
	unsigned int	firstClipPortalVert;	// Portal geometry.
	unsigned int	clipPortalVerts;
	int		planenum;
};


The LeafFace and LeafBrush lumps also use unsigned ints rather than unsigned shorts.