/*
   Copyright (C) 1997-2001 Id Software, Inc.

   This program 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.

   This program 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 this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 */

#define MAX_CM_AREAPORTALS	( MAX_EDICTS )
#define MAX_CM_LEAFS		( MAX_MAP_LEAFS )

#define CM_SUBDIV_LEVEL		( 16 )

//#define TRACEVICFIX
#define TRACE_NOAXIAL // a hack to avoid issues with the return of traces against non axial planes
#define TRACE_NOAXIAL_SAFETY_OFFSET 0.1

typedef struct
{
	char *name;
	int contents;
	int flags;
} cshaderref_t;

typedef struct
{
	cplane_t *plane;
	int children[2];            // negative numbers are leafs
} cnode_t;

typedef struct
{
	cplane_t *plane;
	int surfFlags;
} cbrushside_t;

typedef struct
{
	int contents;
	int checkcount;             // to avoid repeated testings

	int numsides;
	cbrushside_t *brushsides;
} cbrush_t;

typedef struct
{
	int contents;
	int checkcount;             // to avoid repeated testings

	vec3_t mins, maxs;

	int numfacets;
	cbrush_t *facets;
} cface_t;

typedef struct
{
	int contents;
	int cluster;

	int area;

	int nummarkbrushes;
	cbrush_t **markbrushes;

	int nummarkfaces;
	cface_t	**markfaces;
} cleaf_t;

typedef struct cmodel_s
{
	vec3_t mins, maxs;

	int nummarkfaces;
	cface_t	**markfaces;

	int nummarkbrushes;
	cbrush_t **markbrushes;
} cmodel_t;

typedef struct
{
	qboolean open;
	int area;
	int otherarea;
} careaportal_t;

typedef struct
{
	int numareaportals;
	int areaportals[MAX_CM_AREAPORTALS];
	int floodnum;               // if two areas have equal floodnums, they are connected
	int floodvalid;
} carea_t;

struct cmodel_state_s
{
	int checkcount;
	struct mempool_s *mempool;

	bspFormatDesc_t	*cmap_bspFormat;

	char map_name[MAX_CONFIGSTRING_CHARS];
	qboolean map_clientload;
	unsigned int checksum;

	int numbrushsides;
	cbrushside_t *map_brushsides;

	int numshaderrefs;
	cshaderref_t *map_shaderrefs;

	int numplanes;
	cplane_t *map_planes;

	int numnodes;
	cnode_t	*map_nodes;

	int numleafs;                   // = 1
	cleaf_t	map_leaf_empty;         // allow leaf funcs to be called without a map
	cleaf_t	*map_leafs;             // = &map_leaf_empty;

	int nummarkbrushes;
	cbrush_t **map_markbrushes;

	int numcmodels;
	cmodel_t map_cmodel_empty;
	cmodel_t *map_cmodels;          // = &map_cmodel_empty;
	vec3_t world_mins, world_maxs;

	int numbrushes;
	cbrush_t *map_brushes;

	int numfaces;
	cface_t	*map_faces;

	int nummarkfaces;
	cface_t	**map_markfaces;

	vec3_t *map_verts;              // this will be freed
	int numvertexes;

	// 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
	int numareaportals;             // = 1
	careaportal_t map_areaportals[MAX_CM_AREAPORTALS];

	int numareas;                   // = 1
	carea_t	map_area_empty;
	carea_t	*map_areas;             // = &map_area_empty;

	dvis_t *map_pvs, *map_phs;
	int map_visdatasize;

	qbyte nullrow[MAX_CM_LEAFS/8];

	int numentitychars;
	char map_entitystring_empty;
	char *map_entitystring;         // = &map_entitystring_empty;

	int floodvalid;

	qbyte *cmod_base;

	// cm_trace.c
	cplane_t box_planes[6];
	cbrushside_t box_brushsides[6];
	cbrush_t box_brush[1];
	cbrush_t *box_markbrushes[1];
	cmodel_t box_cmodel[1];

	int leaf_count, leaf_maxcount;
	int *leaf_list;
	float *leaf_mins, *leaf_maxs;
	int leaf_topnode;
};

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

void	CM_CalcPHS( cmodel_state_t *cms );
void	CM_InitBoxHull( cmodel_state_t *cms );
void	CM_FloodAreaConnections( cmodel_state_t *cms );
