Gestion des événements avec OpenSceneGraph

Alys Beauvarlet, Thierry Bonnefoy, Bertrand Rix, Guillaume Saby

Présentation de la gestion des événements dans OpenSceneGraph.

Commentez

- Titre : Gestion des événements avec OpenSceneGraph

- Auteur : Alys Beauvarlet, Thierry Bonnefoy, Bertrand Rix, Guillaume Saby

- Parution : 25 juin 2012

- Mise à jour : 27 janvier 2013

- Public visé :

- Licence : Copyright ® 2013 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- 1. Introduction

- 2. Classes et fonctions utilisées

- 3. Mise en Pratique

- 3-A. Mise en place du programme principal

- 3-B. Mise en place des évènements

- 4. Remerciements

1 - Introduction

Ce tutoriel a pour but de permettre à l'utilisateur d'acquérir une maîtrise basique de la classe de gestion d'événements d'OpenScenegraph. Il permettra au lecteur de pouvoir implémenter dans son propre programme, de façon simple, les événements clavier et souris.

Le programme développé a pour but simple de changer la couleur de fond de la scène à la pression d'une touche ou le double-clic de la souris.

2 - Classes et fonctions utilisées

Classe :

GUIEventHandler  : c'est la classe de gestion d'événements OpenSceneGraph. Elle permet de récupérer les événements de la fenêtre pour ensuite les traiter.

Fonction :

bool handle(const osgGA::GUIEventAdapter&,osgGA::GUIActionAdapter&) : c'est la fonction principale de la classe ci-dessus. Elle permet de traiter l'événement récupéré dans le GUIEventAdapter.

3 - Mise en Pratique

3-A - Mise en place du programme principal

Tout d'abord il est nécessaire d'avoir un programme de base simple afin de tester la classe.

Pour cela, prenons simplement une scène contenant un cube. On créera une fonction pour cela afin de bien séparer le code :

// Création de la scène : cube
/******************************************************************************************
******************************************************************************************/
osg::Node* CreateScene()
{
// Déclare un groupe servant de nœud principal :
osg::Group* root = new osg::Group();

// Création du cube
osg::Box* unitCube = new osg::Box( osg::Vec3(0,0,0), 1.0f);

// Met le cube dans un drawable pour pouvoir l'ajouter ensuite à la scène
osg::ShapeDrawable* unitCubeDrawable = new osg::ShapeDrawable(unitCube);

// Déclare une instance de la classe Geode
osg::Geode* basicShapesGeode = new osg::Geode();

// Ajoute unitCubeDrawable à ce dernier
basicShapesGeode->addDrawable(unitCubeDrawable);

// Ajoute le Geode à la scène
root->addChild(basicShapesGeode);

return root;
}

Ensuite dans une fonction main nous allons ajouter le viewer, qui permettra de visualiser la scène, une caméra, puis notre scène. Tout d'abord, pour notre programme de tutoriel, le viewer sera déclaré en global afin de permettre à la fonction de gestion d'événements d'y accéder. Il sera donc déclaré ainsi :

// Création du viewer
/*****************************************************************************************
*****************************************************************************************/
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;

osg::ref_ptr<osgViewer::Viewer> étant simplement la déclaration d'un pointeur vers un type viewer.

Ensuite nous créons la fonction principale qui contiendra la fenêtre dans laquelle est importée notre scène et la caméra. Cela n'est pas l'objet de ce tutoriel, pour plus de détail, se référer au tutoriel concernant le programme de base :

int main(int argc, char* argv[])
{
// Crée une fenêtre de 512x512 en position 100, 100
viewer->setUpViewInWindow( 100, 100, 512, 512 );

// Caméra
/***********************************************************************************
***********************************************************************************/

// Change la matrice de projection
viewer->getCamera()->setProjectionMatrixAsPerspective(
45.0,
viewer->getCamera()->getViewport()->aspectRatio(),
0.1,
1000.0
);

// Change la couleur du fond
viewer->getCamera()->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 0.0));

// Definit la scène comme celle du viewer
viewer->setSceneData(CreateScene());

// Exécution du programme
/***********************************************************************************
***********************************************************************************/
viewer->realize();

// Exécution manuelle de la boucle d'exécution afin de replacer la caméra par défaut
// (voir tutoriel sur les caméras)
while(!viewer->done())
{
viewer->advance();
viewer->eventTraversal();
viewer->updateTraversal();
viewer->getCamera()->setViewMatrixAsLookAt(osg::Vec3d(0.0, -3.0, 3.0),
osg::Vec3d(0.0, 0.0, 0.0), osg::Vec3d(0.0, 0.0, 1.0));
viewer->renderingTraversals();
}
}

Afin que ce programme puisse fonctionner il est nécessaire d'ajouter à notre code les bibliothèques nécessaires, ce qui se fera par les lignes suivantes placées en début de code :

#include <osgViewer/Viewer>
#include <osg/Group>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Camera>
#include <osgGA/GUIEventHandler>
#include <iostream>

3-B - Mise en place des évènements

Venons-en enfin à notre gestion d'événements. Pour cela il est nécessaire de dériver la classe GUIEventHandler d'OpenSceneGraph et de redéfinir la fonction bool handle (const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&) dans notre nouvelle classe.

Cette classe, si elle est déclarée dans notre programme principal (ce qui est le cas pour ce tutoriel, sera placée avant la fonction principale (main)).

La gestion complète se fera donc par la fonction

bool handle (const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&) que nous redéfinirons. Dans ce tutoriel seul le premier paramètre sera utilisé. C'est lui qui récupère l'événement. Nous définirons donc en fonction de chaque événement les actions à effectuer :

bool gestionnaireEvenements::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
{
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYDOWN):
{
viewer->getCamera()->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 0.0));
break;
}
case(osgGA::GUIEventAdapter::KEYUP):
{
switch(ea.getKey())
{
case 't':
viewer->getCamera()->setClearColor(osg::Vec4(1.0, 0.0, 0.0, 0.0));
return false;
break;
case 'g':
viewer->getCamera()->setClearColor(osg::Vec4(0.0, 1.0, 0.0, 0.0));
return false;
break;
case 'b':
viewer->getCamera()->setClearColor(osg::Vec4(0.0, 0.0, 1.0, 0.0));
return false;
break;
case 'h':
std::cout<<"t - bleu"<<std::endl
<<"g - vert"<<std::endl
<<"b - rouge"<<std::endl
<<"autre : noir"<<endl;
return false;
break;
default:
return false;
}
}
case(osgGA::GUIEventAdapter::DOUBLECLICK):
{

osgGA::GUIEventAdapter::KEYDOWN désigne l'action de presser une touche ;

osgGA::GUIEventAdapter::KEYUP désigne la fin de pression d'une touche ;

osgGA::GUIEventAdapter::DOUBLECLICK désigne le double-clic de la souris.

Ce tutoriel ne liste pas tous les événements possibles, pour en savoir plus se référer à la documentation OpenSceneGraph ici.

Il nous suffit ensuite d'intégrer notre gestionnaire d'événements à la fonction principale par ces lignes :

// Événements
/******************************************************************************************
******************************************************************************************/
// Création de l'objet de gestion d'événements clavier
gestionnaireEvenements* evenements = new gestionnaireEvenements();

// Ajout des événements au viewer
viewer->addEventHandler(evenements);

le gestionnaire d'événements est ainsi intégré au viewer, le programme fonctionne !

4 - Remerciements

Merci jacques_jean pour les corrections.