/*
   Copyright (C) 1999-2007 id Software, Inc. and contributors.
   For a list of contributors, see the accompanying CONTRIBUTORS file.

   This file is part of GtkRadiant.

   GtkRadiant is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   GtkRadiant is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GtkRadiant; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

/* Files:

   brushbsp.c
   csg.c
   faces.c
   gldraw.c
   glfile.c
   leakfile.c
   map.c
   nodraw.c
   portals.c
   prtfile.c
   qbsp3.c
   textures.c
   tree.c
   writebsp.c

 */

#include "globaldefs.h"
#include "cmdlib.h"
#include "mathlib.h"
#include "scriplib.h"
#include "polylib.h"
#include "q2_threads.h"
#include "bspfile.h"
#include "inout.h"

#if GDEF_COMPILER_MSVC
	#ifdef NDEBUG                           // Don't show in a Release build
		#pragma warning(disable : 4305)     // truncate from double to float
		#pragma warning(disable : 4244)     // conversion from double to float
		#pragma warning(disable : 4018)     // signed/unsigned mismatch
	#endif
#endif

#define MAX_BRUSH_SIDES 128
#define CLIP_EPSILON    0.1

#define BOGUS_RANGE 8192

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

typedef struct plane_s
{
	vec3_t normal;
	vec_t dist;
	int type;
	struct plane_s  *hash_chain;
} plane_t;

typedef struct
{
	vec_t shift[2];
	vec_t rotate;
	vec_t scale[2];
	char name[32];
	int flags;
	int value;
} brush_texture_t;

typedef struct side_s
{
	int planenum;
	int texinfo;
	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
} side_t;

typedef struct brush_s
{
	int entitynum;
	int brushnum;

	int contents;

	vec3_t mins, maxs;

	int numsides;
	side_t  *original_sides;
} mapbrush_t;

#define PLANENUM_LEAF           -1

#define MAXEDGES        20

typedef struct face_s
{
	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 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];
} face_t;



typedef struct bspbrush_s
{
	struct bspbrush_s   *next;
	vec3_t 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 node_s
{
	// both leafs and nodes
	int planenum;               // -1 = leaf node
	struct node_s   *parent;
	vec3_t mins, maxs;          // valid after portalization
	bspbrush_t      *volume;    // one for each leaf/node

	// nodes only
	qboolean detail_seperator;          // a detail brush caused the split
	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
	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
{
	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;
	vec3_t 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 vec3_t map_mins, map_maxs;

#define MAX_MAP_SIDES       ( MAX_MAP_BRUSHES * 6 )

extern int nummapbrushsides;
extern side_t brushsides[MAX_MAP_SIDES];

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 vec_t microvolume;

extern char outbase[32];

extern char source[1024];

void    LoadMapFile( char *filename );
int     FindFloatPlane( vec3_t normal, vec_t dist );

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

// textures.c

typedef struct
{
	char name[64];
	int flags;
	int value;
	int contents;
	char animname[64];
} textureref_t;

#define MAX_MAP_TEXTURES    1024

extern textureref_t textureref[MAX_MAP_TEXTURES];

int FindMiptex( char *name );

int TexinfoForBrushTexture( plane_t *plane, brush_texture_t *bt, vec3_t origin );

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

void FindGCD( int *v );

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


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

// draw.c

extern vec3_t draw_mins, draw_maxs;
extern qboolean drawflag;

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

bspbrush_t *MakeBspBrushList( int startbrush, int endbrush,
							  vec3_t clipmins, vec3_t clipmaxs );
bspbrush_t *ChopBrushes( bspbrush_t *head );
bspbrush_t *InitialBrushList( bspbrush_t *list );
bspbrush_t *OptimizedBrushList( bspbrush_t *list );

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, vec3_t mins, vec3_t maxs );

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

// 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 );
void FreePortal( portal_t *p );
void EmitAreaPortals( node_t *headnode );

void MakeTreePortals( tree_t *tree );

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

// glfile.c

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

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

// leakfile.c

//void LeakFile (tree_t *tree);
xmlNodePtr 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 );
void EndBSPFile( void );
void BeginModel( void );
void EndModel( void );

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

// faces.c

void MakeFaces( node_t *headnode );
void FixTjuncs( node_t *headnode );
int GetEdge2( int v1, int v2,  face_t *f );

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

void MergeNodeFaces( node_t *node );

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

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

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

// externs

extern char *mapname;
extern char game[64];
