/*  TA3D, a remake of Total Annihilation
    Copyright (C) 2005  Roland BROCHARD

    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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA*/

#define TA3D_ENGINE_VERSION	"Version 0.1.2"

#define DEBUG_MODE				// Mode débogage

extern FONT *aglfont;
extern RGB *pal;

typedef unsigned char byte;

#include <string.h>
#include "glfunc.h"
#include "matrix.h"				// Pour les matrices de 4x4 et les vecteurs
#include "console.h"
#include "hpi.h"				// Pour la lecture des archives du jeu
#include "gaf.h"				// Pour la lecture des fichiers images/animations
#include "gui.h"				// Pour la gestion de l'interface graphique utilisateur
#include "sound.h"				// Pour la gestion du son

#define TIME_UNIT			0.03f		// Pour la simulation physique

#define LANG_ENGLISH		0x0
#define LANG_FRENCH			0x1
#define LANG_GERMAN			0x2
#define LANG_SPANISH		0x3
#define LANG_ITALIAN		0x4

extern int LANG;				// Variable indiquant la langue

extern int CURSOR_MOVE;
extern int CURSOR_GREEN;
extern int CURSOR_CROSS;
extern int CURSOR_RED;
extern int CURSOR_LOAD;
extern int CURSOR_GUARD;
extern int CURSOR_PATROL;
extern int CURSOR_REPAIR;
extern int CURSOR_ATTACK;
extern int CURSOR_BLUE;
#define CURSOR_DEFAULT		CURSOR_BLUE
extern int CURSOR_AIR_LOAD;
extern int CURSOR_BOMB_ATTACK;
extern int CURSOR_BALANCE;
extern int CURSOR_RECLAIM;
extern int CURSOR_WAIT;
extern int CURSOR_CANT_ATTACK;
extern int CURSOR_CROSS_LINK;

extern volatile int Atimer;

extern ANIMS cursor;

extern int fire;
extern int build_part;

extern int start;
extern int cursor_type;

void play(char *filename);
int anim_cursor(int type=-1);
void draw_cursor();
void ReInitTexSys();
void SetDefOpenGlState();

const float DEG2RAD=PI/180.0f;
const float RAD2DEG=180.0f/PI;

const float DEG2TA=65536.0f/360.0f;
const float TA2DEG=360.0f/65536.0f;

const float RAD2TA=RAD2DEG*DEG2TA;
const float TA2RAD=TA2DEG*DEG2RAD;

const float i2pwr16=1.0f/65536.0f;

class CAMERA					// Classe pour la gestion de la caméra
{
public:
	VECTOR	Pos;				// Position de la caméra
	VECTOR	RPos;				// Position de la caméra
	VECTOR	*Ref;				// Référentiel
	VECTOR	Rotat;				// Vitesse de rotation(référentiel)
	VECTOR	Dir;				// Direction de la caméra
	VECTOR	Up;					// Haut de la caméra
	VECTOR	Side;				// Coté de la caméra(optimisation pour les particules)
	float	zfar;				// Pour le volume visible
	float	znear;
	float	zfar2;				// Carré de la distance maximale

	CAMERA()					// Initialise la caméra
	{
		Pos.x=Pos.y=Pos.z=0.0f;			// Position (0,0,0)
		Pos.z=30.0f;
		RPos=Pos;
		Dir=Up=Pos;
		Dir.z=-1.0f;					// Direction
		Up.y=1.0f;						// Haut
		zfar=140000.0f;
		znear=1.0f;
		Side=Dir*Up;
		zfar2=zfar*zfar;
		Ref=NULL;
		Rotat.x=Rotat.y=Rotat.z=0.0f;
	}

	void SetMatrix(MATRIX_4x4 View,float Dt)
	{
		Dir.x=Dir.y=Dir.z=0.0f;
		Up=Dir;
		Dir.z=-1.0f;
		Up.y=1.0f;
		Dir=Dir*View;
		Up=Up*View;
		Side=Dir*Up;
		MATRIX_4x4	Rot;
		Rot=RotateX(Rotat.x*Dt*PI/180.0f)*RotateY(Rotat.y*Dt*PI/180.0f)*RotateZ(Rotat.z*Dt*PI/180.0f);
		RPos=RPos*Rot;
	}

