
/*! \mainpage

\section introduction Presentation

gKitGL est compose de quelques classes permettant d'ecrire simplement une application openGL.

- gk::App fournit une classe de base d'application permettant de creer une fenetre, un contexte de rendu 
ainsi qu'une gestion de clavier asynchrone.

- gk::Vector, gk::Point et gk::Normal permettent de manipuler facilement des 
vecteurs, points et normales en 3d. Les operations courantes sur les points, 
vecteurs et normales sont documentees dans le namespace gk. Les operations 
sur les transformations et compositions sont egalement documentees dans le namespace gk.

- gk::Transform, gk::Matrix4x4 permettent de decrire des transformations sous 
forme de matrices homogenes, de les composer et de transformer des points, vecteurs, normales, etc.

- gk::GLAttributeBuffer, gk::GLIndexBuffer, gk::GLTexture, gk::GLSampler, gk::GLShaderProgram, 
gk::GLFramebuffer permettent de manipuler facilement les objets openGL indispensables : 
vertex buffer, texture et filtrage, shader program et frame buffer. 

- La section \ref GLResource decrit la manipulation des objets openGL.

- gk::Mesh fournit une representation d'un objet 3d. gk::GLMeshIO::read( ) permet de charger tres simplement un fichier maya au format .obj.

- gk::GLTexture2D et gk::GLSampler representent une texture couleur classique
et son mode de filtrage. gk::GLTexture2DIO::read( ) permet de charger une image 
et de creer la texture openGL correspondante.

- gk::GLHDRTexture represente une texture couleur hdr. gk::GLHDRTextureIO::read( )
permet de charger une image .hdr et de creer la texture openGL correspondante.

- gk::GLShaderProgram, gk::GLFragmentShader et gk::GLVertexShader permettent de 
charger, de compiler et d'executer des shaders (ainsi que d'afficher lisiblement
les erreurs de compilations et de link).

Les sections suivantes presentent les fonctionnalites de chaque classe :
	- \ref App Presentation de gk::App.
	- \ref GLResource Presentation de la representation des objets openGL.
	- \ref GLPipeline Presentation de la gestion des objets openGL.


Des exemples complets sont egalement disponibles (cf. la page Examples).

\page App Presentation de gk::App.

gk::App peut etre utilisee de plusieurs facons : soit en utilisant son interface bas niveau, soit en la derivant.

exemple 1: utilisation bas niveau
\code
	// cree une fenetre de 600 par 600 et initialise un context openGL
	App app(600, 600);

	// boucle principale, version decomposee de gk::App::run()
	while(!app.isClosed()) // isClosed() renvoie vrai tant que la fenetre existe
	{
		// traitement des evenements : clavier, souris, fenetre, etc.
		app.processEvents();
		
		// renvoie l'etat d'une touche 
		if(app.key('q'))
		{
			printf("close\n");
			// demande a fermer l'application, la prochaine fois isClosed() renverra faux.
			app.close();
		}
	}
\endcode

exemple 2: utilisation par derivation
\code
	// creation de l'objet application derive de gk::App
	Tuto app(600, 600);

	// boucle principale, deriver de App pour redefinir draw()
	app.run();
\endcode
	
La methode gk::App::run() appelle dans l'ordre la methode gk::App::init(), 
puis execute la boucle telle quelle est presentee dans l'exemple1, gk::App::draw() est appellee a chaque iteration,
et enfin appelle gk::App::quit() avant de sortir.

Voici un exemple de classe derivee :
\code
	class Tuto : public gk::App
	{
	public:
		Tuto( const int w, const int h )
			:
			gk::App(w, h),
		{}
		
		~Tuto( ) {}
		
		// redefinir init pour charger les objets, construire une scene, etc.
		// int init( ) {}
		
		// redefinir quit pour liberer tout ce qui a ete charge dans init().
		// int quit( ) {}
		
		// redefinir draw pour faire quelquechose ...
		int draw( )
		{
			// sortir si l'utilisateur a appuye sur q ou escape, cf. la doc de SDL  pour le detail des codes SDLK_xxx
			if(key('q') || key(SDLK_ESCAPE))
			{
				printf("close\n");
				close();
				// renvoyer 0 ferme l'application
				return 0;
			}
			
			// afficher quelquechose ...
			
			// renvoyer 1 pour continuer
			return 1;
		}
	};
\endcode	


\page GLResource Gestion des objets openGL

Tous les objets openGL derivent d'une classe de base gk::GLResource et se 
manipulent donc de la meme maniere. 

- attention : les objets openGL / les GLResources n'appartiennent pas a 
l'application ! ils appartiennent au contexte openGL. L'application ne peut donc
que les referencer (garder un pointeur sur un objet GLResource).

- les GLResources sont construits en deux etapes : new/delete permettent de 
creer/detruire l'objet c++ qui permet de manipuler un objet openGL, et l'objet 
openGL lui-meme est cree/detruit par createGLResource()/releaseGLResource().

\code
	// creer un shader
	// 1. creer l'objet c++ shader
	GLShaderProgram *shader= new gk::GLShaderProgram("simple.vsl", "simple.fsl");
	if(shader == NULL)
		return "erreur";
	// 2. creer effectivement le shader openGL
	if(shader->createGLResource() < 0)
		return "erreur de creation du shader";

	// utiliser le shader
	glUseProgram(sahder->name());
	// dessiner quelquechose ...
	
	// detruire le shader
	// 1. detruire l'objet openGL
	shader->releaseGLResource();
	// 2. detruire l'objet c++ shader
	delete shader;
\endcode

- les GLResources doivent etre configures completement avant d'appeler 
createGLResource(). Cette "contrainte" permet de mieux structurer 
l'application en imposant une phase d'initialisation suivie d'une "boucle" 
d'utilisation. En effet, il est tres tres (tres) lent de creer les objets openGL
a chaque utilisation. Pour resumer, les GLResources seront donc crees dans 
gk::App::init() et pas dans la fonction gk::App::draw().


\page GLPipeline Pipeline openGL

- creation d'objets openGL : l'application est libre de creer et d'utiliser 
directement les objets openGL (cf. \ref GLResource) mais, dans ce cas, elle est 
egalement responsable de leur destruction / liberation. Une solution encore plus
simple consiste a laisser gKit gerer la creation et la destruction des
objets. Les deux extraits suivants donne un apercu des differences :

\code
// creer un shader "a la main"
	// 1. creer l'objet c++ shader program
	gk::GLShaderProgram *program= new gk::GLShaderProgram();
	if(program == NULL)
		return "erreur";
	// 2. compiler les shaders et les attacher au program.
	...
	
	// 3. creer effectivement le shader openGL
	if(program>createGLResource() < 0)
		return "erreur de creation du shader";

	// utiliser le shader
	glUseProgram(program->name());
	// dessiner quelquechose ...
	
	// 4. liberer l'objet c++ et l'objet openGL
	program->releaseGLResource();
	delete program;
	... 
\endcode
	
	gKit prend en charge la creation / destruction de l'objet c++ 
ainsi que de l'objet openGL, il suffit de verifier que tout c'est bien passe 
immediatement apres la contruction.

\code
// creer un shader en utilisant gKit
	// 1. creer le shader program
	gk::GLShaderProgram *program= gk::createShaderProgram("simple.vsl", "simple.fsl");
	if(program->createGLResource() < 0)
		return "erreur de creation du shader program";
	
	// utiliser le shader program
	glUseProgram(program->name());
	// dessiner quelquechose ...
	
	// 3. liberer l'objet c++ et l'objet openGL
	// ... rien a faire, le gKit le fait tout seul, a la fin de l'application.
\endcode

*/


