/*
*
*   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
*
*   In addition, as a special exception, the author gives permission to
*   link the code of this program with the Half-Life Game Engine ("HL
*   Engine") and Modified Game Libraries ("MODs") developed by Valve,
*   L.L.C ("Valve").  You must obey the GNU General Public License in all
*   respects for all of the code used other than the HL Engine and MODs
*   from Valve.  If you modify this file, you may extend this exception
*   to your version of the file, but you are not obligated to do so.  If
*   you do not wish to do so, delete this exception statement from your
*   version.
*
*/

#ifndef COM_MODEL_H
#define COM_MODEL_H
#ifdef _WIN32
#pragma once
#endif

#include "maintypes.h"
#include "custom.h"
#include "bspfile.h"

#define STUDIO_RENDER		1
#define STUDIO_EVENTS		2

#define MAX_MODEL_NAME		64
#define MAX_MAP_HULLS		4
#define MIPLEVELS		4
#define NUM_AMBIENTS		4				// automatic ambient sounds
#define MAXLIGHTMAPS		4
#define PLANE_ANYZ		5

#define ALIAS_Z_CLIP_PLANE	5

// flags in finalvert_t.flags
#define ALIAS_LEFT_CLIP				0x0001
#define ALIAS_TOP_CLIP				0x0002
#define ALIAS_RIGHT_CLIP			0x0004
#define ALIAS_BOTTOM_CLIP			0x0008
#define ALIAS_Z_CLIP				0x0010
#define ALIAS_ONSEAM				0x0020
#define ALIAS_XY_CLIP_MASK			0x000F

#define ZISCALE	((float)0x8000)

#define CACHE_SIZE				32		// used to align key data structures

typedef enum modtype_e
{
	mod_brush,
	mod_sprite,
	mod_alias,
	mod_studio,
} modtype_t;

// must match definition in modelgen.h
#ifndef SYNCTYPE_T
#define SYNCTYPE_T

typedef enum
{
	ST_SYNC = 0,
	ST_RAND
} synctype_t;

#endif

// plane_t structure
typedef struct mplane_s
{
	vec3_t normal;		// surface normal
	float dist;		// closest appoach to origin
	byte type;		// for texture axis selection and fast side tests
	byte signbits;		// signx + signy<<1 + signz<<1
	byte pad[2];
} mplane_t;

typedef struct
{
	vec3_t position;
} mvertex_t;

typedef struct
{
	unsigned short v[2];
	unsigned int cachededgeoffset;
} medge_t;

typedef struct texture_s
{
	char name[16];
	unsigned width;
	unsigned height;
	int anim_total;				// total tenths in sequence ( 0 = no)
	int anim_min, anim_max;			// time for this frame min <=time< max
	struct texture_s *anim_next;		// in the animation sequence
	struct texture_s *alternate_anims;	// bmodels in frame 1 use these
	unsigned offsets[ MIPLEVELS ];		// four mip maps stored
	unsigned paloffset;
} texture_t;

typedef struct
{
	float vecs[2][4];		// [s/t] unit vectors in world space. 
					// [i][3] is the s/t offset relative to the origin.
					// s or t = dot(3Dpoint,vecs[i])+vecs[i][3]

	float mipadjust;		// ?? mipmap limits for very small surfaces
	texture_t *texture;
	int flags;			// sky or slime, no lightmap or 256 subdivision
} mtexinfo_t;

typedef struct mnode_s
{
	int contents;			// 0, to differentiate from leafs
	int visframe;			// node needs to be traversed if current
	
	short minmaxs[6];		// for bounding box culling
	struct mnode_s *parent;

	mplane_t *plane;
	struct mnode_s *children[2];

	unsigned short firstsurface;
	unsigned short numsurfaces;
} mnode_t;

typedef struct msurface_s msurface_t;
typedef struct decal_s decal_t;

// JAY: Compress this as much as possible
struct decal_s
{
	decal_t *pnext;			// linked list for each surface
	msurface_t *psurface;		// Surface id for persistence / unlinking
	short dx;			// Offsets into surface texture (in texture coordinates, so we don't need floats)
	short dy;
	short texture;			// Decal texture
	byte scale;			// Pixel scale
	byte flags;			// Decal flags
	short entityIndex;		// Entity this is attached to
};

