OpenSceneGraph: Verwalten von Windows- und Anzeigemodi

Bild

Einführung


Wir haben bereits gesagt, dass die Klasse osg :: Camera den zugehörigen OpenGL-Grafikkontext verwaltet. Der Grafikkontext enthält Informationen darüber, wie und wo Objekte gezeichnet werden und welche Statusattribute auf sie angewendet werden. Unter Kontext wird ein Grafikfenster bzw. ein Client-Bereich oder ein OpenGL-Pixelpuffer verstanden, in dem Pixeldaten gespeichert werden, ohne sie in den Bildspeicher zu übertragen.

OSG verwendet die Klasse osg :: GraphicsContext, um einen abstrakten Grafikkontext darzustellen, und die Klasse osg :: GraphicsWindow, um ein abstraktes Grafikfenster darzustellen. Letzteres verfügt über eine getEventQueue () -Methode zum Verwalten von Ereignissen aus GUI-Elementen. Im Allgemeinen ist ein grafischer Kontext ein plattformspezifisches Konzept, sodass OSG den größten Teil der Arbeit zum Erstellen eines Fensters und zum Verknüpfen seines Kontexts mit dem OpenGL-Kontext übernimmt. Wenn Sie die Methode createGraphicsContext () der Klasse osg :: GraphicsContext () aufrufen, wird der erforderliche Code (und es gibt viele davon, glauben Sie mir!) Abhängig von der Plattform automatisch vom Präprozessor generiert. Alles, was wir tun müssen, ist ein Argument an diese Methode vom Typ osg :: GraphicsContex :: Traits zu übergeben, die eine Beschreibung des Fensters enthält, das wir erhalten möchten.

1. Die osg-Klasse :: DisplaySettings


Mit OSG kann der Entwickler globale Anzeigeeinstellungen verwalten, auf deren Grundlage Kameras, Betrachter und Szenenelemente gerendert werden. Hierzu wird das Singleton-Muster verwendet, dh ein eindeutiges Objekt, das diese Einstellungen enthält und in Form der Klasse osg :: DisplaySettings implementiert ist, auf die von überall im Programm zugegriffen werden kann. Daher können wir diese Einstellungen in unserer Anwendung jederzeit ändern.

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

Singleton osg :: DisplaySettings enthält die Einstellungen, die für neu erstellte Rendergeräte gelten, den OpenGL-Kontext des Grafikfensters. Sie können die folgenden Parameter variieren:

  1. setDoubleBuffer () - Aktiviert / deaktiviert die doppelte Pufferung. Standardmäßig aktiviert.
  2. setDepthBuffer () - Tiefenpuffer aktivieren / deaktivieren. Standardmäßig aktiviert.
  3. Stellen Sie die Breite des Alpha-Puffers, des Schablonenpuffers und des Akkumulationspuffers mit Methoden wie setMinimumNumAlphaBits () ein. Standardmäßig sind alle Parameter 0.
  4. Berechtigung zur Verwendung von Anti-Aliasing und seiner Tiefe mit der Methode setNumMultiSamples (). Der Standardwert ist 0.
  5. Schalten Sie den Stereomodus ein. Standardmäßig deaktiviert.

Betrachten Sie die Verwendung dieses Singletons am Beispiel der Glättung

Osg Singleton Beispiel :: 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(); } 


Wesentlich ist hier nur eine Herausforderung.

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

- Einstellen des Glättungsparameters, der je nach verwendetem Grafikgerät die Werte 2, 4 und 6 annehmen kann. Achten Sie darauf, wie die Cessna-Schraubenklinge aussieht, ohne sie zu glätten



und nach seiner Anwendung



2. Wechseln Sie in den Fenstermodus


Die osgViewer :: Viewer-Klasse kann sehr schnell neu konfiguriert werden, um im Fenstermodus angezeigt zu werden. Wie Sie bemerkt haben, wurden alle unsere vorherigen Beispiele im Vollbildmodus angezeigt. Um den Viewer in den Fenstermodus zu schalten, gibt es eine setUpViewInWindow () -Methode, die die Koordinaten der oberen linken Ecke des Fensters, ihre Breite und Höhe in Pixel als Parameter verwendet

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

