//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// Implementation of the main material system interface
//=============================================================================

#if !defined( VBSP_H )
#define VBSP_H

	   
#include "cmdlib.h"
#include "vector.h"
#include "scriplib.h"
#include "polylib.h"
#include "threads.h"
#include "bsplib.h"
#include "qfiles.h"
#include "materialpatch.h"

class CUtlBuffer;

#define	MAX_BRUSH_SIDES	128
#define	CLIP_EPSILON	0.1

#define	TEXINFO_NODE		-1		// side is allready on a node

struct plane_t : public dplane_t
{
	plane_t			*hash_chain;

	plane_t() { normal.Init(); }
};


struct brush_texture_t
{
	Vector	UAxis;
	Vector	VAxis;
	vec_t	shift[2];
	vec_t	rotate;
	vec_t	textureWorldUnitsPerTexel[2];
	vec_t	lightmapWorldUnitsPerLuxel;
	char	name[TEXTURE_NAME_LENGTH];
	int		flags;

	brush_texture_t() : UAxis(0,0,0), VAxis(0,0,0) {}
};

struct mapdispinfo_t;

typedef struct side_s
{
	int			    planenum;
	int			    texinfo;
	mapdispinfo_t	*pMapDisp;

	winding_t	    *winding;
	struct side_s	*original;	    // bspbrush_t sides will reference the mapbrush_t sides
	int			    contents;		// from miptex
	int			    surf;			// from miptex
	qboolean	    visible;		// choose visble planes first
	qboolean	    tested;			// this plane allready checked as a split
	qboolean	    bevel;			// don't ever use for bsp splitting

    struct side_s   *next;
    int             origIndex;      
	int				id;				// This is the unique id generated by worldcraft for this side.
	unsigned int	smoothingGroups;
	CUtlVector<int>	aOverlayIds;	// List of overlays that reside on this side.
} side_t;

typedef struct brush_s
{
	int		entitynum;
	int		brushnum;
	int		contents;
	Vector	mins, maxs;
	int		numsides;
	side_t	*original_sides;
} mapbrush_t;

#define	PLANENUM_LEAF			-1

#define	MAXEDGES		32

typedef struct face_s
{
	int				id;

	struct face_s	*next;		            // on node

	// the chain of faces off of a node can be merged or split,
	// but each face_t along the way will remain in the chain
	// until the entire tree is freed
	struct face_s	*merged;	            // if set, this face isn't valid anymore
	struct face_s	*split[2];	            // if set, this face isn't valid anymore

	struct portal_s	*portal;
	int				texinfo;
	int             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.
	int				surfaceFogVolumeID;
    int				planenum;
	int				contents;	            // faces in different contents can't merge
	int				outputnumber;
	winding_t		*w;
	int				numpoints;
	qboolean		badstartvert;	        // tjunctions cannot be fixed without a midpoint vertex
	int				vertexnums[MAXEDGES];
    side_t          *originalface;          // save the "side" this face came from
	int				firstPrimID;
	int				numPrims;
	unsigned int	smoothingGroups;
} face_t;

void EmitFace( face_t *f, qboolean onNode );

struct mapdispinfo_t
{
	face_t			face;
	int				entitynum;
    int				power;
    int				minTess;
    float			smoothingAngle;
    Vector			uAxis;
    Vector			vAxis;
	Vector			startPosition;
	float			alphaValues[MAX_DISPVERTS];
    float			maxDispDist;
    float			dispDists[MAX_DISPVERTS];
    Vector			vectorDisps[MAX_DISPVERTS];
	Vector			vectorOffsets[MAX_DISPVERTS];
    int				contents;
	int				brushSideID;
	unsigned short	triTags[MAX_DISPTRIS];
};

extern int              nummapdispinfo;
extern mapdispinfo_t    mapdispinfo[MAX_MAP_DISPINFO];

extern float			g_defaultLuxelSize;
extern float			g_luxelScale;
extern bool				g_BumpAll;
extern int				g_nDXLevel;

int GetDispInfoEntityNum( mapdispinfo_t *pDisp );
void ComputeBoundsNoSkybox( );

typedef struct bspbrush_s
{
	int					id;
	struct bspbrush_s	*next;
	Vector	            mins, maxs;
	int		            side, testside;		// side of node during construction
	mapbrush_t	        *original;
	int		            numsides;
	side_t	            sides[6];			// variably sized
} bspbrush_t;


#define	MAX_NODE_BRUSHES	8

typedef struct leafface_s leafface_t;

struct leafface_s 
{
	face_t		*pFace;
	leafface_t	*pNext;
};

typedef struct node_s
{
	int				id;

	// both leafs and nodes
	int				planenum;	// -1 = leaf node
	struct node_s	*parent;
	Vector			mins, maxs;	// valid after portalization
	bspbrush_t		*volume;	// one for each leaf/node

	// nodes only
	side_t			*side;		// the side that created the node
	struct node_s	*children[2];
	face_t			*faces;

	// leafs only
	bspbrush_t		*brushlist;	// fragments of all brushes in this leaf
	leafface_t		*leaffacelist;
	int				contents;	// OR of all brush contents
	int				occupied;	// 1 or greater can reach entity
	entity_t		*occupant;	// for leak file testing
	int				cluster;	// for portalfile writing
	int				area;		// for areaportals
	struct portal_s	*portals;	// also on nodes during construction
} node_t;


