|
gKit2 light
|
il est temps de faire une petite pause et de reprendre calmement tout ça...
les tutos précédents ont utilisé la classe App ou AppCamera pour créer une fenêtre et initialiser openGL. Il est peut être plus clair d'écrire directement les différentes étapes et la boucle de gestion d'évènements :
étape 1 : création de la fenêtre et du contexte openGL
les détails de la création de fenêtre et des options du contexte openGL sont dans écrire une application openGL.
étape 2 : initialisation, chargement d'un objet 3d et des shaders
étape 3 : boucle principale et gestion des évènements, on attend que l'utilisateur ferme la fenêtre ou appuie sur la touche esc / échap. SDL renvoie les évènements un par un avec SDL_PollEvent(), il suffit d'agir en fonction de leur type, appui sur une touche, fermeture, déplacement, redimensionnement de la fenêtre, etc.
étape 4 : libération des ressources / nettoyage
évènements : en pratique, il y a d'autres évènements à surveiller, toutes les touches du clavier, la souris, le redimensionnement de la fenêtre, le drag&drop de fichiers... le code précédent est minimaliste... mais comme c'est toujours la même chose, la fonction events() de window.h s'occupe de ça. ce qui permet d'écrire la boucle de manière très compacte :
events() renvoie false lorsque la fenêtre doit être fermée, il suffit de sortir de la boucle et de nettoyer / libérer tous les objets openGL.
events() maintient l'état de toutes les touches du clavier. on peut savoir, dans n'importe quelle fonction de l'application, si une touche est enfoncée, ou pas, avec key_state( ). Pour connaître l'état de la touche d'une lettre, il suffit d'utiliser la lettre comme paramètre, cf if(key_state('t')) { ... }, mais ça ne marche pas pour les accents, uniquement pour les caractères ASCII basiques. Pour les autres touches comme les flèches ou tab, ctrl, etc, il suffit d'utiliser le code correspondant, cf SDLK_RETURN, SDLK_LEFT, SDLK_TAB, SDLK_PAGEUP, SDLK_F1, etc. la liste complète est dans la doc de SDL2.
il y a un exemple complet dans premiers objets, affichage et transformations.
il suffit d'utiliser directement les fonctions de SDL2, cf doc en ligne. par exemple, récupérer la position de la souris et l'état des boutons avec SDL_GetMouseState() :
buttons est un masque binaire qui représente l'état de tous les boutons. chaque bouton est représenté par un bit du masque, il faut utiliser SDL_BUTTON() pour identifier un bouton: 1, 2 et 3, pour gauche, milieu et droit. Si on préfère obtenir le mouvement de la souris plutôt que sa position, on peut utiliser SDL_GetRelativeMouseState(). attention GetRelativeMouseState() renvoie le mouvement de la souris calculé depuis le dernier appel. résultat, il ne faut l'appeler qu'une fois par frame, sinon les appels suivants renverront de toutes petites valeurs de mouvements ou zero.
pour récupérer la rotation de la molette / bouton de milieu de la souris ou un mouvement sur le pad d'un portable, il faut intercepter les évènements SDL_MouseWheelEvent (comme dans l'étape 3 juste au dessus) ou utiliser events() et wheel_event() (comme dans l'étape évènements) :
exemple d'utilisation pour déplacer une caméra dans update_camera() dans app_camera.cpp.
Dans le même genre, il n'est pas très difficile de dessiner directement avec openGL, cf glDrawArrays() ou glDrawElements() pour des maillages indexés / sommets partagés. par contre, il faut transférer les sommets des triangles dans des buffers openGL et décrire le format des sommets, ie position uniquement, ou coordonnées de texture, normales, etc. Les détails ne sont pas si horribles, cf tuto9_buffers.cpp, mais Mesh peut faire le travail tout seul, cf Mesh::create_buffers(). on peut remplacer l'init et l'affichage de l'objet avec du code openGL :
Une fois que l'on arrive à afficher un objet, on a rapidement envie de bouger autour pour l'observer, il n'est pas si difficile d'écrire une caméra, cf premiers objets, affichage et transformations, mais, parfois, on veut juste un truc simple à utiliser. la classe Orbiter est faite pour ça, elle permet de tourner autour d'un objet. Il suffit de la créer avec les dimensions de l'objet à observer, de définir ses paramètres de projection, et de la mettre à jour à chaque image avec update_camera() de app_camera.h:
on a dit calmement... ce sera pour le prochain épisode...