Optional akzeptiert diese Methode den fünften Parameter - die Nummer des Bildschirms, auf dem das Fenster angezeigt werden soll, falls Sie mehr als einen Monitor haben. Bei der Arbeit mit mehreren Monitoren in Windows haben Sie festgestellt, dass sich die Szene im Vollbildmodus auf alle Monitore ausbreitet (dies wird unter Linux nicht beobachtet).

Außerdem können Sie in den Projekteinstellungen auf diese Weise die Umgebungsvariable OSG_WINDOW festlegen



Dies entspricht dem Aufruf von setUpViewInWindow (), der in diesem Fall möglicherweise nicht ausgeführt wird.



Um den Bildschirm, auf dem der Viewer im Vollbildmodus angezeigt werden soll, explizit anzugeben, können Sie die Methode setUpViewOnSingleScreen () verwenden, indem Sie die Bildschirmnummer als Parameter angeben (Standard 0).

OSG unterstützt auch sphärische Demo-Displays. Sie können die Methode setUpViewFor3DSphericalDisplay () verwenden, um die Anzeige auf einer solchen Anzeige anzupassen.

3. Composite Viewer


Die Klasse osgViewer :: Viewer steuert eine einzelne Ansicht, in der ein einzelnes Szenendiagramm angezeigt wird. Darüber hinaus gibt es eine Klasse osgViewer :: CompositeViewer, die mehrere Ansichten und mehrere Szenen unterstützt. Es verfügt über dieselben Methoden run (), frame () und done () zur Steuerung des Renderprozesses, ermöglicht jedoch das Hinzufügen und Entfernen unabhängiger Ansichten mithilfe der Methoden addView () und removeView () sowie das Abrufen von Ansichten anhand ihres Index mithilfe der Methode getView (). Das Ansichtsobjekt wird von der Klasse osgViewer :: View beschrieben.

Die Klasse osgViewer :: View ist die Basisklasse für die Klasse osgViewer :: Viewer. Sie können einen Stammknoten mit Szenendaten, einen Kameramanipulator und Ereignishandler hinzufügen. Der Hauptunterschied zwischen dieser Klasse (Ansicht) und der Viewer-Klasse besteht darin, dass das Rendern der Szene mit run () - oder frame () -Aufrufen nicht möglich ist. Ein typisches Szenario zum Hinzufügen von Ansichten sieht folgendermaßen aus

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

Mit Composite Viewer können Sie eine Szene in verschiedenen Winkeln anzeigen und diese Winkel in verschiedenen Fenstern anzeigen. Außerdem können Sie unabhängige Szenen in verschiedenen Fenstern anzeigen. Schreiben wir ein einfaches Beispiel für die Verwendung eines zusammengesetzten Viewers

Zusammengesetztes Beispiel
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(); } 


Wir werden die Erstellung einer separaten Ansicht in eine Funktion einfügen, die die Position und Größe des Fensters sowie die Szene als Zeiger auf ihren Wurzelknoten als Parameter verwendet

 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(); } 

Hier erstellen wir eine Ansicht, die von einem intelligenten Zeiger auf ein osgViewer :: View-Objekt gesteuert wird

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

Stellen Sie die Daten der angezeigten Szene und den Fensteranzeigemodus im Fenster mit der angegebenen Position und Größe ein

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

Wir geben die Ansicht von der Funktion gemäß den Regeln für die Rückgabe von intelligenten Zeigern zurück

 return view.release(); 

Jetzt laden wir im Hauptprogramm drei verschiedene Modelle

 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); 

Erstellen Sie drei verschiedene Typen

 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); 

Erstellen Sie einen zusammengesetzten Viewer und fügen Sie zuvor erstellte Ansichten hinzu

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

und führen Sie das Rendering genauso aus wie bei einer Szene

 return viewer.run(); 

Das ist alles! Wenn das Programm startet, erhalten wir drei verschiedene Fenster. Der Inhalt jedes Fensters kann unabhängig gesteuert werden. Jedes der Fenster kann wie gewohnt geschlossen werden und die Anwendung durch Drücken von Esc vollständig beenden.