typedef struct portal_s
{
	int				id;
	plane_t		    plane;
	node_t		    *onnode;		// NULL = outside box
	node_t		    *nodes[2];		// [0] = front side of plane
	struct portal_s *next[2];
	winding_t	    *winding;
	qboolean	    sidefound;		// false if ->side hasn't been checked
	side_t		    *side;			// NULL = non-visible
	face_t		    *face[2];		// output face in bsp file
} portal_t;


typedef struct
{
	node_t		*headnode;
	node_t		outside_node;
	Vector		mins, maxs;
} tree_t;


extern	int			entity_num;

extern	plane_t		mapplanes[MAX_MAP_PLANES];
extern	int			nummapplanes;

extern	int			nummapbrushes;
extern	mapbrush_t	mapbrushes[MAX_MAP_BRUSHES];

extern	Vector		map_mins, map_maxs;

extern	int			nummapbrushsides;
extern	side_t		brushsides[MAX_MAP_BRUSHSIDES];
extern	int			g_nMapFileVersion;

extern	qboolean	noprune;
extern	qboolean	nodetail;
extern	qboolean	fulldetail;
extern	qboolean	nomerge;
extern	qboolean	nosubdiv;
extern	qboolean	nowater;
extern	qboolean	noweld;
extern	qboolean	noshare;
extern	qboolean	notjunc;
extern	qboolean	nocsg;
extern	qboolean	noopt;
extern  qboolean	dumpcollide;
extern	qboolean	nodetailcuts;
extern  qboolean	g_DumpStaticProps;
extern	vec_t		microvolume;
extern	bool		g_snapAxialPlanes;
extern	char		outbase[32];

extern	char	source[1024];
extern char		mapbase[ 64 ];

void 	LoadMapFile(const char *filename);
int		FindFloatPlane (Vector& normal, vec_t dist);
int		GetVertexnum( Vector& v );

//=============================================================================

// textures.c

struct textureref_t
{
	char	name[TEXTURE_NAME_LENGTH];
	int		flags;
	float	lightmapWorldUnitsPerLuxel;
	int		contents;
};

extern	textureref_t	textureref[MAX_MAP_TEXTURES];

int	FindMiptex (const char *name);

int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, const Vector& origin);
int GetSurfaceProperties2( MaterialSystemMaterial_t matID, const char *pMatName );

extern int g_SurfaceProperties[MAX_MAP_TEXDATA];
void LoadSurfaceProperties( void );

//=============================================================================

void FindGCD (int *v);

mapbrush_t *Brush_LoadEntity (entity_t *ent);
int	PlaneTypeForNormal (Vector& normal);
qboolean MakeBrushPlanes (mapbrush_t *b);
int		FindIntPlane (int *inormal, int *iorigin);
void	CreateBrush (int brushnum);


//=============================================================================
// detail objects
//=============================================================================

void LoadEmitDetailObjectDictionary( char const* pGameDir );
void EmitDetailObjects();

//=============================================================================
// static props
//=============================================================================

void EmitStaticProps();
bool LoadStudioModel( char const* pFileName, char const* pEntityType, CUtlBuffer& buf );

//=============================================================================
//=============================================================================
// procedurally created .vmt files
//=============================================================================

void EmitStaticProps();

// draw.c

extern Vector	draw_mins, draw_maxs;
extern	qboolean	drawflag;
extern bool g_bLightIfMissing;

void Draw_ClearWindow (void);
void DrawWinding (winding_t *w);

void GLS_BeginScene (void);
void GLS_Winding (winding_t *w, int code);
void GLS_EndScene (void);

//=============================================================================

// csg

enum detailscreen_e
{
	FULL_DETAIL = 0,
	ONLY_DETAIL = 1,
	NO_DETAIL	= 2,
};

#define TRANSPARENT_CONTENTS	(CONTENTS_GRATE|CONTENTS_WINDOW)
	
bspbrush_t *MakeBspBrushList (int startbrush, int endbrush,
		const Vector& clipmins, const Vector& clipmaxs, int detailScreen);
bspbrush_t *MakeBspBrushList (mapbrush_t **pBrushes, int nBrushCount, const Vector& clipmins, const Vector& clipmaxs);
bspbrush_t *ChopBrushes (bspbrush_t *head);
bspbrush_t *InitialBrushList (bspbrush_t *list);
bspbrush_t *OptimizedBrushList (bspbrush_t *list);
void FixupAreaportalWaterBrushes( bspbrush_t *pList );

void WriteBrushMap (char *name, bspbrush_t *list);

//=============================================================================

// brushbsp

void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis);

bspbrush_t *CopyBrush (bspbrush_t *brush);

void SplitBrush (bspbrush_t *brush, int planenum,
	bspbrush_t **front, bspbrush_t **back);

