//========= Copyright © 1996-2005, 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.h"
#endif

#include "bumpvects.h"
#include "compressed_light_cube.h"

#define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'V')
		// little-endian "VBSP"

#define BSPVERSION 19


// 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	128
#define MAX_DISP_LIGHTMAP_DIM_INCLUDING_BORDER	131


// 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

// 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	4096

#define	MAX_MAP_TEXINFO		12288
#define MAX_MAP_TEXDATA		2048

#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 )

#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_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

// 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,		// *
// JAY: This is texdata now, previously LUMP_TEXTURES
	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,		// *

//#define	LUMP_			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_PORTALS		= 22,
	LUMP_CLUSTERS		= 23,
	LUMP_PORTALVERTS	= 24,
	LUMP_CLUSTERPORTALS = 25,
	LUMP_DISPINFO		= 26,
	LUMP_ORIGINALFACES	= 27,

	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,
};


// Lumps that have versions are listed here
enum
{
	LUMP_LIGHTING_VERSION = 1,
	LUMP_FACES_VERSION = 1,
	LUMP_OCCLUSION_VERSION = 2,
};


#define	HEADER_LUMPS		64

#include "zip_uncompressed.h"

struct lump_t
{
	int		fileofs, filelen;
	int		version;		// default to zero
	char	fourCC[4];		// default to ( char )0, ( char )0, ( char )0, ( char )0
};


struct dheader_t
{
	int			ident;
	int			version;	
	lump_t		lumps[HEADER_LUMPS];
	int			mapRevision;				// the map's revision (iteration, version) number (added BSPVERSION 6)
};

struct dgamelumpheader_t
{
	int lumpCount;

	// dclientlump_ts follow this
};

// This is expected to be a four-CC code ('lump')
typedef int GameLumpId_t;

struct dgamelump_t
{
	GameLumpId_t	id;
	unsigned short flags;		// currently unused, but you never know!
	unsigned short version;
	int	fileofs;
	int filelen;
};

extern int g_MapRevision;

struct dmodel_t
{
	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
{
	int			modelIndex;
	int			dataSize;
	int			keydataSize;
	int			solidCount;
};

struct dvertex_t
{
	Vector	point;
};

// planes (x&~1) and (x&~1)+1 are always opposites
struct dplane_t
{
	Vector	normal;
	float	dist;
	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
};

#ifndef BSPFLAGS_H
#include "bspflags.h"
#endif

struct dnode_t
{
	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
{
	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
{
	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
{
	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
{
	int			firstvertexindex;		// index into doccludervertindices
	int			vertexcount;
	int			planenum;
};


// NOTE: see the section above titled "displacement neighbor rules".
struct CDispSubNeighbor
{
public:

	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:
	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:

	void			SetInvalid()	{ m_nNeighbors = 0; }


public:
	unsigned short	m_Neighbors[MAX_DISP_CORNER_NEIGHBORS];	// indices of neighbors.
	unsigned char	m_nNeighbors;
};


class CDispVert
{
public:
	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)

class CDispTri
{
public:
	unsigned short m_uiTags;		// Displacement triangle tags.
};

class ddispinfo_t
{
public:
	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 { 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
{
	unsigned short	v[2];		// vertex numbers
};

#define	MAXLIGHTMAPS	4

enum dprimitive_type
{
	PRIM_TRILIST=0,
	PRIM_TRISTRIP=1,
};

struct dprimitive_t
{
	unsigned char type;
	unsigned short	firstIndex;
	unsigned short	indexCount;
	unsigned short	firstVert;
	unsigned short	vertCount;
};

struct dprimvert_t
{
	Vector		pos;
};

struct dface_t
{
	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;
}


// NOTE: Only 7-bits stored!!!
#define LEAF_FLAGS_SKY			0x01		// This leaf has sky in its PVS
#define LEAF_FLAGS_RADIAL		0x02		// This leaf culled away some portals due to radial vis


struct dleaf_t
{
	int				contents;			// OR of all brushes (not needed?)

	short			cluster;

	short			area:9;
	short			flags:7;			// Per leaf flags.

	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;
};

struct dbrushside_t
{
	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
{
	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
{
	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
{
	int		numareaportals;
	int		firstareaportal;
};

struct dportal_t
{
	int		firstportalvert;
	int		numportalverts;
	int		planenum;
	unsigned short	cluster[2];
};

struct dcluster_t
{
	int		firstportal;
	int		numportals;
};

struct dleafwaterdata_t
{
	float	surfaceZ;
	float	minZ;
	short	surfaceTexInfoID;
};

class CFaceMacroTextureInfo
{
public:
	// 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
{
	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
{
	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
{
	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 )
{
	Assert( count >= 0 && (count & OVERLAY_RENDER_ORDER_MASK) == 0 );
	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 )
{
	Assert( order >= 0 && order < OVERLAY_NUM_RENDER_ORDERS );
	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));
}


#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;
};

#endif // BSPFILE_H
