text: //========= Copyright Valve Corporation, All rights reserved. ============//
  //
  // Purpose: Defines and structures for the BSP file format.
  //
  // $NoKeywords: $
  //=============================================================================//
  
  #ifndef BSPFILE_H
  #define BSPFILE_H
  #pragma once
  
  #ifndef MATHLIB_H
  #include "mathlib/mathlib.h"
  #endif
  
  #include "datamap.h"
  #include "mathlib/bumpvects.h"
  #include "mathlib/compressed_light_cube.h"
  
  // little-endian "VBSP"
  #define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'V')		
  
  // MINBSPVERSION is the minimum acceptable version.  The engine will load MINBSPVERSION through BSPVERSION
  #define MINBSPVERSION 19
  #define BSPVERSION 20
  
  
  // This needs to match the value in gl_lightmap.h
  // Need to dynamically allocate the weights and light values in radial_t to make this variable.
  #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	
  
  // Max # of neighboring displacement touching a displacement's corner.
  #define MAX_DISP_CORNER_NEIGHBORS	4
  
  #define NUM_DISP_POWER_VERTS(power)	( ((1 << (power)) + 1) * ((1 << (power)) + 1) )
  #define NUM_DISP_POWER_TRIS(power)	( (1 << (power)) * (1 << (power)) * 2 )
  
  #if !defined( BSP_USE_LESS_MEMORY )
  // Common limits
  // leaffaces, leafbrushes, planes, and verts are still bounded by
  // 16 bit short limits
  #define	MAX_MAP_MODELS					1024
  #define	MAX_MAP_BRUSHES					8192
  #define	MAX_MAP_ENTITIES				65536
  #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				65536
  #define MAX_MAP_CUBEMAPSAMPLES			1024
  #define MAX_MAP_OVERLAYS				8192
  #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
  
  #else
  
  // Xbox 360 - Force static arrays to be very small
  #define	MAX_MAP_MODELS					2
  #define	MAX_MAP_BRUSHES					2
  #define	MAX_MAP_ENTITIES				2
  #define	MAX_MAP_TEXINFO					2
  #define MAX_MAP_TEXDATA					2
  #define MAX_MAP_DISPINFO				2
  #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					2
  #define MAX_MAP_AREA_BYTES				2
  #define	MAX_MAP_AREAPORTALS				2
  #define	MAX_MAP_PLANES					2
  #define	MAX_MAP_NODES					2
  #define	MAX_MAP_BRUSHSIDES				2
  #define	MAX_MAP_LEAFS					2
  #define	MAX_MAP_VERTS					2
  #define MAX_MAP_VERTNORMALS				2
  #define MAX_MAP_VERTNORMALINDICES		2
  #define	MAX_MAP_FACES					2
  #define	MAX_MAP_LEAFFACES				2
  #define	MAX_MAP_LEAFBRUSHES				2
  #define	MAX_MAP_PORTALS					2
  #define MAX_MAP_CLUSTERS				2
  #define MAX_MAP_LEAFWATERDATA			2
  #define MAX_MAP_PORTALVERTS				2
  #define	MAX_MAP_EDGES					2
  #define	MAX_MAP_SURFEDGES				2
  #define	MAX_MAP_LIGHTING				2
  #define	MAX_MAP_VISIBILITY				2
  #define	MAX_MAP_TEXTURES				2
  #define MAX_MAP_WORLDLIGHTS				2
  #define MAX_MAP_CUBEMAPSAMPLES			2
  #define MAX_MAP_OVERLAYS				2 
  #define MAX_MAP_WATEROVERLAYS			2
  #define MAX_MAP_TEXDATA_STRING_DATA		2
  #define MAX_MAP_TEXDATA_STRING_TABLE	2
  #define MAX_MAP_PRIMITIVES				2
  #define MAX_MAP_PRIMVERTS				2
  #define MAX_MAP_PRIMINDICES				2
  
  #endif // BSP_USE_LESS_MEMORY
  
  // key / value pair sizes
  #define	MAX_KEY		32
  #define	MAX_VALUE	1024
  
  
  // ------------------------------------------------------------------------------------------------ //
  // Displacement neighbor rules
  // ------------------------------------------------------------------------------------------------ //
  //
  // Each displacement is considered to be in its own space:
  //
  //               NEIGHBOREDGE_TOP
  //
  //                   1 --- 2
  //                   |     |
  // NEIGHBOREDGE_LEFT |     | NEIGHBOREDGE_RIGHT
  //                   |     |
  //                   0 --- 3
  //
  //   			NEIGHBOREDGE_BOTTOM
  //
  //
  // Edge edge of a displacement can have up to two neighbors. If it only has one neighbor
  // and the neighbor fills the edge, then SubNeighbor 0 uses CORNER_TO_CORNER (and SubNeighbor 1
  // is undefined).
  //
  // CORNER_TO_MIDPOINT means that it spans [bottom edge,midpoint] or [left edge,midpoint] depending
  // on which edge you're on.
  //
  // MIDPOINT_TO_CORNER means that it spans [midpoint,top edge] or [midpoint,right edge] depending
  // on which edge you're on.
  //
  // Here's an illustration (where C2M=CORNER_TO_MIDPOINT and M2C=MIDPOINT_TO_CORNER
  //
  //
  //				 C2M			  M2C
  //
  //       1 --------------> x --------------> 2
  //
  //       ^                                   ^
  //       |                                   |
  //       |                                   |
  //  M2C  |                                   |	M2C
  //       |                                   |
  //       |                                   |
  //
  //       x                 x                 x 
  //
  //       ^                                   ^
  //       |                                   |
  //       |                                   |
  //  C2M  |                                   |	C2M
  //       |                                   |
  //       |                                   |
  // 
  //       0 --------------> x --------------> 3
  //
  //               C2M			  M2C
  //
  //
  // The CHILDNODE_ defines can be used to refer to a node's child nodes (this is for when you're
  // recursing into the node tree inside a displacement):
  //
  // ---------
  // |   |   |
  // | 1 | 0 |
  // |   |   |
  // |---x---|
  // |   |   |
  // | 2 | 3 |
  // |   |   |
  // ---------
  // 
  // ------------------------------------------------------------------------------------------------ //
  
  // These can be used to index g_ChildNodeIndexMul.
  enum
  {
  	CHILDNODE_UPPER_RIGHT=0,
  	CHILDNODE_UPPER_LEFT=1,
  	CHILDNODE_LOWER_LEFT=2,
  	CHILDNODE_LOWER_RIGHT=3
  };
  
  
  // Corner indices. Used to index m_CornerNeighbors.
  enum
  {
  	CORNER_LOWER_LEFT=0,
  	CORNER_UPPER_LEFT=1,
  	CORNER_UPPER_RIGHT=2,
  	CORNER_LOWER_RIGHT=3
  };
  
  
  // These edge indices must match the edge indices of the CCoreDispSurface.
  enum
  {
  	NEIGHBOREDGE_LEFT=0,
  	NEIGHBOREDGE_TOP=1,
  	NEIGHBOREDGE_RIGHT=2,
  	NEIGHBOREDGE_BOTTOM=3
  };
  
  
  // These denote where one dispinfo fits on another.
  // Note: tables are generated based on these indices so make sure to update
  //       them if these indices are changed.
  typedef enum
  {
  	CORNER_TO_CORNER=0,
  	CORNER_TO_MIDPOINT=1,
  	MIDPOINT_TO_CORNER=2
  } NeighborSpan;
  
  
  // These define relative orientations of displacement neighbors.
  typedef enum
  {
  	ORIENTATION_CCW_0=0,
  	ORIENTATION_CCW_90=1,
  	ORIENTATION_CCW_180=2,
  	ORIENTATION_CCW_270=3
  } NeighborOrientation;
  
  
  //=============================================================================
  
  enum
  {
  	LUMP_ENTITIES					= 0,	// *
  	LUMP_PLANES						= 1,	// *
  	LUMP_TEXDATA					= 2,	// *
  	LUMP_VERTEXES					= 3,	// *
  	LUMP_VISIBILITY					= 4,	// *
  	LUMP_NODES						= 5,	// *
  	LUMP_TEXINFO					= 6,	// *
  	LUMP_FACES						= 7,	// *
  	LUMP_LIGHTING					= 8,	// *
  	LUMP_OCCLUSION					= 9,
  	LUMP_LEAFS						= 10,	// *
  	LUMP_FACEIDS					= 11,
  	LUMP_EDGES						= 12,	// *
  	LUMP_SURFEDGES					= 13,	// *
  	LUMP_MODELS						= 14,	// *
  	LUMP_WORLDLIGHTS				= 15,	// 
  	LUMP_LEAFFACES					= 16,	// *
  	LUMP_LEAFBRUSHES				= 17,	// *
  	LUMP_BRUSHES					= 18,	// *
  	LUMP_BRUSHSIDES					= 19,	// *
  	LUMP_AREAS						= 20,	// *
  	LUMP_AREAPORTALS				= 21,	// *
  	LUMP_UNUSED0					= 22,
  	LUMP_UNUSED1					= 23,
  	LUMP_UNUSED2					= 24,
  	LUMP_UNUSED3					= 25,
  	LUMP_DISPINFO					= 26,
  	LUMP_ORIGINALFACES				= 27,
  	LUMP_PHYSDISP					= 28,
  	LUMP_PHYSCOLLIDE				= 29,
  	LUMP_VERTNORMALS				= 30,
  	LUMP_VERTNORMALINDICES			= 31,
  	LUMP_DISP_LIGHTMAP_ALPHAS		= 32,
  	LUMP_DISP_VERTS					= 33,		// CDispVerts
  	LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS = 34,	// For each displacement
  												//     For each lightmap sample
  												//         byte for index
  												//         if 255, then index = next byte + 255
  												//         3 bytes for barycentric coordinates
  	// The game lump is a method of adding game-specific lumps
  	// FIXME: Eventually, all lumps could use the game lump system
  	LUMP_GAME_LUMP					= 35,
  	LUMP_LEAFWATERDATA				= 36,
  	LUMP_PRIMITIVES					= 37,
  	LUMP_PRIMVERTS					= 38,
  	LUMP_PRIMINDICES				= 39,
  	// A pak file can be embedded in a .bsp now, and the file system will search the pak
  	//  file first for any referenced names, before deferring to the game directory 
  	//  file system/pak files and finally the base directory file system/pak files.
  	LUMP_PAKFILE					= 40,
  	LUMP_CLIPPORTALVERTS			= 41,
  	// A map can have a number of cubemap entities in it which cause cubemap renders
  	// to be taken after running vrad.
  	LUMP_CUBEMAPS					= 42,
  	LUMP_TEXDATA_STRING_DATA		= 43,
  	LUMP_TEXDATA_STRING_TABLE		= 44,
  	LUMP_OVERLAYS					= 45,
  	LUMP_LEAFMINDISTTOWATER			= 46,
  	LUMP_FACE_MACRO_TEXTURE_INFO	= 47,
  	LUMP_DISP_TRIS					= 48,
  	LUMP_PHYSCOLLIDESURFACE			= 49,	// deprecated.  We no longer use win32-specific havok compression on terrain
  	LUMP_WATEROVERLAYS              = 50,
  	LUMP_LEAF_AMBIENT_INDEX_HDR		= 51,	// index of LUMP_LEAF_AMBIENT_LIGHTING_HDR
  	LUMP_LEAF_AMBIENT_INDEX         = 52,	// index of LUMP_LEAF_AMBIENT_LIGHTING
  
  	// optional lumps for HDR
  	LUMP_LIGHTING_HDR				= 53,
  	LUMP_WORLDLIGHTS_HDR			= 54,
  	LUMP_LEAF_AMBIENT_LIGHTING_HDR	= 55,	// NOTE: this data overrides part of the data stored in LUMP_LEAFS.
  	LUMP_LEAF_AMBIENT_LIGHTING		= 56,	// NOTE: this data overrides part of the data stored in LUMP_LEAFS.
  
  	LUMP_XZIPPAKFILE				= 57,   // deprecated. xbox 1: xzip version of pak file
  	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
  };
  
  
  // Lumps that have versions are listed here
  enum
  {
  	LUMP_LIGHTING_VERSION          = 1,
  	LUMP_FACES_VERSION             = 1,
  	LUMP_OCCLUSION_VERSION         = 2,
  	LUMP_LEAFS_VERSION			   = 1,
  	LUMP_LEAF_AMBIENT_LIGHTING_VERSION = 1,
  };
  
  
  #define	HEADER_LUMPS		64
  
  #include "zip_uncompressed.h"
  
  struct lump_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int		fileofs, filelen;
  	int		version;		// default to zero
  	// this field was char fourCC[4] previously, but was unused, favoring the LUMP IDs above instead. It has been
  	// repurposed for compression.  0 implies the lump is not compressed.
  	int		uncompressedSize; // default to zero
  };
  
  
  struct dheader_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int			ident;
  	int			version;
  	lump_t		lumps[HEADER_LUMPS];
  	int			mapRevision;				// the map's revision (iteration, version) number (added BSPVERSION 6)
  };
  
  // level feature flags
  #define LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_NONHDR 0x00000001	// was processed by vrad with -staticproplighting, no hdr data
  #define LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_HDR    0x00000002   // was processed by vrad with -staticproplighting, in hdr
  
  struct dflagslump_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	uint32 m_LevelFlags;						// LVLFLAGS_xxx
  };
  
  struct lumpfileheader_t
  {
  	int				lumpOffset;
  	int				lumpID;
  	int				lumpVersion;	
  	int				lumpLength;
  	int				mapRevision;				// the map's revision (iteration, version) number (added BSPVERSION 6)
  };
  
  struct dgamelumpheader_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int lumpCount;
  
  	// dgamelump_t follow this
  };
  
  // This is expected to be a four-CC code ('lump')
  typedef int GameLumpId_t;
  
  // game lump is compressed, filelen reflects original size
  // use next entry fileofs to determine actual disk lump compressed size
  // compression stage ensures a terminal null dictionary entry
  #define GAMELUMPFLAG_COMPRESSED	0x0001
  
  struct dgamelump_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	GameLumpId_t	id;
  	unsigned short	flags;
  	unsigned short	version;
  	int				fileofs;
  	int				filelen;
  };
  
  extern int g_MapRevision;
  
  struct dmodel_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	Vector		mins, maxs;
  	Vector		origin;					// for sounds or lights
  	int			headnode;
  	int			firstface, numfaces;	// submodels just draw faces without walking the bsp tree
  };
  
  struct dphysmodel_t
  {
  	DECLARE_BYTESWAP_DATADESC()
  	int			modelIndex;
  	int			dataSize;
  	int			keydataSize;
  	int			solidCount;
  };
  
  // contains the binary blob for each displacement surface's virtual hull
  struct dphysdisp_t
  {
  	DECLARE_BYTESWAP_DATADESC()
  	unsigned short numDisplacements;
  	//unsigned short dataSize[numDisplacements];
  };
  
  struct dvertex_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	Vector	point;
  };
  
  // planes (x&~1) and (x&~1)+1 are always opposites
  struct dplane_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	Vector	normal;
  	float	dist;
  	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
  };
  
  #ifndef BSPFLAGS_H
  #include "bspflags.h"
  #endif
  
  struct dnode_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int			planenum;
  	int			children[2];	// negative numbers are -(leafs+1), not nodes
  	short		mins[3];		// for frustom culling
  	short		maxs[3];
  	unsigned short	firstface;
  	unsigned short	numfaces;	// counting both sides
  	short			area;		// If all leaves below this node are in the same area, then
  								// this is the area index. If not, this is -1.
  };
  
  typedef struct texinfo_s
  {
  	DECLARE_BYTESWAP_DATADESC();
  	float		textureVecsTexelsPerWorldUnits[2][4];			// [s/t][xyz offset]
  	float		lightmapVecsLuxelsPerWorldUnits[2][4];			// [s/t][xyz offset] - length is in units of texels/area
  	int			flags;				// miptex flags + overrides
  	int			texdata;			// Pointer to texture name, size, etc.
  } texinfo_t;
  
  #define TEXTURE_NAME_LENGTH	 128			// changed from 64 BSPVERSION 8
  
  struct dtexdata_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	Vector		reflectivity;
  	int			nameStringTableID;				// index into g_StringTable for the texture name
  	int			width, height;					// source image
  	int			view_width, view_height;		//
  };
  
  
  //-----------------------------------------------------------------------------
  // Occluders are simply polygons
  //-----------------------------------------------------------------------------
  // Flags field of doccluderdata_t
  enum
  {
  	OCCLUDER_FLAGS_INACTIVE = 0x1,
  };
  
  struct doccluderdata_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int			flags;
  	int			firstpoly;				// index into doccluderpolys
  	int			polycount;
  	Vector		mins;
  	Vector		maxs;
  	int			area;
  };
  
  struct doccluderdataV1_t
  {
  	int			flags;
  	int			firstpoly;				// index into doccluderpolys
  	int			polycount;
  	Vector		mins;
  	Vector		maxs;
  };
  
  struct doccluderpolydata_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int			firstvertexindex;		// index into doccludervertindices
  	int			vertexcount;
  	int			planenum;
  };
  
  
  // NOTE: see the section above titled "displacement neighbor rules".
  struct CDispSubNeighbor
  {
  public:
  	DECLARE_BYTESWAP_DATADESC();
  	unsigned short		GetNeighborIndex() const		{ return m_iNeighbor; }
  	NeighborSpan		GetSpan() const					{ return (NeighborSpan)m_Span; }
  	NeighborSpan		GetNeighborSpan() const			{ return (NeighborSpan)m_NeighborSpan; }
  	NeighborOrientation	GetNeighborOrientation() const	{ return (NeighborOrientation)m_NeighborOrientation; }
  
  	bool				IsValid() const				{ return m_iNeighbor != 0xFFFF; }
  	void				SetInvalid()				{ m_iNeighbor = 0xFFFF; }
  
  
  public:
  	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.
  };
  
  
  // NOTE: see the section above titled "displacement neighbor rules".
  class CDispNeighbor
  {
  public:
  	DECLARE_BYTESWAP_DATADESC();
  	void				SetInvalid()	{ m_SubNeighbors[0].SetInvalid(); m_SubNeighbors[1].SetInvalid(); }
  	
  	// Returns false if there isn't anything touching this edge.
  	bool				IsValid()		{ return m_SubNeighbors[0].IsValid() || m_SubNeighbors[1].IsValid(); }
  
  
  public:
  	// Note: if there is a neighbor that fills the whole side (CORNER_TO_CORNER),
  	//       then it will always be in CDispNeighbor::m_Neighbors[0]
  	CDispSubNeighbor	m_SubNeighbors[2];
  };
  
  
  class CDispCornerNeighbors
  {
  public:
  	DECLARE_BYTESWAP_DATADESC();
  	void			SetInvalid()	{ m_nNeighbors = 0; }
  
  
  public:
  	unsigned short	m_Neighbors[MAX_DISP_CORNER_NEIGHBORS];	// indices of neighbors.
  	unsigned char	m_nNeighbors;
  };
  
  
  class CDispVert
  {
  public:
  	DECLARE_BYTESWAP_DATADESC();
  	Vector		m_vVector;		// Vector field defining displacement volume.
  	float		m_flDist;		// Displacement distances.
  	float		m_flAlpha;		// "per vertex" alpha values.
  };
  
  #define DISPTRI_TAG_SURFACE			(1<<0)
  #define DISPTRI_TAG_WALKABLE		(1<<1)
  #define DISPTRI_TAG_BUILDABLE		(1<<2)
  #define DISPTRI_FLAG_SURFPROP1		(1<<3)
  #define DISPTRI_FLAG_SURFPROP2		(1<<4)
  #define DISPTRI_TAG_REMOVE			(1<<5)
  
  class CDispTri
  {
  public:
  	DECLARE_BYTESWAP_DATADESC();
  	unsigned short m_uiTags;		// Displacement triangle tags.
  };
  
  class ddispinfo_t
  {
  public:
  	DECLARE_BYTESWAP_DATADESC();
  	int			NumVerts() const		{ return NUM_DISP_POWER_VERTS(power); }
  	int			NumTris() const			{ return NUM_DISP_POWER_TRIS(power); }
  
  public:
  	Vector		startPosition;						// start position used for orientation -- (added BSPVERSION 6)
  	int			m_iDispVertStart;					// Index into LUMP_DISP_VERTS.
  	int			m_iDispTriStart;					// Index into LUMP_DISP_TRIS.
  
      int         power;                              // power - indicates size of map (2^power + 1)
      int         minTess;                            // minimum tesselation allowed
      float       smoothingAngle;                     // lighting smoothing angle
      int         contents;                           // surface contents
  
  	unsigned short	m_iMapFace;						// Which map face this displacement comes from.
  	
  	int			m_iLightmapAlphaStart;				// Index into ddisplightmapalpha.
  													// The count is m_pParent->lightmapTextureSizeInLuxels[0]*m_pParent->lightmapTextureSizeInLuxels[1].
  
  	int			m_iLightmapSamplePositionStart;		// Index into LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS.
  
  	CDispNeighbor			m_EdgeNeighbors[4];		// Indexed by NEIGHBOREDGE_ defines.
  	CDispCornerNeighbors	m_CornerNeighbors[4];	// Indexed by CORNER_ defines.
  
  	enum unnamed { ALLOWEDVERTS_SIZE = PAD_NUMBER( MAX_DISPVERTS, 32 ) / 32 };
  	unsigned long	m_AllowedVerts[ALLOWEDVERTS_SIZE];	// This is built based on the layout and sizes of our neighbors
  														// and tells us which vertices are allowed to be active.
  };
  
  
  // note that edge 0 is never used, because negative edge nums are used for
  // counterclockwise use of the edge in a face
  struct dedge_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	unsigned short	v[2];		// vertex numbers
  };
  
  #define	MAXLIGHTMAPS	4
  
  enum dprimitive_type
  {
  	PRIM_TRILIST=0,
  	PRIM_TRISTRIP=1,
  };
  
  struct dprimitive_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	unsigned char type;
  	unsigned short	firstIndex;
  	unsigned short	indexCount;
  	unsigned short	firstVert;
  	unsigned short	vertCount;
  };
  
  struct dprimvert_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	Vector		pos;
  };
  
  struct dface_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	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;
  	// This is a union under the assumption that a fog volume boundary (ie. water surface)
  	// isn't a displacement map.
  	// FIXME: These should be made a union with a flags or type field for which one it is
  	// if we can add more to this.
  //	union
  //	{
  	    short       dispinfo;
  		// This is only for surfaces that are the boundaries of fog volumes
  		// (ie. water surfaces)
  		// All of the rest of the surfaces can look at their leaf to find out
  		// what fog volume they are in.
  		short		surfaceFogVolumeID;
  //	};
  
  	// lighting info
  	byte		styles[MAXLIGHTMAPS];
  	int			lightofs;		// start of [numstyles*surfsize] samples
      float       area;
  
  	// TODO: make these unsigned chars?
  	int			m_LightmapTextureMinsInLuxels[2];
  	int			m_LightmapTextureSizeInLuxels[2];
  
  	int origFace;				// reference the original face this face was derived from
  
  
  public:
  
  	unsigned short GetNumPrims() const;
  	void SetNumPrims( unsigned short nPrims );
  	bool AreDynamicShadowsEnabled();
  	void SetDynamicShadowsEnabled( bool bEnabled );
  
  	// non-polygon primitives (strips and lists)
  private:
  	unsigned short m_NumPrims;	// Top bit, if set, disables shadows on this surface (this is why there are accessors).
  
  public:
  	unsigned short	firstPrimID; 
  	
  	unsigned int	smoothingGroups;
  };
  
  
  inline unsigned short dface_t::GetNumPrims() const
  {
  	return m_NumPrims & 0x7FFF;
  }
  
  inline void dface_t::SetNumPrims( unsigned short nPrims )
  {
  	Assert( (nPrims & 0x8000) == 0 );
  	m_NumPrims &= ~0x7FFF;
  	m_NumPrims |= (nPrims & 0x7FFF);
  }
  
  inline bool dface_t::AreDynamicShadowsEnabled()
  {
  	return (m_NumPrims & 0x8000) == 0;
  }
  
  inline void dface_t::SetDynamicShadowsEnabled( bool bEnabled )
  {
  	if ( bEnabled )
  		m_NumPrims &= ~0x8000;
  	else
  		m_NumPrims |= 0x8000;
  }
  
  struct dfaceid_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	unsigned short	hammerfaceid;
  };
  
  
  // NOTE: Only 7-bits stored!!!
  #define LEAF_FLAGS_SKY			0x01		// This leaf has 3D sky in its PVS
  #define LEAF_FLAGS_RADIAL		0x02		// This leaf culled away some portals due to radial vis
  #define LEAF_FLAGS_SKY2D		0x04		// This leaf has 2D sky in its PVS
  
  #if defined( _X360 )
  #pragma bitfield_order( push, lsb_to_msb )
  #endif
  #pragma warning( disable:4201 )	// C4201: nonstandard extension used: nameless struct/union
  struct dleaf_version_0_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int				contents;			// OR of all brushes (not needed?)
  
  	short			cluster;
  
  	BEGIN_BITFIELD( bf );
  	short			area:9;
  	short			flags:7;			// Per leaf flags.
  	END_BITFIELD();
  
  	short			mins[3];			// for frustum culling
  	short			maxs[3];
  
  	unsigned short	firstleafface;
  	unsigned short	numleaffaces;
  
  	unsigned short	firstleafbrush;
  	unsigned short	numleafbrushes;
  	short			leafWaterDataID; // -1 for not in water
  
  	// Precaculated light info for entities.
  	CompressedLightCube m_AmbientLighting;
  };
  
  // version 1
  struct dleaf_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int				contents;			// OR of all brushes (not needed?)
  
  	short			cluster;
  
  	BEGIN_BITFIELD( bf );
  	short			area:9;
  	short			flags:7;			// Per leaf flags.
  	END_BITFIELD();
  
  	short			mins[3];			// for frustum culling
  	short			maxs[3];
  
  	unsigned short	firstleafface;
  	unsigned short	numleaffaces;
  
  	unsigned short	firstleafbrush;
  	unsigned short	numleafbrushes;
  	short			leafWaterDataID; // -1 for not in water
  
  	// NOTE: removed this for version 1 and moved into separate lump "LUMP_LEAF_AMBIENT_LIGHTING" or "LUMP_LEAF_AMBIENT_LIGHTING_HDR"
  	// Precaculated light info for entities.
  //	CompressedLightCube m_AmbientLighting;
  };
  #pragma warning( default:4201 )	// C4201: nonstandard extension used: nameless struct/union
  #if defined( _X360 )
  #pragma bitfield_order( pop )
  #endif
  
  // each leaf contains N samples of the ambient lighting
  // each sample contains a cube of ambient light projected on to each axis
  // and a sampling position encoded as a 0.8 fraction (mins=0,maxs=255) of the leaf's bounding box
  struct dleafambientlighting_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	CompressedLightCube	cube;
  	byte x;		// fixed point fraction of leaf bounds
  	byte y;		// fixed point fraction of leaf bounds
  	byte z;		// fixed point fraction of leaf bounds
  	byte pad;	// unused
  };
  
  struct dleafambientindex_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  
  	unsigned short ambientSampleCount;
  	unsigned short firstAmbientSample;
  };
  
  struct dbrushside_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	unsigned short	planenum;		// facing out of the leaf
  	short			texinfo;
  	short			dispinfo;		// displacement info (BSPVERSION 7)
  	short			bevel;			// is the side a bevel plane? (BSPVERSION 7)
  };
  
  struct dbrush_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int			firstside;
  	int			numsides;
  	int			contents;
  };
  
  #define	ANGLE_UP	-1
  #define	ANGLE_DOWN	-2
  
  
  // the visibility lump consists of a header with a count, then
  // byte offsets for the PVS and PHS of each cluster, then the raw
  // compressed bit vectors
  #define	DVIS_PVS	0
  #define	DVIS_PAS	1
  struct dvis_t
  {
  	int			numclusters;
  	int			bitofs[8][2];	// bitofs[numclusters][2]
  };
  
  // each area has a list of portals that lead into other areas
  // when portals are closed, other areas may not be visible or
  // hearable even if the vis info says that it should be
  struct dareaportal_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	unsigned short	m_PortalKey;		// Entities have a key called portalnumber (and in vbsp a variable
  									// called areaportalnum) which is used
  									// to bind them to the area portals by comparing with this value.
  	
  	unsigned short	otherarea;		// The area this portal looks into.
  	
  	unsigned short	m_FirstClipPortalVert;	// Portal geometry.
  	unsigned short	m_nClipPortalVerts;
  
  	int				planenum;
  };
  
  
  struct darea_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int		numareaportals;
  	int		firstareaportal;
  };
  
  struct dleafwaterdata_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	float	surfaceZ;
  	float	minZ;
  	short	surfaceTexInfoID;
  };
  
  class CFaceMacroTextureInfo
  {
  public:
  	DECLARE_BYTESWAP_DATADESC();
  	// This looks up into g_TexDataStringTable, which looks up into g_TexDataStringData.
  	// 0xFFFF if the face has no macro texture.
  	unsigned short m_MacroTextureNameID;	
  };
  
  // lights that were used to illuminate the world
  enum emittype_t
  {
  	emit_surface,		// 90 degree spotlight
  	emit_point,			// simple point light source
  	emit_spotlight,		// spotlight with penumbra
  	emit_skylight,		// directional light with no falloff (surface must trace to SKY texture)
  	emit_quakelight,	// linear falloff, non-lambertian
  	emit_skyambient,	// spherical light source with no falloff (surface must trace to SKY texture)
  };
  
  
  // Flags for dworldlight_t::flags
  #define DWL_FLAGS_INAMBIENTCUBE		0x0001	// This says that the light was put into the per-leaf ambient cubes.
  
  
  struct dworldlight_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	Vector		origin;
  	Vector		intensity;
  	Vector		normal;			// for surfaces and spotlights
  	int			cluster;
  	emittype_t	type;
      int			style;
  	float		stopdot;		// start of penumbra for emit_spotlight
  	float		stopdot2;		// end of penumbra for emit_spotlight
  	float		exponent;		// 
  	float		radius;			// cutoff distance
  	// falloff for emit_spotlight + emit_point: 
  	// 1 / (constant_attn + linear_attn * dist + quadratic_attn * dist^2)
  	float		constant_attn;	
  	float		linear_attn;
  	float		quadratic_attn;
  	int			flags;			// Uses a combination of the DWL_FLAGS_ defines.
  	int			texinfo;		// 
  	int			owner;			// entity that this light it relative to
  };
  
  struct dcubemapsample_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int			origin[3];			// position of light snapped to the nearest integer
  									// the filename for the vtf file is derived from the position
  	unsigned char size;				// 0 - default
  									// otherwise, 1<<(size-1)
  };
  
  #define OVERLAY_BSP_FACE_COUNT	64
  
  #define OVERLAY_NUM_RENDER_ORDERS		(1<<OVERLAY_RENDER_ORDER_NUM_BITS)
  #define OVERLAY_RENDER_ORDER_NUM_BITS	2
  #define OVERLAY_RENDER_ORDER_MASK		0xC000	// top 2 bits set
  
  struct doverlay_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int			nId;
  	short		nTexInfo;
  
  	// Accessors..
  	void			SetFaceCount( unsigned short count );
  	unsigned short	GetFaceCount() const;
  
  	void			SetRenderOrder( unsigned short order );
  	unsigned short	GetRenderOrder() const;
  
  private:
  	unsigned short	m_nFaceCountAndRenderOrder;
  
  public:
  	int			aFaces[OVERLAY_BSP_FACE_COUNT];
  	float		flU[2];
  	float		flV[2];
  	Vector		vecUVPoints[4];
  	Vector		vecOrigin;
  	Vector		vecBasisNormal;
  };
  
  
  inline void doverlay_t::SetFaceCount( unsigned short count )
  {
  	m_nFaceCountAndRenderOrder &= OVERLAY_RENDER_ORDER_MASK;
  	m_nFaceCountAndRenderOrder |= (count & ~OVERLAY_RENDER_ORDER_MASK);
  }
  
  inline unsigned short doverlay_t::GetFaceCount() const
  {
  	return m_nFaceCountAndRenderOrder & ~OVERLAY_RENDER_ORDER_MASK;
  }
  
  inline void doverlay_t::SetRenderOrder( unsigned short order )
  {
  	m_nFaceCountAndRenderOrder &= ~OVERLAY_RENDER_ORDER_MASK;
  	m_nFaceCountAndRenderOrder |= (order << (16 - OVERLAY_RENDER_ORDER_NUM_BITS));	// leave 2 bits for render order.
  }
  
  inline unsigned short doverlay_t::GetRenderOrder() const
  {
  	return (m_nFaceCountAndRenderOrder >> (16 - OVERLAY_RENDER_ORDER_NUM_BITS));
  }
  
  
  struct doverlayfade_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  
  	float flFadeDistMinSq;
  	float flFadeDistMaxSq;
  };
  
  
  #define WATEROVERLAY_BSP_FACE_COUNT				256
  #define WATEROVERLAY_RENDER_ORDER_NUM_BITS		2
  #define WATEROVERLAY_NUM_RENDER_ORDERS			(1<<WATEROVERLAY_RENDER_ORDER_NUM_BITS)
  #define WATEROVERLAY_RENDER_ORDER_MASK			0xC000	// top 2 bits set
  struct dwateroverlay_t
  {
  	DECLARE_BYTESWAP_DATADESC();
  	int				nId;
  	short			nTexInfo;
  
  	// Accessors..
  	void			SetFaceCount( unsigned short count );
  	unsigned short	GetFaceCount() const;
  	void			SetRenderOrder( unsigned short order );
  	unsigned short	GetRenderOrder() const;
  
  private:
  
  	unsigned short	m_nFaceCountAndRenderOrder;
  
  public:
  
  	int				aFaces[WATEROVERLAY_BSP_FACE_COUNT];
  	float			flU[2];
  	float			flV[2];
  	Vector			vecUVPoints[4];
  	Vector			vecOrigin;
  	Vector			vecBasisNormal;
  };
  
  inline void dwateroverlay_t::SetFaceCount( unsigned short count )
  {
  	m_nFaceCountAndRenderOrder &= WATEROVERLAY_RENDER_ORDER_MASK;
  	m_nFaceCountAndRenderOrder |= (count & ~WATEROVERLAY_RENDER_ORDER_MASK);
  }
  
  inline unsigned short dwateroverlay_t::GetFaceCount() const
  {
  	return m_nFaceCountAndRenderOrder & ~WATEROVERLAY_RENDER_ORDER_MASK;
  }
  
  inline void dwateroverlay_t::SetRenderOrder( unsigned short order )
  {
  	m_nFaceCountAndRenderOrder &= ~WATEROVERLAY_RENDER_ORDER_MASK;
  	m_nFaceCountAndRenderOrder |= ( order << ( 16 - WATEROVERLAY_RENDER_ORDER_NUM_BITS ) );	// leave 2 bits for render order.
  }
  
  inline unsigned short dwateroverlay_t::GetRenderOrder() const
  {
  	return ( m_nFaceCountAndRenderOrder >> ( 16 - WATEROVERLAY_RENDER_ORDER_NUM_BITS ) );
  }
  
  #ifndef _DEF_BYTE_
  #define _DEF_BYTE_
  typedef unsigned char	byte;
  typedef unsigned short	word;
  #endif
  
  
  #define	ANGLE_UP	-1
  #define	ANGLE_DOWN	-2
  
  
  //===============
  
  
  struct epair_t
  {
  	epair_t	*next;
  	char	*key;
  	char	*value;
  };
  
  // finalized page of surface's lightmaps
  #define MAX_LIGHTMAPPAGE_WIDTH	256
  #define MAX_LIGHTMAPPAGE_HEIGHT	128
  typedef struct nameForDatadesc_dlightmappage_t // unnamed structs collide in the datadesc macros
  {
  	DECLARE_BYTESWAP_DATADESC();
  	byte	data[MAX_LIGHTMAPPAGE_WIDTH*MAX_LIGHTMAPPAGE_HEIGHT];
  	byte	palette[256*4];
  } dlightmappage_t;
  
  typedef struct nameForDatadesc_dlightmappageinfo_t // unnamed structs collide in the datadesc macros
  {
  	DECLARE_BYTESWAP_DATADESC();
  	byte			page;			// lightmap page [0..?]
  	byte			offset[2];		// offset into page (s,t)
  	byte			pad;			// unused
  	ColorRGBExp32	avgColor;		// average used for runtime lighting calcs
  } dlightmappageinfo_t;
  
  #endif // BSPFILE_H
  