OpenSceneGraph: Gestión de Windows y modos de visualización

imagen

Introduccion


Ya hemos dicho que la clase osg :: Camera gestiona el contexto gráfico OpenGL asociado. El contexto gráfico encapsula información sobre cómo y dónde se dibujan los objetos y qué atributos de estado se les aplican. El contexto se entiende como una ventana gráfica, o más bien su área de cliente, o el búfer de píxeles de OpenGL, que almacena datos de píxeles sin transferirlos al búfer de cuadros.

OSG utiliza la clase osg :: GraphicsContext para representar un contexto gráfico abstracto y la clase osg :: GraphicsWindow para representar una ventana gráfica abstracta. Este último tiene un método getEventQueue () para administrar eventos desde elementos de la GUI. En términos generales, un contexto gráfico es un concepto específico de la plataforma, por lo que OSG se encarga de la mayor parte del trabajo de crear una ventana y asociar su contexto con el contexto OpenGL. Cuando se llama al método createGraphicsContext () de la clase osg :: GraphicsContext (), el preprocesador generará automáticamente el código requerido (y hay muchos, ¡créanme!), Dependiendo de la plataforma. Todo lo que se requiere de nosotros es pasar a este método un argumento del tipo osg :: GraphicsContex :: Traits que contenga una descripción de la ventana que queremos recibir.

1. La clase osg :: DisplaySettings


OSG permite al desarrollador administrar la configuración de visualización global, en función de qué cámaras, visores y elementos de escena se representan. Para esto, se utiliza el patrón singleton, es decir, un objeto único que contiene esta configuración, implementado en forma de la clase osg :: DisplaySettings, a la que se puede acceder desde cualquier parte del programa. Por lo tanto, desde nuestra aplicación, podemos cambiar esta configuración en cualquier momento.

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

Singleton osg :: DisplaySettings contiene la configuración que se aplica a los dispositivos de renderizado recién creados, el contexto OpenGL de la ventana gráfica. Puede variar los siguientes parámetros:

  1. setDoubleBuffer () - habilita / deshabilita el doble buffering. Habilitado por defecto.
  2. setDepthBuffer () - activa / desactiva el búfer de profundidad. Habilitado por defecto.
  3. Establezca el ancho del búfer alfa, el búfer de la plantilla y el búfer de acumulación utilizando métodos como setMinimumNumAlphaBits (). Por defecto, todos los parámetros son 0.
  4. Permiso para usar anti-aliasing y su profundidad usando el método setNumMultiSamples (). El valor predeterminado es 0.
  5. Activa el modo estéreo. Desactivado por defecto.

Considere el uso de este singleton en el ejemplo de suavizado

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


Lo esencial aquí es solo un desafío.

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

- establecer el parámetro de suavizado, que puede tomar los valores 2, 4 y 6, dependiendo del dispositivo gráfico utilizado. Preste atención a cómo se ve la cuchilla de tornillo Cessna sin aplicar suavizado



y luego de su aplicación



2. Cambiar al modo ventana


La clase osgViewer :: Viewer se puede reconfigurar muy rápidamente para mostrar en modo de ventana. Como notó, todos nuestros ejemplos anteriores se mostraron en pantalla completa. Para cambiar el visor al modo de ventana, existe el método setUpViewInWindow (), que toma como parámetros las coordenadas de la esquina superior izquierda de la ventana, su ancho y alto en píxeles

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

Opcionalmente, este método acepta el quinto parámetro: el número de la pantalla en la que se debe mostrar la ventana, en caso de que tenga más de un monitor. Seguramente trabajando con múltiples monitores en Windows, observó que la escena se extiende a todos los monitores en modo de pantalla completa (esto no se observa en Linux).

Además, en la configuración del proyecto, puede establecer la variable de entorno OSG_WINDOW de esta manera



que será equivalente a llamar a setUpViewInWindow (), que en este caso no se puede ejecutar.



Para especificar explícitamente la pantalla en la que se debe mostrar el visor en modo de pantalla completa, puede usar el método setUpViewOnSingleScreen () especificando el número de pantalla como un parámetro (0 por defecto).

OSG también admite pantallas esféricas de demostración. Puede usar el método setUpViewFor3DSphericalDisplay () para personalizar la pantalla en dicha pantalla.

3. Visor compuesto


La clase osgViewer :: Viewer controla una vista única que muestra un solo gráfico de escena. Además de esto, hay una clase osgViewer :: CompositeViewer que admite varias vistas y varias escenas. Tiene los mismos métodos run (), frame () y done () para controlar el proceso de renderizado, pero le permite agregar y eliminar vistas independientes usando los métodos addView () y removeView (), así como obtener vistas por su índice usando el método getView () El objeto de vista es descrito por la clase osgViewer :: View.

