studio para mentor herramientas desarrollo crear con colección avanzado aula aplicaciones c++ macos opengl glut

c++ - para - herramientas de android studio pdf



Limpiar al salir de una aplicación OpenGL (5)

Me enamoré de esto de vez en cuando, tratando de jugar con GLUT. Intenté todo lo que pude hacer, incluyendo IIRC saliendo de glutMainLoop través de una excepción atrapada en la función principal pero ...

Cuando se usa glutMainLoop

Mi solución fue la siguiente: crear un objeto Context global, que será el propietario de todos sus recursos, y liberar esos recursos en el destructor.

Se llamará a este destructor de objeto de Context global inmediatamente después de salir de la principal.

Es importante El Context es una variable global, y no una variable declarada en la función principal, porque por un motivo que aún se me escapa (aún no veo el interés de esta opción de implementación), glutMainLoop no volverá.

En mi cuadro Linux (Ubuntu), el destructor se llama correctamente. Supongo que debería funcionar de la misma manera en Windows y MacOS, también.

Tenga en cuenta que esta es la versión C ++ de la solución atexit() de Francisco Soto, sin las posibles limitaciones.

Usando glutMainLoopEvent

Aparentemente, algunas implementaciones tienen un glutMainLoopEvent que se puede usar en lugar de llamar a glutMainLoop.

http://openglut.sourceforge.net/group__mainloop.html#ga1

glutMainLoopEvent solo resolverá los eventos pendientes y luego regresará. Por lo tanto, debe proporcionar el bucle de evento (el constructo for(;;) ) alrededor de la llamada a glutMainLoopEvent , pero de esta manera, puede trabajar con un GLUT y seguir teniendo control sobre el bucle de evento, y liberar sus recursos cuando sea necesario.

Tengo una aplicación OSX OpenGL que estoy tratando de modificar. Cuando creo la aplicación se invocan un montón de funciones de inicialización, incluidos los métodos en los que puedo especificar mis propios manejadores de mouse y teclado, etc. Por ejemplo:

glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100, 100); glutInitWindowSize(700, 700); glutCreateWindow("Map Abstraction"); glutReshapeFunc(resizeWindow); glutDisplayFunc(renderScene); glutIdleFunc(renderScene); glutMouseFunc(mousePressedButton); glutMotionFunc(mouseMovedButton); glutKeyboardFunc(keyPressed);

En algún momento paso el control a glutMainLoop y se ejecuta mi aplicación. En el proceso de ejecución creo un montón de objetos. Me gustaría limpiar esto. ¿Hay alguna manera en que pueda decirle a GLUT que llame a un método de limpieza antes de que se cierre?


Por lo general, no es necesario que hagas esto; el solo hecho de salir de la aplicación eliminará todos los recursos que haya asignado. Incluso si capturó la pantalla, debería volver a la normalidad.


Si está utilizando C / C ++ quizás pueda usar una llamada atexit () ?


En freeglut si llamas esto:

glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION)

Antes de ingresar al ciclo principal, cuando la ventana se cierra, la función de ciclo principal regresará y podrá realizar la limpieza.

Vale la pena señalar que en esa etapa el contexto GL ya ha sido destruido por lo que no puede realizar ninguna operación GL.


Terminé usando la respuesta de paercebal anterior, junto con su intento anterior de usar un bloque try / catch alrededor de glutMainLoop () también. ¿Por qué? Porque quería limpiar correctamente, sin importar cómo se cerró. El objeto Contexto global se destruirá correctamente si la aplicación sale limpiamente, que es lo que sucede si cierra la aplicación al cerrar la ventana (o salir de la aplicación en OS X). Pero si presionas ctrl-C en la terminal donde se lanzó (o le envías un SIGINT), la limpieza no ocurre. Para manejar esto, agregué lo siguiente a mi código:

static bool exitFlag = false; static void sighandler(int sig) { exitFlag = true; } static void idleFunc() { if(exitFlag) { throw NULL; } }

Y luego en main ():

signal(SIGINT, sighandler); glutIdleFunc(idleFunc); try { glutMainLoop(); } catch(...) {}

Este no es el código más bonito de código, pero maneja ambos casos de salir del programa correctamente.

Una trampa (sin juego de palabras): cualquier código que coloques después del bloque catch () no se ejecutará si cierras la ventana / salgas de la aplicación normalmente. Debe colocar su código de limpieza en el objeto Contexto global como se muestra en la respuesta de paercebal. Todo lo que este código está haciendo es permitir que la señal SIGINT se use para salir del glutMainLoop ().

Creo que la verdadera lección aquí es que para algo realmente complejo, GLUT simplemente no va a cortarlo.