tree_t *AllocTree (void);
node_t *AllocNode (void);
bspbrush_t *AllocBrush (int numsides);
int	CountBrushList (bspbrush_t *brushes);
void FreeBrush (bspbrush_t *brushes);
vec_t BrushVolume (bspbrush_t *brush);

void BoundBrush (bspbrush_t *brush);
void FreeBrushList (bspbrush_t *brushes);

tree_t *BrushBSP (bspbrush_t *brushlist, Vector& mins, Vector& maxs);

#define	PSIDE_FRONT			1
#define	PSIDE_BACK			2
#define	PSIDE_BOTH			(PSIDE_FRONT|PSIDE_BACK)
#define	PSIDE_FACING		4
int BrushBspBoxOnPlaneSide (const Vector& mins, const Vector& maxs, dplane_t *plane);

//=============================================================================

// portals.c

int VisibleContents (int contents);

void MakeHeadnodePortals (tree_t *tree);
void MakeNodePortal (node_t *node);
void SplitNodePortals (node_t *node);

qboolean	Portal_VisFlood (portal_t *p);

qboolean FloodEntities (tree_t *tree);
void FillOutside (node_t *headnode);
void FloodAreas (tree_t *tree);
void MarkVisibleSides (tree_t *tree, int start, int end, int detailScreen);
void MarkVisibleSides (tree_t *tree, mapbrush_t **ppBrushes, int nCount );
void FreePortal (portal_t *p);
void EmitAreaPortals (node_t *headnode);

void MakeTreePortals (tree_t *tree);

//=============================================================================

// glfile.c

void OutputWinding (winding_t *w, FileHandle_t glview);
void WriteGLView (tree_t *tree, char *source);

//=============================================================================

// leakfile.c

void LeakFile (tree_t *tree);

//=============================================================================

// prtfile.c

void WritePortalFile (tree_t *tree);

//=============================================================================

// writebsp.c

void SetModelNumbers (void);
void SetLightStyles (void);

void BeginBSPFile (void);
void WriteBSP (node_t *headnode, face_t *pLeafFaceList);
void EndBSPFile (void);
void BeginModel (void);
void EndModel (void);

extern	int firstmodeledge;
extern	int	firstmodelface;

//=============================================================================

// faces.c

void MakeFaces (node_t *headnode);
void MakeDetailFaces (node_t *headnode);
face_t *FixTjuncs( node_t *headnode, face_t *pLeafFaceList );

face_t	*AllocFace (void);
void FreeFace (face_t *f);
void FreeFaceList( face_t *pFaces );

void MergeFaceList(face_t **pFaceList);
void SubdivideFaceList(face_t **pFaceList);

extern face_t		*edgefaces[MAX_MAP_EDGES][2];


//=============================================================================

// tree.c

void FreeTree (tree_t *tree);
void FreeTree_r (node_t *node);
void PrintTree_r (node_t *node, int depth);
void FreeTreePortals_r (node_t *node);
void PruneNodes_r (node_t *node);
void PruneNodes (node_t *node);

// Returns true if the entity is a func_occluder
bool IsFuncOccluder( int entity_num );


//=============================================================================
// ivp.cpp
class CPhysCollide;
void EmitPhysCollision( void );
void DumpCollideToGlView( CPhysCollide *pCollide, const char *pFilename );

//=============================================================================
// find or create the texdata 
extern int FindTexData( const char *pName );
// Add a clone of an existing texdata with a new name
extern int AddCloneTexData( dtexdata_t *pExistingTexData, char const *cloneTexDataName );
extern int FindOrCreateTexInfo( const texinfo_t &searchTexInfo );
extern int FindAliasedTexData( const char *pName, dtexdata_t *sourceTexture );

//=============================================================================
// normals.c
void SaveVertexNormals( void );

//=============================================================================
// cubemap.cpp
void Cubemap_InsertSample( const Vector& origin, int size );
void Cubemap_CreateDefaultCubemaps( void );
void Cubemap_SaveBrushSides( const char *pSideListStr );
void Cubemap_FixupBrushSidesMaterials( void );
void Cubemap_FixupDispMaterials( void );
void Cubemap_MakeDefaultVersionsOfEnvCubemapMaterials( void );

//=============================================================================
// overlay.cpp
#define OVERLAY_MAP_STRLEN			256

struct mapoverlay_t
{
	int					nId;
	char				szMaterialName[OVERLAY_MAP_STRLEN];
	float				flU[2];
	float				flV[2];
	Vector				vecUVPoints[4];
	Vector				vecOrigin;
	Vector				vecBasisNormal;
	CUtlVector<int>		aSideList;
	CUtlVector<int>		aFaceList;
};

extern CUtlVector<mapoverlay_t>	g_aMapOverlays;

void Overlay_GetFromEntity( entity_t *pMapEnt );
void Overlay_UpdateSideLists( void );
void Overlay_AddFaceToLists( int iFace, side_t *pSide );
void Overlay_EmitOverlayFaces( void );

//=============================================================================

void RemoveAreaPortalBrushes_R( node_t *node );

dtexdata_t *GetTexData( int index );

#endif