La clase osgViewer :: View es la clase base para la clase osgViewer :: Viewer. Le permite agregar un nodo raíz con datos de escena, un manipulador de cámara y controladores de eventos. La principal diferencia entre esta clase (vista) y la clase de visor es que no permite renderizar la escena con llamadas run () o frame (). Un escenario típico para agregar vistas se ve así

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

El visor compuesto le permite mostrar una escena en diferentes ángulos, mostrando estos ángulos en diferentes ventanas. También le permite mostrar escenas independientes en diferentes ventanas. Escribamos un ejemplo simple de uso de un visor compuesto

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


Colocaremos la creación de una vista separada en una función que tome como parámetros la posición y el tamaño de la ventana, así como la escena como un puntero a su nodo raíz

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

Aquí creamos una vista controlada por un puntero inteligente a un objeto osgViewer :: View

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

establecer los datos de la escena mostrada y el modo de visualización de la ventana en la ventana con la posición y el tamaño especificados

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

Devolvemos la vista desde la función de acuerdo con las reglas para devolver punteros inteligentes

 return view.release(); 

Ahora en el programa principal cargamos tres modelos diferentes

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

crear tres tipos diferentes

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

crear un visor compuesto y agregarle vistas creadas previamente

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

y ejecuta el renderizado exactamente de la misma manera que lo hicimos en el caso de una escena

 return viewer.run(); 

Eso es todo! Cuando se inicia el programa, obtenemos tres ventanas diferentes. El contenido de cada ventana se puede controlar de forma independiente. Cualquiera de las ventanas se puede cerrar de la manera estándar y salir completamente de la aplicación presionando Esc.



3. La clase osg :: GraphicsContext :: Traits


La palabra "rasgos" en la traducción del inglés significa "características". Entonces, la clase mencionada anteriormente describe las características de la ventana futura y contiene todas las propiedades para describir el contexto gráfico. Se diferencia de la clase osg :: DisplaySettings, que controla las características de todos los contextos gráficos para cámaras recién creadas. Las principales propiedades públicas de esta clase se enumeran en la tabla a continuación.

Atributo de claseTipoValor por defectoDescripción
xint0 0La posición horizontal inicial de la ventana.
yint0 0La posición vertical inicial de la ventana.
anchoint0 0Ancho de la ventana
alturaint0 0Altura de la ventana
windowNamestd :: string""Título de la ventana
ventanaDecoraciónboolfalsoIndicador de visualización del título de la ventana
rojounsigned int8El número de bits de rojo en el búfer de color OpenGL
verdeunsigned int8El número de bits de verde en el búfer de color OpenGL
azulunsigned int8El número de bits de azul en el búfer de color OpenGL
alfaunsigned int8El número de bits en el búfer alfa OpenGL
profundidadunsigned int24El número de bits en el búfer de profundidad OpenGL
plantillaunsigned int0 0El número de bits en el búfer de galería de símbolos OpenGL
doubleBufferboolfalsoUsar doble tampón
muestrasunsigned int0 0Número de suavizado primitivo
quadBufferStereoboolfalsoUtilice un búfer estéreo cuádruple (para equipos NVidia)
inheritedWindowDataosg :: ref_ptrNuloDescriptor de datos asociado a la ventana

Para inicializar el objeto Traits, ejecute el siguiente código

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

4. Configure la ventana de la aplicación OSG


Para crear una ventana con las características especificadas, debe realizar los siguientes pasos:

  1. Configure un objeto de tipo osg :: GraphicsContext :: Traits
  2. Crear un contexto de ventana gráfica
  3. Enlace este contexto gráfico a la cámara
  4. Haz de la cámara el espectador principal

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


Para establecer las preferencias de la ventana, cree una instancia de la clase osg :: GraphicsContext :: Traits e inicialícela con los parámetros que necesitamos

 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; 

Después de eso, creamos un contexto gráfico pasando un puntero a los rasgos como la configuración

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

Crear una cámara

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

Asociamos la cámara con el contexto gráfico creado.

 camera->setGraphicsContext(gc); 

Configure la ventana gráfica, configure la máscara de limpieza del búfer, configure el color de limpieza

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

Configurar una matriz de proyección en perspectiva

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

No olvide habilitar la prueba de profundidad, para la correcta visualización de caras.

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

Cargando modelo de avión

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

Configuramos y lanzamos el visor, indicando la cámara que configuramos en la calidad de la cámara principal.

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

A la salida tenemos una ventana con los parámetros requeridos.



El título de la ventana no se muestra porque esta función está deshabilitada en la configuración de mi administrador de ventanas. Si ejecuta el ejemplo en Windows o Linux con configuraciones diferentes, el encabezado estará en su lugar.

Continuará ...

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


All Articles