OpenSceneGraph: Gestion de Windows et des modes d'affichage

image

Présentation


Nous avons dĂ©jĂ  dit que la classe osg :: Camera gĂšre le contexte graphique OpenGL associĂ©. Le contexte graphique encapsule des informations sur comment et oĂč les objets sont dessinĂ©s et quels attributs d'Ă©tat leur sont appliquĂ©s. Le contexte est compris comme une fenĂȘtre graphique, ou plutĂŽt sa zone cliente, ou un tampon de pixels OpenGL qui stocke les donnĂ©es de pixels sans les transfĂ©rer dans le tampon de trame.

OSG utilise la classe osg :: GraphicsContext pour reprĂ©senter un contexte graphique abstrait et la classe osg :: GraphicsWindow pour reprĂ©senter une fenĂȘtre graphique abstraite. Ce dernier a une mĂ©thode getEventQueue () pour gĂ©rer les Ă©vĂ©nements Ă  partir des Ă©lĂ©ments GUI. De maniĂšre gĂ©nĂ©rale, un contexte graphique est un concept spĂ©cifique Ă  la plate-forme, donc OSG s'occupe de la plupart du travail de crĂ©ation d'une fenĂȘtre et d'association de son contexte au contexte OpenGL. Lorsque vous appelez la mĂ©thode createGraphicsContext () de la classe osg :: GraphicsContext (), le code requis (et il y en a beaucoup, croyez-moi!) Sera gĂ©nĂ©rĂ© automatiquement par le prĂ©processeur, selon la plate-forme. Tout ce que nous avons Ă  faire est de passer un argument Ă  cette mĂ©thode de type osg :: GraphicsContex :: Traits, qui contient une description de la fenĂȘtre que nous voulons obtenir.

1. La classe osg :: DisplaySettings


OSG permet au dĂ©veloppeur de gĂ©rer les paramĂštres d'affichage globaux, sur la base des camĂ©ras, des visionneuses et des Ă©lĂ©ments de scĂšne rendus. Pour cela, le modĂšle singleton est utilisĂ©, c'est-Ă -dire un objet unique contenant ces paramĂštres, implĂ©mentĂ© sous la forme de la classe osg :: DisplaySettings, accessible Ă  partir de n'importe oĂč dans le programme. Par consĂ©quent, Ă  partir de notre application, nous pouvons modifier ces paramĂštres Ă  tout moment.

osg::DisplaySettings *ds = osg::DisplaySettings::instance(); 

Singleton osg :: DisplaySettings contient les paramĂštres qui s'appliquent aux pĂ©riphĂ©riques de rendu nouvellement créés, le contexte OpenGL de la fenĂȘtre graphique. Vous pouvez faire varier les paramĂštres suivants:

  1. setDoubleBuffer () - active / désactive la double mise en mémoire tampon. Activé par défaut.
  2. setDepthBuffer () - active / désactive le tampon de profondeur. Activé par défaut.
  3. Définissez la largeur du tampon alpha, du tampon de gabarit et du tampon d'accumulation à l'aide de méthodes telles que setMinimumNumAlphaBits (). Par défaut, tous les paramÚtres sont 0.
  4. Autorisation d'utiliser l'anticrénelage et sa profondeur à l'aide de la méthode setNumMultiSamples (). La valeur par défaut est 0.
  5. Activez le mode stéréo. Désactivé par défaut.

Considérez l'utilisation de ce singleton sur l'exemple du lissage

Exemple de singleton Osg :: DisplaySettings
main.h

 #ifndef MAIN_H #define MAIN_H #include <osgDB/ReadFile> #include <osgViewer/Viewer> #endif 

main.cpp

 #include "main.h" int main(int argc, char *argv[]) { (void) argc; (void) argv; osg::DisplaySettings::instance()->setNumMultiSamples(6); osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/cessna.osg"); osgViewer::Viewer viewer; viewer.setSceneData(model.get()); return viewer.run(); } 


L'essentiel ici n'est qu'un défi.

 osg::DisplaySettings::instance()->setNumMultiSamples(6); 

- définir le paramÚtre de lissage, qui peut prendre des valeurs 2, 4 et 6, selon le périphérique graphique utilisé. Faites attention à l'apparence de la lame de la vis Cessna sans appliquer de lissage



et aprĂšs son application



2. Passer en mode fenĂȘtre