typedef struct mleaf_s
{
	// common with node
	int contents;			// wil be a negative contents number
	int visframe;			// node needs to be traversed if current

	short minmaxs[6];		// for bounding box culling

	struct mnode_s *parent;

	// leaf specific
	byte *compressed_vis;
	struct efrag_s *efrags;

	msurface_t **firstmarksurface;
	int nummarksurfaces;
	int key;			// BSP sequence number for leaf's contents
	byte ambient_sound_level[ NUM_AMBIENTS ];
} mleaf_t;

struct msurface_s
{
	int visframe;			// should be drawn when node is crossed
	int dlightframe;		// last frame the surface was checked by an animated light
	int dlightbits;			// dynamically generated. Indicates if the surface illumination 
					// is modified by an animated light.

	mplane_t *plane;		// pointer to shared plane			
	int flags;			// see SURF_ #defines
	int firstedge;			// look up in model->surfedges[], negative numbers
	int numedges;			// are backwards edges

	struct surfcache_s *cachespots[ MIPLEVELS ];

	short texturemins[2]; 		// smallest s/t position on the surface.
	short extents[2];		// ?? s/t texture size, 1..256 for all non-sky surfaces

	mtexinfo_t *texinfo;
	byte styles[ MAXLIGHTMAPS ];	// index into d_lightstylevalue[] for animated lights 
					// no one surface can be effected by more than 4 
					// animated lights.

	color24 *samples;
	decal_t *pdecals;
};

typedef struct hull_s
{
	dclipnode_t *clipnodes;
	mplane_t *planes;
	int firstclipnode;
	int lastclipnode;
	vec3_t clip_mins;
	vec3_t clip_maxs;
} hull_t;

#if !defined(CACHE_USER) && !defined(QUAKEDEF_H)
#define CACHE_USER
typedef struct cache_user_s
{
	void	*data;
} cache_user_t;
#endif

typedef struct model_s
{
	char name[ MAX_MODEL_NAME ];
	qboolean needload;			// bmodels and sprites don't cache normally

	modtype_t type;
	int numframes;
	synctype_t synctype;
	
	int flags;

	// volume occupied by the model		
	vec3_t mins, maxs;
	float radius;

	// brush model
	int firstmodelsurface, nummodelsurfaces;

	int numsubmodels;
	dmodel_t *submodels;

	int numplanes;
	mplane_t *planes;

	int numleafs;				// number of visible leafs, not counting 0
	struct mleaf_s *leafs;

	int numvertexes;
	mvertex_t *vertexes;

	int numedges;
	medge_t *edges;

	int numnodes;
	mnode_t *nodes;

	int numtexinfo;
	mtexinfo_t *texinfo;

	int numsurfaces;
	msurface_t *surfaces;

	int numsurfedges;
	int *surfedges;

	int numclipnodes;
	dclipnode_t *clipnodes;

	int nummarksurfaces;
	msurface_t **marksurfaces;

	hull_t hulls[ MAX_MAP_HULLS ];

	int numtextures;
	texture_t **textures;

	byte *visdata;
	color24 *lightdata;
	char *entities;

	// additional model data
	cache_user_t cache;			// only access through Mod_Extradata

} model_t;

typedef vec_t vec4_t[4];

typedef struct alight_s
{
	int ambientlight;	// clip at 128
	int shadelight;		// clip at 192 - ambientlight
	vec3_t color;
	float *plightvec;
} alight_t;

typedef struct auxvert_s
{
	float fv[3];		// viewspace x, y
} auxvert_t;

#define MAX_INFO_STRING		256
#define MAX_SCOREBOARDNAME	32

typedef struct player_info_s
{
	// User id on server
	int userid;

	// User info string
	char userinfo[ MAX_INFO_STRING ];

	// Name
	char name[ MAX_SCOREBOARDNAME ];

	// Spectator or not, unused
	int spectator;
	int ping;
	int packet_loss;

	// skin information
	char model[MAX_QPATH];
	int topcolor;
	int bottomcolor;

	// last frame rendered
	int renderframe;	

	// Gait frame estimation
	int gaitsequence;
	float gaitframe;
	float gaityaw;
	vec3_t prevgaitorigin;

	customization_t customdata;

} player_info_t;

#endif // COM_MODEL_H