/*====================ÉCOLE POLYTECHNIQUE DE MONTRÉAL============================

	NOM DU FICHIER :CTrou.cpp

	DESCRIPTION :	Implémentation des fonctions membres de la classe Trou

	AUTEUR : Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse

	DATE DE CRÉATION : 2004-3-16

	MISES À JOUR :

===============================================================================*/
#include "CTrou.h"
#include <GL/glut.h>
#include "al/al.h"
#include "al/alc.h"
#include "al/alut.h"

CPngTexture CTrou::TextureTrou;
bool CTrou::ballein = false;
int CTrou::HoleSource;
int CTrou::HoleSoundBuffer;

/*------------------------------------------------------------------
  Fonction :	CTrou::AfficheGL

  Description :	Affiche en OpenGL le trou

  Paramètres :

  Valeur retournée :	void : 

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CTrou::AfficheGL() const
{
    GLfloat mat_diffuse[] = {0.0, 0.0, 0.1, 1.0};
    GLfloat mat_specular[] = {0.7, 0.7, 0.7, 0.0};
    GLfloat mat_shininess[] = {5.0};
    GLfloat mat_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
    glColor3f(0,0,0);
    GLUquadric* myDisk = gluNewQuadric();
    glPushMatrix();
    glTranslatef(Pos.GetPosX(), Pos.GetPosY(), -PROF_TROU-SAFE_DISP);
    gluDisk(myDisk,0,rayon/TAILLE_TUILE,15,1);
    glPopMatrix();
    gluDeleteQuadric(myDisk);
    glColor3f(0.5,0.5,0.5);
    GLUquadric* myCylinder = gluNewQuadric();
    gluQuadricOrientation(myCylinder, (GLenum)GLU_INSIDE);
    glPushMatrix();
    glTranslatef(Pos.GetPosX(), Pos.GetPosY(), -PROF_TROU-SAFE_DISP);
    gluCylinder(myCylinder, rayon/TAILLE_TUILE,rayon/TAILLE_TUILE,PROF_TROU,15,1);
    glPopMatrix();
    gluDeleteQuadric(myCylinder);
    glColor3f(1,1,1);
}

/*------------------------------------------------------------------
  Fonction :	CTrou::isCollision

  Description :	Vérifie si la balle fait collision avec le trou
				et change sa vitesse selon certains critères
				afin d'avoir un certain "réalisme"

  Paramètres :
	 CBalle *balle : 

  Valeur retournée :	bool : Si la collision se produit

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
bool CTrou::isCollision(CBalle *balle) const
{
	CVector3f PosBall = balle->getPos();
	CVector3f PosTrou = this->Pos;
	PosBall.setZ(0);
	PosTrou.setZ(0);
	float Distance = (PosBall - PosTrou).GetNorm();
	float norme = balle->getDirection().GetNorm();
	if (Distance > this->rayon/TAILLE_TUILE)
	{
		if (ballein)
		{
			balle->setZ(balle->getRayon()/TAILLE_TUILE);

			CVector3f Vcolli, Vconst;
			Vcolli = balle->getDirection() >> (PosBall - PosTrou);			
			Vconst = balle->getDirection() - Vcolli;
			balle->setDirection((Vconst + 0.3*Vcolli));

			balle->setSurTrou(false);
			ballein = false;
			return true;
		}
		else
			return false;
	} else if ((Distance < this->rayon/TAILLE_TUILE)) {
		if (Distance < (rayon-balle->getRayon())/TAILLE_TUILE)
		{
			ballein = true;
			if (norme < 8 && !balle->getSurTrou())
			  {
			    PlayHoleSound();
			    balle->setZ(-PROF_TROU+balle->getRayon()/TAILLE_TUILE);
			    balle->setSurTrou(true);
			  }
		}
		//Attirer la balle vers le centre du trou
		balle->setDirection((balle->getDirection()+
			FORCE_CENTRE*(PosTrou-PosBall)).GetNormalVector()*norme);
	}
	// Empêche la balle de sortir
	if (  balle->getDirection()*(PosBall-PosTrou) > 0 &&
		 (Distance >= (rayon-balle->getRayon())/TAILLE_TUILE)
		)
	{
		if (norme < 8)
		{		    
			CVector3f Vcolli, Vconst;
			Vcolli = balle->getDirection() >> (PosBall - PosTrou);
			Vconst = balle->getDirection() - Vcolli;
			balle->setDirection((Vconst - Vcolli));
		}
	}
	if (ballein && norme < 8)
	    balle->setDirection(0.998f*balle->getDirection());
return true;
}


/*------------------------------------------------------------------
  Fonction :	CTrou::ChargeTextures

  Description :	Charge la texture du trou

  Paramètres :

  Valeur retournée :	bool : Si le chargement s'est fait

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
bool CTrou::ChargeTextures()
{
  return (TextureTrou.LoadPNG("editeur/images/Trou.png") != 0);
}


/*------------------------------------------------------------------
  Fonction :	CTrou::DechargeTextures

  Description :	Décharge la texture du trou

  Paramètres :

  Valeur retournée :	bool : Vrai

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
bool CTrou::DechargeTextures()
{
  TextureTrou.Unload();
  return true;
}

/*------------------------------------------------------------------
  Fonction :	setStencil

  Description :	Crée le stencil pour "creuser" le sol pour le trou

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CTrou::setStencil()
{
    glEnable(GL_STENCIL_TEST);
    glClear(GL_STENCIL_BUFFER_BIT);
    glStencilFunc (GL_ALWAYS, 0x1, 0x1);
    glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
    GLUquadric* myDisk = gluNewQuadric();
    glPushMatrix();
    glTranslatef(Pos.GetPosX(), Pos.GetPosY(), -SAFE_DISP);
    gluDisk(myDisk,0,rayon/TAILLE_TUILE,15,1);
    glPopMatrix();
    gluDeleteQuadric(myDisk);
    glDisable(GL_STENCIL_TEST);
}

/*------------------------------------------------------------------
  Fonction :	PlayHoleSound()
  
  Description :	Joue un son de la balle dans le trou avec OpenAL
  
  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CTrou::PlayHoleSound() const
{
    alSourcei(HoleSource,AL_BUFFER,HoleSoundBuffer);
    alSourcePlay(HoleSource);  	
}

/*------------------------------------------------------------------
  Fonction :	ChargeSons()
  
  Description :	Charge les sons
  
  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CTrou::ChargeSons()
{
    ALenum format;
    ALvoid *data;
    ALsizei size;
    ALsizei freq;
    ALboolean loop;
    
    alGenSources(1,(ALuint*)&HoleSource);
    alSourcei(HoleSource,AL_LOOPING,AL_FALSE);
    
    alGenBuffers(1,(ALuint*)&HoleSoundBuffer);
    alutLoadWAVFile((ALbyte*)"jeu/sons/golfball.wav",&format,&data,&size,&freq,&loop);
    alBufferData(HoleSoundBuffer,format,data,size,freq);
    alutUnloadWAV(format,data,size,freq);
}