La classe osgViewer :: Viewer peut ĂȘtre trĂšs rapidement reconfigurĂ©e pour s'afficher en mode fenĂȘtrĂ©. Comme vous l'avez remarquĂ©, tous nos exemples prĂ©cĂ©dents Ă©taient affichĂ©s en plein Ă©cran. Pour basculer le visualiseur en mode fenĂȘtrĂ©, il existe la mĂ©thode setUpViewInWindow (), qui prend comme paramĂštres les coordonnĂ©es du coin supĂ©rieur gauche de la fenĂȘtre, sa largeur et sa hauteur en pixels

 viewer.setUpViewInWindow(50, 50, 800, 600); 

Facultativement, cette mĂ©thode accepte le cinquiĂšme paramĂštre - le numĂ©ro de l'Ă©cran sur lequel la fenĂȘtre doit ĂȘtre affichĂ©e, au cas oĂč vous avez plus d'un moniteur. En travaillant sĂ»rement avec plusieurs moniteurs sous Windows, vous avez observĂ© que la scĂšne se propage Ă  tous les moniteurs en mode plein Ă©cran (ce qui n'est pas observĂ© sous Linux).

De plus, dans les paramÚtres du projet, vous pouvez définir la variable d'environnement OSG_WINDOW de cette maniÚre



qui Ă©quivaudra Ă  appeler setUpViewInWindow (), qui dans ce cas peut ne pas ĂȘtre exĂ©cutĂ©.



Pour spĂ©cifier explicitement l'Ă©cran sur lequel la visionneuse doit ĂȘtre affichĂ©e en mode plein Ă©cran, vous pouvez utiliser la mĂ©thode setUpViewOnSingleScreen () en spĂ©cifiant le numĂ©ro d'Ă©cran comme paramĂštre (par dĂ©faut 0).

OSG prend également en charge les écrans sphériques de démonstration. Vous pouvez utiliser la méthode setUpViewFor3DSphericalDisplay () pour personnaliser l'affichage sur un tel affichage.

3. Visionneuse composite


La classe osgViewer :: Viewer contrĂŽle une seule vue affichant un seul graphique de scĂšne. En plus, il existe une classe osgViewer :: CompositeViewer qui prend en charge plusieurs vues et plusieurs scĂšnes. Il a les mĂȘmes mĂ©thodes run (), frame () et done () pour contrĂŽler le processus de rendu, mais il vous permet d'ajouter et de supprimer des vues indĂ©pendantes Ă  l'aide des mĂ©thodes addView () et removeView (), ainsi que d'obtenir des vues par leur index Ă  l'aide de la mĂ©thode getView (). L'objet view est dĂ©crit par la classe osgViewer :: View.

La classe osgViewer :: View est la classe de base de la classe osgViewer :: Viewer. Il vous permet d'ajouter un nƓud racine avec des donnĂ©es de scĂšne, un manipulateur de camĂ©ra et des gestionnaires d'Ă©vĂ©nements. La principale diffĂ©rence entre cette classe (view) et la classe viewer est qu'elle ne permet pas de rendre la scĂšne avec des appels run () ou frame (). Un scĂ©nario d'ajout de vue typique ressemble Ă  ceci

 osgViewer::CompositeViewer multiviewer; multiviewer.addView( view ); 

La visionneuse composite vous permet d'afficher une scĂšne sous diffĂ©rents angles, en affichant ces angles dans diffĂ©rentes fenĂȘtres. Il vous permet Ă©galement d'afficher des scĂšnes indĂ©pendantes dans diffĂ©rentes fenĂȘtres. Écrivons un exemple simple d'utilisation d'une visionneuse composite

Exemple composite
main.h

 #ifndef MAIN_H #define MAIN_H #include <osgDB/ReadFile> #include <osgViewer/CompositeViewer> #endif 

main.cpp

 #include "main.h" //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ osgViewer::View *createView(int x, int y, int w, int h, osg::Node *scene) { osg::ref_ptr<osgViewer::View> view = new osgViewer::View; view->setSceneData(scene); view->setUpViewInWindow(x, y, w, h); return view.release(); } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ int main(int argc, char *argv[]) { (void) argc; (void) argv; osg::ref_ptr<osg::Node> model1 = osgDB::readNodeFile("../data/cessna.osg"); osg::ref_ptr<osg::Node> model2 = osgDB::readNodeFile("../data/cow.osg"); osg::ref_ptr<osg::Node> model3 = osgDB::readNodeFile("../data/glider.osg"); osgViewer::View *view1 = createView(50, 50, 320, 240, model1); osgViewer::View *view2 = createView(380, 50, 320, 240, model2); osgViewer::View *view3 = createView(185, 330, 320, 240, model3); osgViewer::CompositeViewer viewer; viewer.addView(view1); viewer.addView(view2); viewer.addView(view3); return viewer.run(); } 


Nous allons placer la crĂ©ation d'une vue sĂ©parĂ©e dans une fonction qui prend comme paramĂštres la position et la taille de la fenĂȘtre, ainsi que la scĂšne comme pointeur vers son nƓud racine

 osgViewer::View *createView(int x, int y, int w, int h, osg::Node *scene) { osg::ref_ptr<osgViewer::View> view = new osgViewer::View; view->setSceneData(scene); view->setUpViewInWindow(x, y, w, h); return view.release(); } 

Ici, nous créons une vue contrÎlée par un pointeur intelligent vers un objet osgViewer :: View

 osg::ref_ptr<osgViewer::View> view = new osgViewer::View; 

dĂ©finir les donnĂ©es de la scĂšne affichĂ©e et le mode d'affichage de la fenĂȘtre dans la fenĂȘtre avec la position et la taille spĂ©cifiĂ©es

 view->setSceneData(scene); view->setUpViewInWindow(x, y, w, h); 

Nous retournons la vue de la fonction selon les rĂšgles de retour des pointeurs intelligents

 return view.release(); 

Maintenant, dans le programme principal, nous chargeons trois modÚles différents

 osgViewer::View *view1 = createView(50, 50, 320, 240, model1); osgViewer::View *view2 = createView(380, 50, 320, 240, model2); osgViewer::View *view3 = createView(185, 330, 320, 240, model3); 

créer trois types différents

 osgViewer::View *view1 = createView(50, 50, 320, 240, model1); osgViewer::View *view2 = createView(380, 50, 320, 240, model2); osgViewer::View *view3 = createView(185, 330, 320, 240, model3); 

créer une visionneuse composite et y ajouter des vues précédemment créées

 osgViewer::CompositeViewer viewer; viewer.addView(view1); viewer.addView(view2); viewer.addView(view3); 

et exĂ©cutez le rendu exactement de la mĂȘme maniĂšre que dans le cas d'une scĂšne

 return viewer.run(); 

C’est tout! Lorsque le programme dĂ©marre, nous obtenons trois fenĂȘtres diffĂ©rentes. Le contenu de chaque fenĂȘtre peut ĂȘtre contrĂŽlĂ© indĂ©pendamment. Chacune des fenĂȘtres peut ĂȘtre fermĂ©e de la maniĂšre standard et quitter complĂštement l'application en appuyant sur Echap.



3. La classe osg :: GraphicsContext :: Traits


Le mot «traits» dans la traduction de l'anglais signifie «caractĂ©ristiques». Ainsi, la classe susmentionnĂ©e dĂ©crit les fonctionnalitĂ©s de la future fenĂȘtre et contient toutes les propriĂ©tĂ©s pour dĂ©crire le contexte graphique. Elle diffĂšre de la classe osg :: DisplaySettings, qui contrĂŽle les caractĂ©ristiques de tous les contextes graphiques pour les camĂ©ras nouvellement créées. Les principales propriĂ©tĂ©s publiques de cette classe sont rĂ©pertoriĂ©es dans le tableau ci-dessous.

Attribut de classeTapezValeur par défautLa description
xint0La position horizontale initiale de la fenĂȘtre
yint0La position verticale initiale de la fenĂȘtre
largeurint0Largeur de fenĂȘtre
hauteurint0Hauteur fenĂȘtre
windowNamestd :: string""Titre de la fenĂȘtre
fenĂȘtreDĂ©corationboolfauxDrapeau d'affichage du titre de la fenĂȘtre
rougeentier non signé8Le nombre de bits de rouge dans le tampon de couleur OpenGL
vertentier non signé8Le nombre de bits de vert dans le tampon de couleur OpenGL
bleuentier non signé8Le nombre de bits de bleu dans le tampon de couleur OpenGL
alphaentier non signé8Le nombre de bits dans le tampon alpha OpenGL
profondeurentier non signé24Le nombre de bits dans le tampon de profondeur OpenGL
pochoirentier non signé0Le nombre de bits dans le tampon de gabarit OpenGL
doubleBufferboolfauxUtiliser un double tampon
échantillonsentier non signé0Numéro de lissage primitif
quadBufferStereoboolfauxUtiliser un tampon stéréo quad (pour les équipements NVidia)
inheritedWindowDataosg :: ref_ptrNullDescripteur de donnĂ©es associĂ© Ă  la fenĂȘtre

Pour initialiser l'objet Traits, exécutez le code suivant

 osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->x = 50; traits->y = 100; ... 

4. Configurer la fenĂȘtre d'application OSG


Pour crĂ©er une fenĂȘtre avec les caractĂ©ristiques spĂ©cifiĂ©es, vous devez effectuer les Ă©tapes suivantes:

  1. Configurer un objet de type osg :: GraphicsContext :: Traits
  2. CrĂ©er un contexte de fenĂȘtre graphique
  3. Liez ce contexte graphique à la caméra
  4. Faire de la caméra la visionneuse principale

Exemple de traits
main.h

 #ifndef MAIN_H #define MAIN_H #include <osg/GraphicsContext> #include <osgDB/ReadFile> #include <osgViewer/Viewer> #endif 

main.cpp

 #include "main.h" int main(int argc, char *argv[]) { (void) argc; (void) argv; osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->x = 50; traits->y = 50; traits->width = 800; traits->height = 600; traits->windowName = "OSG application"; traits->windowDecoration = true; traits->doubleBuffer = true; traits->samples = 4; osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get()); osg::ref_ptr<osg::Camera> camera = new osg::Camera; camera->setGraphicsContext(gc); camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); camera->setClearColor( osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f) ); double aspect = static_cast<double>(traits->width) / static_cast<double>(traits->height); camera->setProjectionMatrixAsPerspective(30.0, aspect, 1.0, 1000.0); camera->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON); osg::ref_ptr<osg::Node> root = osgDB::readNodeFile("../data/cessna.osg"); osgViewer::Viewer viewer; viewer.setCamera(camera.get()); viewer.setSceneData(root.get()); return viewer.run(); } 


Pour dĂ©finir les prĂ©fĂ©rences de fenĂȘtre, crĂ©ez une instance de la classe osg :: GraphicsContext :: Traits et initialisez-la avec les paramĂštres dont nous avons besoin

 osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->x = 50; traits->y = 50; traits->width = 800; traits->height = 600; traits->windowName = "OSG application"; traits->windowDecoration = true; traits->doubleBuffer = true; traits->samples = 4; 

AprÚs cela, nous créons un contexte graphique en passant un pointeur sur les traits comme paramÚtres

 osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get()); 