	void SetRef(VECTOR *NRef=NULL,float r1=0.0f,float r2=0.0f,float r3=0.0f)
	{
		if(Ref!=NULL && NRef!=NULL)
			RPos=RPos+(*Ref)-(*NRef);
		else if(NRef!=NULL)
			RPos=RPos-(*NRef);
		if(NRef==NULL && Ref!=NULL)
			RPos=RPos+(*Ref);
		Ref=NRef;
		Rotat.x=r1;
		Rotat.y=r2;
		Rotat.z=r3;
	}

	void SetView()				// Remplace la caméra OpenGl par celle-ci
	{
		zfar2=zfar*zfar;
		glMatrixMode (GL_PROJECTION);			// Matrice de projection
		glLoadIdentity ();
		glFrustum (-1.0f*znear, 1.0f*znear, -0.75f*znear, 0.75f*znear, znear, zfar);
		glMatrixMode (GL_MODELVIEW);

		glLoadIdentity();			// Charge la matrice identité

		if(Ref!=NULL)
			Pos=RPos+(*Ref);
		else
			Pos=RPos;

		VECTOR	FP;
		FP=Pos+Dir;

		gluLookAt(Pos.x,Pos.y,Pos.z,FP.x,FP.y,FP.z,Up.x,Up.y,Up.z);
	}
};

/*------------------------------------------------------------------------\
|              Classe pour la gestion de l'éclairage matériel             |
\------------------------------------------------------------------------*/

class HWLIGHT
{
public:
	VECTOR	Pos;				// Position
	VECTOR	Dir;				// Direction
	GLfloat LightAmbient[4];
	GLfloat LightDiffuse[4];
	GLfloat LightSpecular[4];
	GLuint	HWNb;				// Indice de lumière matérielle
	float	Att;				// Attenuation
	bool	Directionnal;		// Indique si il s'agit d'une lumière directionnelle

	void init()
	{
		LightAmbient[0]=0.125f;
		LightAmbient[1]=0.125f;
		LightAmbient[2]=0.125f;
		LightAmbient[3]=1.0f;

		LightDiffuse[0]=1.0f;
		LightDiffuse[1]=1.0f;
		LightDiffuse[2]=1.0f;
		LightDiffuse[3]=1.0f;

		LightSpecular[0]=1.0f;
		LightSpecular[1]=1.0f;
		LightSpecular[2]=1.0f;
		LightSpecular[3]=1.0f;

		Pos.x=0.0f;
		Pos.y=0.0f;
		Pos.z=0.0f;
		Dir=Pos;
		Dir.z=-1.0f;
		HWNb=GL_LIGHT0;
		Att=0.05f;
		Directionnal=true;
	}
	
	HWLIGHT()
	{
		init();
	}
	
	void Enable()
	{
		glEnable (HWNb);
		//glEnable (GL_LIGHTING);
		glEnable (GL_COLOR_MATERIAL);
	}

	void Disable()
	{
		glDisable(HWNb);
	}

	void Set(CAMERA View)
	{
		GLfloat LightPosition[4];
		if(Directionnal) {
			LightPosition[0]=Dir.x;
			LightPosition[1]=Dir.y;
			LightPosition[2]=Dir.z;
			LightPosition[3]=0.0f;
			}
		else {
			View.SetView();
			LightPosition[0]=Pos.x;
			LightPosition[1]=Pos.y;
			LightPosition[2]=Pos.z;
			LightPosition[3]=1.0f;
			}

		glLightfv(HWNb, GL_AMBIENT, LightAmbient);		// Setup The Ambient Light
		glLightfv(HWNb, GL_DIFFUSE, LightDiffuse);		// Setup The Diffuse Light
		glLightfv(HWNb, GL_SPECULAR, LightSpecular);	// Setup The Diffuse Light
		glLightfv(HWNb, GL_POSITION,LightPosition);		// Position The Light
		glLightf(HWNb, GL_LINEAR_ATTENUATION, Att);		// Attenuation
	}
};

extern CAMERA *game_cam;

BITMAP *load_memory_pcx(byte *data,RGB *cpal);
RGB *LoadPal(char *filename);
#ifndef ALLEGRO_WINDOWS
int min(int a,int b);
int max(int a,int b);
float min(float a,float b);
float max(float a,float b);
#endif
void PutTex(GLuint Tex,float x1,float y1,float x2,float y2);
GLuint LoadTex(char *file);
GLuint LoadMaskedTex(char *file,char *filealpha);
BITMAP *LoadMaskedTexBmp(char *file,char *filealpha);