3. Die Klasse osg :: GraphicsContext :: Traits


Das Wort "Merkmale" in der Übersetzung aus dem Englischen bedeutet "Merkmale". Die oben genannte Klasse beschreibt also die Funktionen des zukünftigen Fensters und enthält alle Eigenschaften zur Beschreibung des grafischen Kontexts. Es unterscheidet sich von der Klasse osg :: DisplaySettings, die die Eigenschaften aller Grafikkontexte für neu erstellte Kameras steuert. Die wichtigsten öffentlichen Eigenschaften dieser Klasse sind in der folgenden Tabelle aufgeführt.

KlassenattributTypStandardwertBeschreibung
xint0Die anfängliche horizontale Position des Fensters
yint0Die anfängliche vertikale Position des Fensters
Breiteint0Fensterbreite
Höheint0Fensterhöhe
Fensternamestd :: string""Fenstertitel
FensterdekorationBoolfalschFenstertitel-Anzeigeflag
rotunsigned int8Die Anzahl der roten Bits im OpenGL-Farbpuffer
grünunsigned int8Die Anzahl der grünen Bits im OpenGL-Farbpuffer
blauunsigned int8Die Anzahl der blauen Bits im OpenGL-Farbpuffer
Alphaunsigned int8Die Anzahl der Bits im OpenGL-Alpha-Puffer
Tiefeunsigned int24Die Anzahl der Bits im OpenGL-Tiefenpuffer
Schabloneunsigned int0Die Anzahl der Bits im OpenGL-Schablonenpuffer
doubleBufferBoolfalschVerwenden Sie einen doppelten Puffer
Probenunsigned int0Primitive Glättungszahl
quadBufferStereoBoolfalschVerwenden Sie einen Quad-Stereopuffer (für NVidia-Geräte).
geerbte Windows-Datenosg :: ref_ptrNullFenster zugeordneter Datendeskriptor

Führen Sie den folgenden Code aus, um das Traits-Objekt zu initialisieren

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

4. Richten Sie das OSG-Anwendungsfenster ein


Um ein Fenster mit den angegebenen Merkmalen zu erstellen, müssen Sie die folgenden Schritte ausführen:

  1. Konfigurieren Sie ein Objekt vom Typ osg :: GraphicsContext :: Traits
  2. Erstellen Sie einen grafischen Fensterkontext
  3. Verknüpfen Sie diesen Grafikkontext mit der Kamera
  4. Machen Sie die Kamera zum Hauptbetrachter

Beispiel für Eigenschaften
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(); } 


Erstellen Sie zum Festlegen der Fenstereinstellungen eine Instanz der Klasse osg :: GraphicsContext :: Traits und initialisieren Sie sie mit den erforderlichen Parametern

 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; 

Danach erstellen wir einen grafischen Kontext, indem wir einen Zeiger auf Merkmale als Einstellungen übergeben

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

Erstellen Sie eine Kamera

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

Wir verknüpfen die Kamera mit dem erstellten grafischen Kontext

 camera->setGraphicsContext(gc); 

Richten Sie das Ansichtsfenster ein, legen Sie die Pufferreinigungsmaske und die Reinigungsfarbe fest

 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) ); 

Richten Sie eine perspektivische Projektionsmatrix ein

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

Vergessen Sie nicht, den Tiefentest für die korrekte Anzeige von Gesichtern zu aktivieren

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

Laden des Flugzeugmodells

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

Wir konfigurieren und starten den Viewer und geben die Kamera an, die wir in der Qualität der Hauptkamera konfiguriert haben

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

Am Ausgang haben wir ein Fenster mit den erforderlichen Parametern



Der Fenstertitel wird nicht angezeigt, da diese Funktion in den Einstellungen meines Fenstermanagers deaktiviert ist. Wenn Sie das Beispiel unter Windows oder Linux mit unterschiedlichen Einstellungen ausführen, wird der Header an seiner Stelle platziert.

Fortsetzung folgt...

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


All Articles