Créer une caméra

 osg::ref_ptr<osg::Camera> camera = new osg::Camera; 

Nous associons la caméra au contexte graphique créé

 camera->setGraphicsContext(gc); 

Configurer la fenĂȘtre, dĂ©finir le masque de nettoyage du tampon, dĂ©finir la couleur de nettoyage

 camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); camera->setClearColor( osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f) ); 

Configurer une matrice de projection en perspective

 double aspect = static_cast<double>(traits->width) / static_cast<double>(traits->height); camera->setProjectionMatrixAsPerspective(30.0, aspect, 1.0, 1000.0); 

N'oubliez pas d'activer le test de profondeur, pour l'affichage correct des visages

 camera->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON); 

Chargement du modĂšle d'avion

 osg::ref_ptr<osg::Node> root = osgDB::readNodeFile("../data/cessna.osg"); 

Nous configurons et lançons la visionneuse, indiquant la caméra que nous avons configurée dans la qualité de la caméra principale

 osgViewer::Viewer viewer; viewer.setCamera(camera.get()); viewer.setSceneData(root.get()); return viewer.run(); 

A la sortie, nous avons une fenĂȘtre avec les paramĂštres requis



Le titre de la fenĂȘtre ne s'affiche pas car cette fonction est dĂ©sactivĂ©e dans les paramĂštres de mon gestionnaire de fenĂȘtres. Si vous exĂ©cutez l'exemple sur Windows ou Linux avec des paramĂštres diffĂ©rents, l'en-tĂȘte sera Ă  sa place.

À suivre ...

Source: https://habr.com/ru/post/fr437764/


All Articles