+ Répondre à la discussion
Affichage des résultats 1 à 4 sur 4
  1. #1
    Membre éprouvé
    Avatar de Le Farfadet Spatial
    Inscrit en
    avril 2008
    Messages
    144
    Détails du profil
    Informations forums :
    Inscription : avril 2008
    Messages : 144
    Points : 424
    Points
    424

    Par défaut GtkGLExtmm : crash au passage en plein écran

    Salut à tous !

    J’ai converti le deuxième tutoriel de NeHe sur OpenGL de telle sorte qu’il utilise GtkGlExtmm. Cependant, j’ai une bogue surprenante : sur mon ordinateur portable, utilisant le pilote libre pour processeur graphique Intel Sandy bridge mobile sur Debian Wheezy, tout ce passe bien. En particulier, je peux commencer immédiatement en mode plein écran.

    En revanche, sur mon ordinateur fixe, qui utilise Flgrx toujours sur Debian Wheezy, si je peux basculer en (puis quitter le) mode plein écran à partir du moment où je commence en mode fenêtré, le serveur X crash (écran entièrement noir) si je veux commencer immédiatement en mode plein écran. Dans ce cas-là, plus possible d’obtenir une console virtuelle. Cependant, je suis certain que seul X crash, dans la mesure où j’entends encore la musique que j’écoutais éventuellement à ce moment-là et je peux me connecter par SSH sur l’ordinateur fixe depuis le portable (c’est ce que je fais pour reprendre la main).

    Je ne sais pas trop comment résoudre le problème, je suis donc preneur de toute aide éventuelle.

    Je génère le code à l’aide de CMake. Le fichier « CMakeLists.txt » associé se situe dans la racine du projet, tandis que tous les codes sont dans le sous-répertoire « src/ ».

    Fichier « CMakeLists.txt » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    ## Génération des tutoriels OpenGL de NeHe version Gtkmm.
     
    cmake_minimum_required(VERSION 2.6)
     
    project(Tutoriel1)
     
    # Répertoire où placer l’exécutable.
    set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
    # Nom de l’exécutable.
    set(EXECUTABLE_NAME tutoriel1)
     
    find_package(OpenGL)
     
    find_package(PkgConfig)
     
    pkg_check_modules(Glibmm glibmm-2.4>=2.4.0)
    pkg_check_modules(GTKmm gtkmm-2.4>=2.4.0)
    pkg_check_modules(GLExtmm gtkglextmm-1.2>=1.2.0)
    link_directories(
            ${OPENGL_LIBRARY_DIRS}
            ${Glibmm_LIBRARY_DIRS}
            ${GTKmm_LIBRARY_DIRS}
            ${GLExtmm_LIBRARY_DIRS}
    )
    include_directories(
            ${OPENGL_INCLUDE_DIRS}
            ${Glibmm_INCLUDE_DIRS}
            ${GTKmm_INCLUDE_DIRS}
            ${GLExtmm_INCLUDE_DIRS}
    )
     
    file(
            GLOB_RECURSE
            source_files
            src/*
    )
     
    add_executable(
            ${EXECUTABLE_NAME}
            ${source_files}
    )
     
    target_link_libraries(
            ${EXECUTABLE_NAME}
            ${OPENGL_LIBRARIES}
            ${Glibmm_LIBRARIES}
            ${GTKmm_LIBRARIES}
            ${GLExtmm_LIBRARIES}
    )
    Fichier « src/erreurs.hpp » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    #ifndef ERREURS_HPP
    #define ERREURS_HPP
     
    /*
     * Exceptions pour la gestions des erreurs.
     */
     
    #include <exception>
     
    /* Espace de nommage pour la gestion des erreurs. */
    namespace Erreurs {
    /* -- Erreurs provoquées par l’interface graphique. ---------------------- */
      class ErreurInterface: public std::exception {
        public:
          /* Constructeur par défaut. */
          ErreurInterface () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurInterface () throw () {}
     
          /* Génére le message d’erreur. */
          virtual const char* what () const throw () {
            return "une erreur s’est produite dans l’interface graphique";
          }
      };
     
    /* -- Erreur lors de la configuration d’OpenGL. -------------------------- */
      class ErreurConfigurationGL: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurConfigurationGL () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurConfigurationGL () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            return "erreur lors de la configuration d’OpenGL";
          }
      };
     
    /* -- Erreur lors de la création du contexte OpenGL. --------------------- */
      class ErreurCreationContexte: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurCreationContexte () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurCreationContexte () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            return "impossible de créer un contexte OpenGL";
          }
      };
     
    /* -- Erreur à l’obtention du contexte OpenGL. --------------------------- */
      class ErreurObtentionContexte: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurObtentionContexte () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurObtentionContexte () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            return "impossible d’obtenir le contexte OpenGL";
          }
      };
    }
     
    #endif  // #ifndef ERREURS_HPP
    Fichier « src/fenetre.hpp » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #ifndef FENETRE_HPP
    #define FENETRE_HPP
     
    /*
     * Définitions des classes gérants le fenêtrage OpenGL.
     */
     
    #include <gtkmm/window.h>
    #include <gtkmm/drawingarea.h>
    #include <gtkglmm.h>
     
    #include "erreurs.hpp"
     
    /* Espace de nommage pour la gestion de l’interface. */
    namespace Interface {
      /* Classe pour la zone de rendu OpenGL. */
      class GlDrawingArea: public Gtk::DrawingArea,
                           public Gtk::GL::Widget<GlDrawingArea> {
        public:
          GlDrawingArea ();
          virtual ~GlDrawingArea ();
     
        protected:
          /* -- Controleurs: */
     
          /* À l’initialisation de la fenêtre. */
          virtual void on_realize ();
     
          /* À la demande d’affichage. */
          virtual bool on_expose_event (GdkEventExpose* event);
     
          /* Au changement de taille de la fenêtre. */
          virtual bool on_configure_event (GdkEventConfigure* event);
      };
     
    /* ----------------------------------------------------------------------- */
     
      /* Classe pour la fenetre principale. */
      class Fenetre: public Gtk::Window {
        public:
          Fenetre ();
          virtual ~Fenetre();
     
        protected:
          /* -- Controleurs : */
     
          /* Gestion des évènements clavier. */
          bool on_key_release (GdkEventKey* evenement);
     
          /* Lors du passage du mode fenêtré au mode plein écran. */
          bool on_window_state_event (GdkEventWindowState *pEven);
     
          /* -- Composant membre : */
     
          /* Zone de rendu OpenGL. */
          GlDrawingArea zoneRendu;
     
        private:
          /* Indique si on se trouve en mode plein écran. */
          bool enPleinEcran;
      };
    }
     
    #endif  // #ifndef FENETRE_HPP
    Fichier « src/fenetre.cpp »

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    /*
     * Implémentations du fenêtrage OpenGL.
     */
     
    #include <glibmm/error.h>
    #include <cstdlib>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <sstream>
    #include <gtkmm/messagedialog.h>
    #include <gdk/gdkkeysyms.h>
     
    #include "fenetre.hpp"
     
    /* -- Constructeur par défaut de GlDrawingArea. -------------------------- */
    Interface::GlDrawingArea::GlDrawingArea (): Gtk::DrawingArea () {
      /* Configuration d’OpenGL */
      Glib::RefPtr<Gdk::GL::Config> configuration;
     
      /* Tente d’ouvrir une espace à double tampon. */
      configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA   |
                                              Gdk::GL::MODE_DEPTH  |
                                              Gdk::GL::MODE_DOUBLE);
      if (!configuration) {
        /* Message d’avertissement. */
        std::stringstream message;
        message << "Impossible de configurer OpenGL en mode double tampon, "
                << "tente le mode simple tampon.\n";
        g_warning(message.str().c_str());
        /* Tente de configurer un tampon simple. */
        configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA  |
                                                Gdk::GL::MODE_DEPTH);
        if (!configuration) throw Erreurs::ErreurConfigurationGL ();
      }
     
      /* Donne accès à OpenGL au composant. */
      set_gl_capability(configuration);
    }
     
    /* -- Destructeur de GlDrawingArea. -------------------------------------- */
    Interface::GlDrawingArea::~GlDrawingArea () {
    }
     
    /* -- Initialisation du contexte OpenGL. --------------------------------- */
    void Interface::GlDrawingArea::on_realize () {
      /* D’abord l’initialisation standard. */
      Gtk::Widget::on_realize();
     
      if (!create_gl_context()) throw Erreurs::ErreurCreationContexte ();
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl) throw Erreurs::ErreurObtentionContexte ();
     
      fenetreGl->gl_begin(get_gl_context());
     
        /* Permet un joli ombrage. */
        glShadeModel(GL_SMOOTH);
     
        /* Fond noir. */
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     
        /* Mis en place du tampon de profondeur. */
        glClearDepth(1.0f);
        /* Mis en place du test de profondeur. */
        glEnable(GL_DEPTH_TEST);
        /* Le type de test de profondeur . */
        glDepthFunc(GL_LEQUAL);
     
        /* Très jolis calculs de perspective. */
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
     
      fenetreGl->gl_end();
    }
     
    /* -- À la demande  d’affichage de GlDrawingArea. ------------------------ */
    bool Interface::GlDrawingArea::on_expose_event (GdkEventExpose* event) {
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
     
      fenetreGl->gl_begin(get_gl_context());
     
        /* Vide l'écran et le Z-Buffer (Depth Buffer : contient les informations
           de profondeur de chaque pixel). */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        /* Repositionne la caméra. */
        glLoadIdentity();
     
        /* Bouge de 1.5 unités vers la gauche et de 6.0 unités vers l'intérieur
           de l'écran. */
        glTranslatef(-1.5f,0.0f,-6.0f);
     
        /* Dessiner un Triangle. */
        glBegin(GL_TRIANGLES);
          /* Point du haut. */
          glVertex3f( 0.0f, 1.0f, 0.0f);
          /* Point en bas à gauche. */
          glVertex3f(-1.0f,-1.0f, 0.0f);
          /* Point en bas à droite */
          glVertex3f( 1.0f,-1.0f, 0.0f);
        /* Le dessin du Triangle est fini */
        glEnd();
     
        /* Bouge de 3.0f unités vers la droite. */
        glTranslatef(3.0f,0.0f,0.0f);
     
        /* Dessin d'un quadrilatère. */
        glBegin(GL_QUADS);
          /* Haut Gauche. */
          glVertex3f(-1.0f, 1.0f, 0.0f);
          /* Haut Droite. */
          glVertex3f( 1.0f, 1.0f, 0.0f);
          /* Bas Droite. */
          glVertex3f( 1.0f,-1.0f, 0.0f);
          /* Bas Gauche. */
          glVertex3f(-1.0f,-1.0f, 0.0f);
        glEnd();
     
      fenetreGl->gl_end();
      fenetreGl->swap_buffers();
     
      /* Partie standard de la la procédure d’affichage. */
      return Gtk::Widget::on_expose_event(event);
    }
     
    /* -- Lorsque la fenêtre est redimensionnée. ----------------------------- */
    bool Interface::GlDrawingArea::on_configure_event (GdkEventConfigure* event) {
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
     
      fenetreGl->gl_begin(get_gl_context());
     
        /* Choisir la matrice de projection. */
        glMatrixMode(GL_PROJECTION);
        /* Remettre a zéro de la matrice de projection. */
        glLoadIdentity();
     
        /* Calculer le ratio pour la perspective de la fenêtre. */
        gluPerspective(45.0f, static_cast<GLfloat>(get_width())
                                / static_cast<GLfloat>(get_height()),
                       0.1f,100.0f);
        /* Choisir la matrice de modélisation. */
        glMatrixMode(GL_MODELVIEW);
        /* Remetre à zéro la matrice de modélisation. */
        glLoadIdentity();
     
      fenetreGl->gl_end();
     
      /* Partie standard du redimensionnement. */
      return Gtk::Widget::on_configure_event(event);
    }
     
    /* -- Constructeur par défaut de la fenêtre. ----------------------------- */
    Interface::Fenetre::Fenetre (): Gtk::Window (), zoneRendu () {
      set_title("Tutoriel 2");
      set_default_size(640, 480);
      /* Taille minimum pour éviter les divisions par zéro. */
      set_size_request(1, 1);
     
      add(zoneRendu);
     
      add_events(Gdk::KEY_RELEASE_MASK);
     
      signal_key_release_event().connect(sigc::mem_fun(*this,
                                                      &Fenetre::on_key_release));
      signal_window_state_event().connect(sigc::mem_fun(*this,
                                               &Fenetre::on_window_state_event));
     
      /* Boîte de dialogue pour le plein écran. */
      Gtk::MessageDialog pleinEcran (*this, "Passer en mode plein écran ?",
                                     false, Gtk::MESSAGE_QUESTION,
                                     Gtk::BUTTONS_YES_NO);
      /* Choix de l’utilisateur. */
      int choix = pleinEcran.run();
     
      if (choix == Gtk::RESPONSE_YES) {
        enPleinEcran = true;
        fullscreen();
      }
      else {
        set_border_width(2);
        enPleinEcran = false;
      }
     
      show_all_children();
    }
     
    /* -- Destructeur de la fenêtre. ----------------------------------------- */
     
    Interface::Fenetre::~Fenetre () {
    }
     
    /* -- Gestion des évènements claviers. ----------------------------------- */
    bool Interface::Fenetre::on_key_release (GdkEventKey* evenement) {
      switch (evenement->keyval) {
        case GDK_KEY_Escape:
          hide();
          break;
        case GDK_KEY_F1:
          if (enPleinEcran) {
            enPleinEcran = false;
    	set_border_width(2);
            unfullscreen();
          }
          else {
            enPleinEcran = true;
    	set_border_width(0);
            fullscreen();
          }
      }
     
      return true;
    }
     
    /* -- Lors du passage du mode plein écran au mode fenêtré. --------------- */
    bool Interface::Fenetre::on_window_state_event(GdkEventWindowState* pEven) {
      /* Résultat de la mise à jour standard de la fenêtre. */
      const bool resultat = Gtk::Widget::on_window_state_event(pEven);
     
      if (resultat) {
        /* Vérifie que l’écran est bien dans le mode souhaité. */
        if (enPleinEcran
            && (pEven->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)) {
          set_border_width(2);
          enPleinEcran = false;
          unfullscreen();
     
          /* Boîte de dialogue signifiant l’échec de l’opération. */
          Gtk::MessageDialog pleinEcran (*this,
                                      "Impossible de passer en mode plein écran",
                                         false, Gtk::MESSAGE_QUESTION,
                                         Gtk::BUTTONS_YES_NO);
          pleinEcran.set_secondary_text("Rester en mode fenêtré ?");
          /* Choix de l’utilisateur. */
          int choix = pleinEcran.run();
          if (choix == Gtk::RESPONSE_NO) return false;
        }
      }
     
      return resultat;
    }
    Fichier « src/main.cpp » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    /*
     * Deuxième tutoriel : création d’un triangle et d’un carré.
     */
     
    #include <iostream>
    #include <gtkmm/main.h>
    #include <sstream>
    #include <glibmm/error.h>
    #include <exception>
     
    #include "erreurs.hpp"
    #include "fenetre.hpp"
     
    /*
     * Principale fonction du programme.
     * Entrées :
     *   argc  Nombre d’arguments.
     *   argv  Valeures des arguments.
     * Retourne :
     *   0 si tout s’est bien passé.
     *   -1 en cas d’erreur venant de la GLib ou de ses dérivés.
     *   -2 en cas d’erreur en provenance d’OpenGL.
     *   -3 en cas d’erreur en provenance de la bibliothèque standard.
     *   -4 en cas d’erreur non standard.
     */
    int main (int argc, char** argv) {
      try {
        /* Boucle d’évènements. */
        const Gtk::Main kit(argc, argv);
        Gtk::GL::init(argc, argv);
     
        /* Fenêtre principale. */
        Interface::Fenetre principale;
     
        kit.run(principale);
     
        return 0;
      }
      catch(const Glib::Error &ex) {
        /* Message d’erreur. */
        std::ostringstream message;
        message << "Erreur venant de GLib : " <<  ex.what() << '\n';
        g_warning(message.str().c_str());
        return -1;
      }
      catch (const Erreurs::ErreurInterface &e) {
        /* Message d’erreur. */
        std::stringstream message;
        message << "Erreur de contexte OpenGL : " << e.what() << ".\n";
        g_critical(message.str().c_str());
        return -2;
      }
      catch (const std::exception &e) {
        /* Message d’erreur. */
        std::stringstream message;
        message << "Erreur venant de la bibliothèque standard : " << e.what()
                << '\n';
        g_critical(message.str().c_str());
        return -3;
      }
      catch (...) {
        g_critical("Exception non-standard.\n");
        return -4;
      }
    }
    À bientôt.

    Le Farfadet Spatial

  2. #2
    Membre éprouvé
    Avatar de Le Farfadet Spatial
    Inscrit en
    avril 2008
    Messages
    144
    Détails du profil
    Informations forums :
    Inscription : avril 2008
    Messages : 144
    Points : 424
    Points
    424

    Par défaut

    Salut à tous !

    Au cas où, j’essaye de relancer le sujet. Ça ressemble vraiment à un problème dans la configuration de Gtkmm, mais je n’arrive pas à déterminer ce que j’ai mal fait. Quelqu’un a-t-il déjà utilisé le mode plein écran avec Gtkmm ?

    À bientôt.

    Le Farfadet Spatial

  3. #3
    Membre éprouvé
    Avatar de Le Farfadet Spatial
    Inscrit en
    avril 2008
    Messages
    144
    Détails du profil
    Informations forums :
    Inscription : avril 2008
    Messages : 144
    Points : 424
    Points
    424

    Par défaut

    Salut à tous !

    Après pas mal d'errements et de découragement, j'en suis finalement arrivé à un code qui parvient à s'amorcer en plein écran. Tout d'abord, j'explique les raisons de ce que j'ai fait, si quelqu'un peut confirmer que je ne me trompe pas ou bien au contraire m'indiquer ce que j'ai mal compris, je lui en saurais gré.

    Donc, en cherchant sur le web, il ressort que visiblement un composant Gtk+ suit les étapes suivantes au cours de son existence :

    • Création ;
    • configuration (usuellement faite dans le constructeur) ;
    • réalisation (assigne une ressource système tel qu'une fenêtre X Window) ;
    • mapping (qui rend le composant visible sur l'écran) ;
    • « show » (qui réalise les deux précédentes étapes) ;
    • unmapping (qui supprime le composant de l'écran) ;
    • « hide » (une version plus simple de l'étape précédente) ;
    • destruction.


    J'ai fait appel à « show(); » juste avant de basculer en mode plein-écran et alors le code peut s'initialiser directement en plein écran. J'avais essayé avec uniquement « realize(); », mais ce n'était pas suffisant.

    Donc, ce qu'il me semble, c'est que Gtk+ ne peut pas passer en plein-écran un composant qui n'a pas déjà une fenêtre associée. Est-ce que quelqu'un peut confirmer cela ?

    Le code actuel.

    Fichier « CMakeLists.txt » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    ## Génération des tutoriels OpenGL de NeHe version Gtkmm.
     
    cmake_minimum_required(VERSION 2.6)
     
    project(Tutoriel2 CXX)
     
    # Répertoire où placer l’exécutable.
    set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
    # Nom de l’exécutable.
    set(EXECUTABLE_NAME tutoriel2)
     
    find_package(PkgConfig REQUIRED)
     
    pkg_check_modules(Glibmm glibmm-2.4>=2.4.0)
    pkg_check_modules(GTKmm gtkmm-2.4>=2.4.0)
    pkg_check_modules(GLExtmm gtkglextmm-1.2>=1.2.0)
     
    link_directories(
            ${Glibmm_LIBRARY_DIRS}
            ${GTKmm_LIBRARY_DIRS}
            ${GLExtmm_LIBRARY_DIRS}
    )
    include_directories(
            ${Glibmm_INCLUDE_DIRS}
            ${GTKmm_INCLUDE_DIRS}
            ${GLExtmm_INCLUDE_DIRS}
    )
     
    file(
            GLOB_RECURSE
            source_files
            src/*
    )
     
    add_executable(
            ${EXECUTABLE_NAME}
            ${source_files}
    )
     
    target_link_libraries(
            ${EXECUTABLE_NAME}
            ${Glibmm_LIBRARIES}
            ${GTKmm_LIBRARIES}
            ${GLExtmm_LIBRARIES}
    )
    Fichier « src/erreurs.hpp » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    #ifndef ERREURS_HPP
    #define ERREURS_HPP
     
    /*
     * Exceptions pour la gestions des erreurs.
     */
     
    #include <exception>
     
    /* Espace de nommage pour la gestion des erreurs. */
    namespace Erreurs {
    /* -- Erreurs provoquées par l’interface graphique. ---------------------- */
      class ErreurInterface: public std::exception {
        public:
          /* Constructeur par défaut. */
          ErreurInterface () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurInterface () throw () {}
     
          /* Génére le message d’erreur. */
          virtual const char* what () const throw () {
            return "une erreur s’est produite dans l’interface graphique";
          }
      };
     
    /* -- Erreur lors de la configuration d’OpenGL. -------------------------- */
      class ErreurConfigurationGL: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurConfigurationGL () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurConfigurationGL () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            return "erreur lors de la configuration d’OpenGL";
          }
      };
     
    /* -- Erreur lors de la création du contexte OpenGL. --------------------- */
      class ErreurCreationContexte: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurCreationContexte () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurCreationContexte () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            return "impossible de créer un contexte OpenGL";
          }
      };
     
    /* -- Erreur à l’obtention du contexte OpenGL. --------------------------- */
      class ErreurObtentionContexte: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurObtentionContexte () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurObtentionContexte () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            return "impossible d’obtenir le contexte OpenGL";
          }
      };
    }
     
    #endif  // #ifndef ERREURS_HPP
    Fichier « src/fenetre.hpp » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #ifndef FENETRE_HPP
    #define FENETRE_HPP
     
    /*
     * Définitions des classes gérants le fenêtrage OpenGL.
     */
     
    #include <gtkmm/window.h>
    #include <gtkmm/drawingarea.h>
    #include <gtkglmm.h>
     
    #include "erreurs.hpp"
     
    /* Espace de nommage pour la gestion de l’interface. */
    namespace Interface {
      /* Classe pour la zone de rendu OpenGL. */
      class GlDrawingArea: public Gtk::DrawingArea,
                           public Gtk::GL::Widget<GlDrawingArea> {
        public:
          GlDrawingArea ();
          virtual ~GlDrawingArea ();
     
        protected:
          /* -- Controleurs: */
     
          /* À l’initialisation de la fenêtre. */
          virtual void on_realize ();
     
          /* À la demande d’affichage. */
          virtual bool on_expose_event (GdkEventExpose* event);
     
          /* Au changement de taille de la fenêtre. */
          virtual bool on_configure_event (GdkEventConfigure* event);
      };
     
    /* ----------------------------------------------------------------------- */
     
      /* Classe pour la fenetre principale. */
      class Fenetre: public Gtk::Window {
        public:
          Fenetre ();
          virtual ~Fenetre();
     
        protected:
          /* -- Controleurs : */
     
          /* Gestion des évènements clavier. */
          bool on_key_release (GdkEventKey* evenement);
     
          /* Lors du passage du mode fenêtré au mode plein écran. */
          bool on_window_state_event (GdkEventWindowState *pEven);
     
          /* -- Composant membre : */
     
          /* Zone de rendu OpenGL. */
          GlDrawingArea zoneRendu;
     
        private:
          /* Indique si on se trouve en mode plein écran. */
          bool enPleinEcran;
      };
    }
     
    #endif  // #ifndef FENETRE_HPP
    Fichier « src/fenetre.cpp » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    /*
     * Implémentations du fenêtrage OpenGL.
     */
     
    #include <glibmm/error.h>
    #include <cstdlib>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <sstream>
    #include <gtkmm/messagedialog.h>
    #include <gdk/gdkkeysyms.h>
    #include <gdkmm/cursor.h>
     
    #include "fenetre.hpp"
     
    /* -- Constructeur par défaut de GlDrawingArea. -------------------------- */
    Interface::GlDrawingArea::GlDrawingArea (): Gtk::DrawingArea () {
      /* Configuration d’OpenGL */
      Glib::RefPtr<Gdk::GL::Config> configuration;
     
      /* Tente d’ouvrir une espace à double tampon. */
      configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA   |
                                              Gdk::GL::MODE_DEPTH  |
                                              Gdk::GL::MODE_DOUBLE);
      if (!configuration) {
        /* Message d’avertissement. */
        std::stringstream message;
        message << "Impossible de configurer OpenGL en mode double tampon, "
                << "tente le mode simple tampon.\n";
        g_warning(message.str().c_str());
        /* Tente de configurer un tampon simple. */
        configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA  |
                                                Gdk::GL::MODE_DEPTH);
        if (!configuration) throw Erreurs::ErreurConfigurationGL ();
      }
     
      /* Donne accès à OpenGL au composant. */
      set_gl_capability(configuration);
    }
     
    /* -- Destructeur de GlDrawingArea. -------------------------------------- */
    Interface::GlDrawingArea::~GlDrawingArea () {
    }
     
    /* -- Initialisation du contexte OpenGL. --------------------------------- */
    void Interface::GlDrawingArea::on_realize () {
      /* D’abord l’initialisation standard. */
      Gtk::Widget::on_realize();
     
      if (!create_gl_context()) throw Erreurs::ErreurCreationContexte ();
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl) throw Erreurs::ErreurObtentionContexte ();
     
      fenetreGl->gl_begin(get_gl_context());
     
        /* Permet un joli ombrage. */
        glShadeModel(GL_SMOOTH);
     
        /* Fond noir. */
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     
        /* Mis en place du tampon de profondeur. */
        glClearDepth(1.0f);
        /* Mis en place du test de profondeur. */
        glEnable(GL_DEPTH_TEST);
        /* Le type de test de profondeur . */
        glDepthFunc(GL_LEQUAL);
     
        /* Très jolis calculs de perspective. */
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
     
      fenetreGl->gl_end();
    }
     
    /* -- À la demande  d’affichage de GlDrawingArea. ------------------------ */
    bool Interface::GlDrawingArea::on_expose_event (GdkEventExpose* event) {
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
     
      fenetreGl->gl_begin(get_gl_context());
     
        /* Vide l'écran et le Z-Buffer (Depth Buffer : contient les informations
           de profondeur de chaque pixel). */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        /* Repositionne la caméra. */
        glLoadIdentity();
     
        /* Bouge de 1.5 unités vers la gauche et de 6.0 unités vers l'intérieur
           de l'écran. */
        glTranslatef(-1.5f,0.0f,-6.0f);
     
        /* Dessiner un Triangle. */
        glBegin(GL_TRIANGLES);
          /* Point du haut. */
          glVertex3f( 0.0f, 1.0f, 0.0f);
          /* Point en bas à gauche. */
          glVertex3f(-1.0f,-1.0f, 0.0f);
          /* Point en bas à droite */
          glVertex3f( 1.0f,-1.0f, 0.0f);
        /* Le dessin du Triangle est fini */
        glEnd();
     
        /* Bouge de 3.0f unités vers la droite. */
        glTranslatef(3.0f,0.0f,0.0f);
     
        /* Dessin d'un quadrilatère. */
        glBegin(GL_QUADS);
          /* Haut Gauche. */
          glVertex3f(-1.0f, 1.0f, 0.0f);
          /* Haut Droite. */
          glVertex3f( 1.0f, 1.0f, 0.0f);
          /* Bas Droite. */
          glVertex3f( 1.0f,-1.0f, 0.0f);
          /* Bas Gauche. */
          glVertex3f(-1.0f,-1.0f, 0.0f);
        glEnd();
     
      fenetreGl->gl_end();
      fenetreGl->swap_buffers();
     
      /* Partie standard de la la procédure d’affichage. */
      return Gtk::Widget::on_expose_event(event);
    }
     
    /* -- Lorsque la fenêtre est redimensionnée. ----------------------------- */
    bool Interface::GlDrawingArea::on_configure_event (GdkEventConfigure* event) {
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
     
      /* Largeur de la zone de rendu. */
      const GLsizei largeur = static_cast<GLsizei>(get_width());
      /* Hauteur de la zone de rendu. */
      const GLsizei hauteur = static_cast<GLsizei>(get_height());
     
      fenetreGl->gl_begin(get_gl_context());
     
        /* Fixer la taille de la zone de rendue. */
        glViewport(0, 0, largeur, hauteur);
        /* Choisir la matrice de projection. */
        glMatrixMode(GL_PROJECTION);
        /* Remettre a zéro de la matrice de projection. */
        glLoadIdentity();
     
        /* Calculer le ratio pour la perspective de la fenêtre. */
        gluPerspective(45.0f, static_cast<GLfloat>(largeur)
                                / static_cast<GLfloat>(hauteur), 0.1f,100.0f);
        glMatrixMode(GL_MODELVIEW);
        /* Remetre à zéro la matrice de modélisation. */
        glLoadIdentity();
     
      fenetreGl->gl_end();
     
      /* Partie standard du redimensionnement. */
      return Gtk::Widget::on_configure_event(event);
    }
     
    /* -- Constructeur par défaut de la fenêtre. ----------------------------- */
    Interface::Fenetre::Fenetre (): Gtk::Window (), zoneRendu () {
      set_title("Tutoriel 2");
      set_default_size(640, 480);
      /* Taille minimum pour éviter les divisions par zéro. */
      set_size_request(1, 1);
     
      add(zoneRendu);
     
      add_events(Gdk::KEY_RELEASE_MASK);
     
      signal_key_release_event().connect(sigc::mem_fun(*this,
                                                      &Fenetre::on_key_release));
      signal_window_state_event().connect(sigc::mem_fun(*this,
                                               &Fenetre::on_window_state_event));
     
      /* Boîte de dialogue pour le plein écran. */
      Gtk::MessageDialog pleinEcran (*this, "Passer en mode plein écran ?",
                                     false, Gtk::MESSAGE_QUESTION,
                                     Gtk::BUTTONS_YES_NO);
      /* Choix de l’utilisateur. */
      int choix = pleinEcran.run();
     
      if (choix == Gtk::RESPONSE_YES) {
        enPleinEcran = true;
        show();
        fullscreen();
     
        /* Créé un curseur vide. */
        const Gdk::Cursor cursor (Gdk::Display::get_default(),
                                  Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true,
                                                      8, 1, 1), 0, 0);
        /* Affiche le curseur vide, ce qui efface donc le curseur. */
        get_window()->set_cursor(cursor);
      }
      else {
        set_border_width(2);
        enPleinEcran = false;
      }
     
      show_all_children();
    }
     
    /* -- Destructeur de la fenêtre. ----------------------------------------- */
     
    Interface::Fenetre::~Fenetre () {
    }
     
    /* -- Gestion des évènements claviers. ----------------------------------- */
    bool Interface::Fenetre::on_key_release (GdkEventKey* evenement) {
      switch (evenement->keyval) {
        case GDK_KEY_Escape:
          hide();
          break;
        case GDK_KEY_F1:
          if (enPleinEcran) {
            enPleinEcran = false;
            set_border_width(2);
            unfullscreen();
            /* Revient au curseur par défaut, ce qui donc l’affiche de
               nouveau. */
            get_window()->set_cursor();
          }
          else {
            enPleinEcran = true;
            set_border_width(0);
            fullscreen();
            /* Créé un curseur vide. */
            const Gdk::Cursor cursor (Gdk::Display::get_default(),
                                      Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB,
                                                          true, 8, 1, 1), 0, 0);
            /* Affiche le curseur vide, ce qui efface donc le curseur. */
            get_window()->set_cursor(cursor);
          }
      }
     
      return true;
    }
     
    /* -- Lors du passage du mode plein écran au mode fenêtré. --------------- */
    bool Interface::Fenetre::on_window_state_event(GdkEventWindowState* pEven) {
      /* Résultat de la mise à jour standard de la fenêtre. */
      const bool resultat = Gtk::Widget::on_window_state_event(pEven);
     
      if (resultat) {
        /* Vérifie que l’écran est bien dans le mode souhaité. */
        if (enPleinEcran
            && (pEven->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)) {
          set_border_width(2);
          enPleinEcran = false;
          unfullscreen();
     
          /* Boîte de dialogue signifiant l’échec de l’opération. */
          Gtk::MessageDialog pleinEcran (*this,
                                      "Impossible de passer en mode plein écran",
                                         false, Gtk::MESSAGE_QUESTION,
                                         Gtk::BUTTONS_YES_NO);
          pleinEcran.set_secondary_text("Rester en mode fenêtré ?");
          /* Choix de l’utilisateur. */
          int choix = pleinEcran.run();
          if (choix == Gtk::RESPONSE_NO) return false;
        }
      }
     
      return resultat;
    }
    Fichier « src/main.cpp » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    /*
     * Deuxième tutoriel : création d’un triangle et d’un carré.
     */
     
    #include <iostream>
    #include <gtkmm/main.h>
    #include <sstream>
    #include <glibmm/error.h>
    #include <exception>
     
    #include "erreurs.hpp"
    #include "fenetre.hpp"
     
    /*
     * Principale fonction du programme.
     * Entrées :
     *   argc  Nombre d’arguments.
     *   argv  Valeures des arguments.
     * Retourne :
     *   0 si tout s’est bien passé.
     *   -1 en cas d’erreur venant de la GLib ou de ses dérivés.
     *   -2 en cas d’erreur en provenance d’OpenGL.
     *   -3 en cas d’erreur en provenance de la bibliothèque standard.
     *   -4 en cas d’erreur non standard.
     */
    int main (int argc, char** argv) {
      try {
        /* Boucle d’évènements. */
        const Gtk::Main kit(argc, argv);
        Gtk::GL::init(argc, argv);
     
        /* Fenêtre principale. */
        Interface::Fenetre principale;
     
        kit.run(principale);
     
        return 0;
      }
      catch(const Glib::Error &ex) {
        /* Message d’erreur. */
        std::ostringstream message;
        message << "Erreur venant de GLib : " <<  ex.what() << '\n';
        g_critical(message.str().c_str());
        return -1;
      }
      catch (const Erreurs::ErreurInterface &e) {
        /* Message d’erreur. */
        std::stringstream message;
        message << "Erreur de contexte OpenGL : " << e.what() << ".\n";
        g_critical(message.str().c_str());
        return -2;
      }
      catch (const std::exception &e) {
        /* Message d’erreur. */
        std::stringstream message;
        message << "Erreur venant de la bibliothèque standard : " << e.what()
                << '\n';
        g_critical(message.str().c_str());
        return -3;
      }
      catch (...) {
        g_critical("Exception non-standard.\n");
        return -4;
      }
    }
    Je laisse un peu de temps avant de passer le sujet en résolu, pour le cas où quelqu’un aurait une réponse à apporter.

    À bientôt.

    Le Farfadet Spatial

  4. #4
    Membre éprouvé
    Avatar de Le Farfadet Spatial
    Inscrit en
    avril 2008
    Messages
    144
    Détails du profil
    Informations forums :
    Inscription : avril 2008
    Messages : 144
    Points : 424
    Points
    424

    Par défaut

    Salut à tous !

    Ma demande d’aide sur la liste de diffusion de Gtkmm a fini par trouver une réponse. Il en ressort que si les étapes de la vie d’un composant Gtk+ que j’ai donné dans le message précédent sont bonnes, en revanche il n’est pas nécessaire d’attendre un « show() » avant de passer une fenêtre en plein-écran. Le problème, c’est que j’avais oublié des étapes. Pour passer une fenêtre Gtk+ en plein écran, il faut réaliser les étapes suivantes :

    1. Supprimer la décoration de la fenêtre, c’est-à-dire la barre de titre (« set_decorated(false); ») ;
    2. maximiser la fenêtre (« maximize(); ») ;
    3. passer en mode plein-écran (« fullscreen(); »).


    En revanche, pour effacer le curseur de la souris, il faut faire appel à la fonction « get_window(); » qui ne renvoie un pointeur non-nul que si la fenêtre a été réalisée.

    Voici donc le code final :

    Fichier « CMakeLists.txt » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    ## Génération des tutoriels OpenGL de NeHe version Gtkmm.
     
    cmake_minimum_required(VERSION 2.6)
     
    project(Tutoriel2 CXX)
     
    # Répertoire où placer l’exécutable.
    set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
    # Nom de l’exécutable.
    set(EXECUTABLE_NAME tutoriel2)
     
    find_package(PkgConfig REQUIRED)
     
    pkg_check_modules(Glibmm glibmm-2.4>=2.4.0)
    pkg_check_modules(GTKmm gtkmm-2.4>=2.4.0)
    pkg_check_modules(GLExtmm gtkglextmm-1.2>=1.2.0)
     
    link_directories(
            ${Glibmm_LIBRARY_DIRS}
            ${GTKmm_LIBRARY_DIRS}
            ${GLExtmm_LIBRARY_DIRS}
    )
    include_directories(
            ${Glibmm_INCLUDE_DIRS}
            ${GTKmm_INCLUDE_DIRS}
            ${GLExtmm_INCLUDE_DIRS}
    )
     
    file(
            GLOB_RECURSE
            source_files
            src/*
    )
     
    add_executable(
            ${EXECUTABLE_NAME}
            ${source_files}
    )
     
    target_link_libraries(
            ${EXECUTABLE_NAME}
            ${Glibmm_LIBRARIES}
            ${GTKmm_LIBRARIES}
            ${GLExtmm_LIBRARIES}
    )
    Fichier « src/erreurs.hpp »

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    #ifndef ERREURS_HPP
    #define ERREURS_HPP
     
    /*
     * Exceptions pour la gestions des erreurs.
     */
     
    #include <exception>
     
    /* Espace de nommage pour la gestion des erreurs. */
    namespace Erreurs {
    /* -- Erreurs provoquées par l’interface graphique. ---------------------- */
      class ErreurInterface: public std::exception {
        public:
          /* Constructeur par défaut. */
          ErreurInterface () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurInterface () throw () {}
     
          /* Génére le message d’erreur. */
          virtual const char* what () const throw () {
            return "une erreur s’est produite dans l’interface graphique";
          }
      };
     
    /* -- Erreur lors de la configuration d’OpenGL. -------------------------- */
      class ErreurConfigurationGL: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurConfigurationGL () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurConfigurationGL () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            return "erreur lors de la configuration d’OpenGL";
          }
      };
     
    /* -- Erreur lors de la création du contexte OpenGL. --------------------- */
      class ErreurCreationContexte: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurCreationContexte () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurCreationContexte () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            return "impossible de créer un contexte OpenGL";
          }
      };
     
    /* -- Erreur à l’obtention du contexte OpenGL. --------------------------- */
      class ErreurObtentionContexte: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurObtentionContexte () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurObtentionContexte () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            return "impossible d’obtenir le contexte OpenGL";
          }
      };
    }
     
    #endif  /* #ifndef ERREURS_HPP */
    Fichier « src/fenetre.hpp » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    #ifndef FENETRE_HPP
    #define FENETRE_HPP
     
    /*
     * Définitions des classes gérants le fenêtrage OpenGL.
     */
     
    #include <gtkmm/window.h>
    #include <gtkmm/drawingarea.h>
    #include <gtkglmm.h>
     
    #include "erreurs.hpp"
     
    /* Espace de nommage pour la gestion de l’interface. */
    namespace Interface {
      /* Classe pour la zone de rendu OpenGL. */
      class GlDrawingArea: public Gtk::DrawingArea,
                           public Gtk::GL::Widget<GlDrawingArea> {
        public:
          GlDrawingArea ();
          virtual ~GlDrawingArea ();
     
        protected:
          /* -- Controleurs: */
     
          /* À l’initialisation de la fenêtre. */
          virtual void on_realize ();
     
          /* À la demande d’affichage. */
          virtual bool on_expose_event (GdkEventExpose* event);
     
          /* Au changement de taille de la fenêtre. */
          virtual bool on_configure_event (GdkEventConfigure* event);
      };
     
    /* ----------------------------------------------------------------------- */
     
      /* Classe pour la fenetre principale. */
      class Fenetre: public Gtk::Window {
        public:
          Fenetre ();
          virtual ~Fenetre();
     
        protected:
          /* -- Controleurs : */
     
          /* Gestion des évènements clavier. */
          bool on_key_release (GdkEventKey* evenement);
     
          /* Lors du passage du mode fenêtré au mode plein écran. */
          bool on_window_state_event (GdkEventWindowState* pEven);
     
          /* -- Composant membre : */
     
          /* Zone de rendu OpenGL. */
          GlDrawingArea zoneRendu;
     
        private:
          /* Change de mode d’affichage : de fenêtré à plein-écran et
             inversement. */
          void echangeModeAffichage ();
      };
    }
     
    #endif  /* #ifndef FENETRE_HPP */
    Fichier « src/fenetre.cpp » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    /*
     * Implémentations du fenêtrage OpenGL.
     */
     
    #include <glibmm/error.h>
    #include <cstdlib>
    #include <GL/glu.h>
    #include <sstream>
    #include <gtkmm/messagedialog.h>
    #include <gdk/gdkkeysyms.h>
    #include <gdkmm/cursor.h>
     
    #include "fenetre.hpp"
     
    /* -- Constructeur par défaut de GlDrawingArea. -------------------------- */
    Interface::GlDrawingArea::GlDrawingArea (): Gtk::DrawingArea () {
      #ifndef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED
        /* Connecte les contrôleurs de signaux s’il ne s’agit pas déjà de
           méthodes virtuelles surchargées : */
        signal_realize().connect(sigc::mem_fun(*this,
                                               &GlDrawingArea::on_realize),
                                 false);
        signal_expose_event().connect(sigc::mem_fun(*this,
                                                &GlDrawingArea::on_expose_event),
                                      false);
        signal_configure_event().connect(sigc::mem_fn(*this,
                                             &GlDrawingArea::on_configure_event),
                                         false);
      #endif  /* #ifndef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED */
     
      /* Configuration d’OpenGL */
      Glib::RefPtr<Gdk::GL::Config> configuration;
     
      /* Tente d’ouvrir une espace à double tampon. */
      configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA   |
                                              Gdk::GL::MODE_DEPTH  |
                                              Gdk::GL::MODE_DOUBLE);
      if (!configuration) {
        /* Message d’avertissement. */
        std::stringstream message;
        message << "Impossible de configurer OpenGL en mode double tampon, "
                << "tente le mode simple tampon.\n";
        g_warning(message.str().c_str());
        /* Tente de configurer un tampon simple. */
        configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA  |
                                                Gdk::GL::MODE_DEPTH);
        if (!configuration) throw Erreurs::ErreurConfigurationGL ();
      }
     
      /* Donne accès à OpenGL au composant. */
      set_gl_capability(configuration);
    }
     
    /* -- Destructeur de GlDrawingArea. -------------------------------------- */
    Interface::GlDrawingArea::~GlDrawingArea () {
    }
     
    /* -- Initialisation du contexte OpenGL. --------------------------------- */
    void Interface::GlDrawingArea::on_realize () {
      /* D’abord l’initialisation standard. */
      Gtk::Widget::on_realize();
     
      if (!create_gl_context()) throw Erreurs::ErreurCreationContexte ();
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl) throw Erreurs::ErreurObtentionContexte ();
     
      fenetreGl->gl_begin(get_gl_context());
     
        /* Permet un joli ombrage. */
        glShadeModel(GL_SMOOTH);
     
        /* Fond noir. */
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     
        /* Mis en place du tampon de profondeur. */
        glClearDepth(1.0f);
        /* Mis en place du test de profondeur. */
        glEnable(GL_DEPTH_TEST);
        /* Le type de test de profondeur . */
        glDepthFunc(GL_LEQUAL);
     
        /* Très jolis calculs de perspective. */
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
     
      fenetreGl->gl_end();
    }
     
    /* -- À la demande  d’affichage de GlDrawingArea. ------------------------ */
    bool Interface::GlDrawingArea::on_expose_event (GdkEventExpose* event) {
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
     
      fenetreGl->gl_begin(get_gl_context());
     
        /* Vide l'écran et le Z-Buffer (Depth Buffer : contient les informations
           de profondeur de chaque pixel). */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        /* Repositionne la caméra. */
        glLoadIdentity();
     
        /* Bouge de 1.5 unités vers la gauche et de 6.0 unités vers l'intérieur
           de l'écran. */
        glTranslatef(-1.5f,0.0f,-6.0f);
     
        /* Dessiner un Triangle. */
        glBegin(GL_TRIANGLES);
          /* Point du haut. */
          glVertex3f( 0.0f, 1.0f, 0.0f);
          /* Point en bas à gauche. */
          glVertex3f(-1.0f,-1.0f, 0.0f);
          /* Point en bas à droite */
          glVertex3f( 1.0f,-1.0f, 0.0f);
        /* Le dessin du Triangle est fini */
        glEnd();
     
        /* Bouge de 3.0f unités vers la droite. */
        glTranslatef(3.0f,0.0f,0.0f);
     
        /* Dessin d'un quadrilatère. */
        glBegin(GL_QUADS);
          /* Haut Gauche. */
          glVertex3f(-1.0f, 1.0f, 0.0f);
          /* Haut Droite. */
          glVertex3f( 1.0f, 1.0f, 0.0f);
          /* Bas Droite. */
          glVertex3f( 1.0f,-1.0f, 0.0f);
          /* Bas Gauche. */
          glVertex3f(-1.0f,-1.0f, 0.0f);
        glEnd();
     
      fenetreGl->gl_end();
      fenetreGl->swap_buffers();
     
      /* Partie standard de la la procédure d’affichage. */
      return Gtk::Widget::on_expose_event(event);
    }
     
    /* -- Lorsque la fenêtre est redimensionnée. ----------------------------- */
    bool Interface::GlDrawingArea::on_configure_event
        (GdkEventConfigure* event) {
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
     
      /* Largeur de la zone de rendu. */
      const GLsizei largeur = static_cast<GLsizei>(get_width());
      /* Hauteur de la zone de rendu. */
      const GLsizei hauteur = static_cast<GLsizei>(get_height());
     
      fenetreGl->gl_begin(get_gl_context());
     
        /* Fixer la taille de la zone de rendue. */
        glViewport(0, 0, largeur, hauteur);
        /* Choisir la matrice de projection. */
        glMatrixMode(GL_PROJECTION);
        /* Remettre a zéro de la matrice de projection. */
        glLoadIdentity();
     
        /* Calculer le ratio pour la perspective de la fenêtre. */
        gluPerspective(45.0f, static_cast<GLfloat>(largeur)
                                / static_cast<GLfloat>(hauteur), 0.1f,100.0f);
        glMatrixMode(GL_MODELVIEW);
        /* Remetre à zéro la matrice de modélisation. */
        glLoadIdentity();
     
      fenetreGl->gl_end();
     
      /* Partie standard du redimensionnement. */
      return Gtk::Widget::on_configure_event(event);
    }
     
    /* -- Constructeur par défaut de la fenêtre. ----------------------------- */
    Interface::Fenetre::Fenetre (): Gtk::Window (), zoneRendu () {
      set_title("Tutoriel 1");
      set_default_size(640, 480);
      /* Taille minimum pour éviter les divisions par zéro. */
      set_size_request(1, 1);
     
      add(zoneRendu);
     
      set_border_width(2);
     
      add_events(Gdk::KEY_RELEASE_MASK);
     
      signal_key_release_event().connect(sigc::mem_fun(*this,
                                                      &Fenetre::on_key_release));
      signal_window_state_event().connect(sigc::mem_fun(*this,
                                               &Fenetre::on_window_state_event));
     
      /* Boîte de dialogue pour le plein écran. */
      Gtk::MessageDialog pleinEcran (*this, "Passer en mode plein écran ?",
                                     false, Gtk::MESSAGE_QUESTION,
                                     Gtk::BUTTONS_YES_NO);
      /* Choix de l’utilisateur. */
      int choix = pleinEcran.run();
     
      if (choix == Gtk::RESPONSE_YES) {
        show();
        echangeModeAffichage();
      }
     
      show_all_children();
    }
     
    /* -- Destructeur de la fenêtre. ----------------------------------------- */
     
    Interface::Fenetre::~Fenetre () {
    }
     
    /* -- Échange de mode d’affichage. --------------------------------------- */
    void Interface::Fenetre::echangeModeAffichage () {
      set_decorated(!get_decorated());
      if (get_decorated()) {
        unfullscreen();
        unmaximize();
        /* Revient au curseur par défaut, ce qui donc l’affiche de
           nouveau. */
        get_window()->set_cursor();
        set_border_width(2);
      }
      else {
        set_border_width(0);
        /* Créé un curseur vide. */
        const Gdk::Cursor cursor (Gdk::Display::get_default(),
                                  Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true,
                                                      8, 1, 1), 0, 0);
        /* Affiche le curseur vide, ce qui efface donc le curseur. */
        get_window()->set_cursor(cursor);
        maximize();
        fullscreen();
      }
    }
     
    /* -- Gestion des évènements claviers. ----------------------------------- */
    bool Interface::Fenetre::on_key_release (GdkEventKey* evenement) {
      switch (evenement->keyval) {
        case GDK_KEY_Escape:
          hide();
          break;
        case GDK_KEY_F1:
          echangeModeAffichage();
      }
     
      return true;
    }
     
    /* -- Lors du passage du mode plein écran au mode fenêtré. --------------- */
    bool Interface::Fenetre::on_window_state_event(GdkEventWindowState* pEven) {
      /* Résultat de la mise à jour standard de la fenêtre. */
      const bool resultat = Gtk::Widget::on_window_state_event(pEven);
     
      if (resultat) {
        /* Vérifie que l’écran est bien dans le mode souhaité. */
        if (!get_decorated()
            && (pEven->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)) {
          unfullscreen();
          unmaximize();
          set_decorated(true);
          /* Curseur par défaut. */
          get_window()->set_cursor();
          set_border_width(2);
     
          /* Boîte de dialogue signifiant l’échec de l’opération. */
          Gtk::MessageDialog pleinEcran (*this,
                                      "Impossible de passer en mode plein écran",
                                         false, Gtk::MESSAGE_QUESTION,
                                         Gtk::BUTTONS_YES_NO);
          pleinEcran.set_secondary_text("Rester en mode fenêtré ?");
          /* Choix de l’utilisateur. */
          int choix = pleinEcran.run();
          if (choix == Gtk::RESPONSE_NO) return false;
        }
      }
     
      return resultat;
    }
    Fichier « src/main.cpp » :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    /*
     * Deuxième tutoriel : création d’un triangle et d’un carré.
     */
     
    #include <iostream>
    #include <gtkmm/main.h>
    #include <sstream>
    #include <glibmm/error.h>
    #include <exception>
     
    #include "erreurs.hpp"
    #include "fenetre.hpp"
     
    /*
     * Principale fonction du programme.
     * Entrées :
     *   argc  Nombre d’arguments.
     *   argv  Valeures des arguments.
     * Retourne :
     *   0 si tout s’est bien passé.
     *   -1 en cas d’erreur venant de la GLib ou de ses dérivés.
     *   -2 en cas d’erreur en provenance d’OpenGL.
     *   -3 en cas d’erreur en provenance de la bibliothèque standard.
     *   -4 en cas d’erreur non standard.
     */
    int main (int argc, char** argv) {
      try {
        /* Boucle d’évènements. */
        const Gtk::Main kit(argc, argv);
        Gtk::GL::init(argc, argv);
     
        /* Fenêtre principale. */
        Interface::Fenetre principale;
     
        kit.run(principale);
     
        return 0;
      }
      catch(const Glib::Error &ex) {
        /* Message d’erreur. */
        std::ostringstream message;
        message << "Erreur venant de GLib : " <<  ex.what() << '\n';
        g_critical(message.str().c_str());
        return -1;
      }
      catch (const Erreurs::ErreurInterface &e) {
        /* Message d’erreur. */
        std::stringstream message;
        message << "Erreur de contexte OpenGL : " << e.what() << ".\n";
        g_critical(message.str().c_str());
        return -2;
      }
      catch (const std::exception &e) {
        /* Message d’erreur. */
        std::stringstream message;
        message << "Erreur venant de la bibliothèque standard : " << e.what()
                << '\n';
        g_critical(message.str().c_str());
        return -3;
      }
      catch (...) {
        g_critical("Exception non-standard.\n");
        return -4;
      }
    }
    Cette fois-ci, je passe le sujet en résolu.

    À bientôt.

    Le Farfadet Spatial

+ Répondre à la discussion
Cette discussion est résolue.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •