2008-09-23 19 views
21

Estoy construyendo un motor y editor de simulación física en Windows. Quiero construir la parte del editor usando Qt y quiero ejecutar el motor usando SDL con OpenGL.¿Cómo uso Qt y SDL juntos?

Mi primera idea fue construir el editor usando solo Qt y compartir tanto código con el motor (el administrador de recursos, el procesador, las matemáticas). Pero también me gustaría poder ejecutar la simulación dentro del editor. Esto significa que también tengo que compartir el código de simulación que usa subprocesos SDL.

Entonces, mi pregunta es esta: ¿Hay alguna manera de tener un render OpenGL en una ventana de Qt usando SDL?

He leído en la web que es posible suministrarle a SDL un identificador de ventana en el que renderizar. Alguien tiene experiencia dong eso?

Además, la parte roscada del simulador puede ser un problema ya que utiliza hilos SDL.

+0

Se trata de un proyecto de código abierto que estoy empezando ahora mismo. Publicaré mi arquitectura/solución a medida que avance el proyecto. – bineteri

+0

Basado en la tarea que desea lograr, creo que puede ir directamente a Qt y volcar SDL por completo. Qt tiene una excelente compatibilidad con OpenGL, ofrece manejo de entrada, capacidades de interfaz de usuario mucho mejores (sin ofender, SDL) etc. El uso del widget OpenGL Qt es trivial y los modelos de subprocesamiento que ofrece el framework Qt también son muy fáciles de usar (tiene roscado estándar, concurrencia, etc. + el concepto de señal/ranura). Si el modelo de subprocesamiento no es de su agrado, puede usar algo como aumentar, por ejemplo. De cualquier manera, realmente no veo una razón para usar SDL + Qt en su escenario. – rbaleksandar

Respuesta

11

Si bien puede que funcione como la primera respuesta, es probable que tenga problemas debido al enhebrado. No hay soluciones simples cuando se trata de subprocesos, y aquí tendría SDL Qt y OpenGL mainloop interactuando. No es divertido.

La solución más fácil y más segura sería desacoplar ambas partes. Para que SDL y Qt se ejecuten en procesos separados y les pida que utilicen algún tipo de mensaje para comunicarse (recomendaría d-bus aquí). Puede hacer que SDL se convierta en una ventana sin bordes y su editor envía comandos a través de mensajes.

+0

Gracias, esta información es muy valiosa. Creo que tendré que separar el trabajo en 2 procesos. El mayor obstáculo proviene de compartir el "contexto" de OpenGL. Los widgets de Qt no funcionan bien con OpenGL/SDL. El enhebrado parece funcionar bien, ya que QT y SDL usan la misma biblioteca (pthreads, win32 hilos). – bineteri

3

Renderizar en opengl desde QT es trivial (y funciona muy bien) No hay experiencia directa de SDL, pero aquí hay una aplicación de ejemplo sobre cómo mezclarlas. http://www.devolution.com/pipermail/sdl/2003-January/051805.html

Hay un buen artículo sobre la mezcla de QT widgewts directamente con el OpenGL aquí http://doc.trolltech.com/qq/qq26-openglcanvas.html un poco más allá de lo que estrictamente necesario, sino más bien inteligente!

+0

OpenGL no es el problema aquí. Sé que funciona bien con Qt. El problema es principalmente el enhebrado. – bineteri

+0

Mi error, ¡pensé que SDL era la biblioteca de motores de física! –

18

Esto es una simplificación de lo que hago en mi proyecto. Se puede utilizar como un widget de ordinario, pero como sea necesario, se puede usar se m_Screen objeto señalar a la superficie SDL y va a mostrar en el widget :)

#include "SDL.h" 
#include <QWidget> 

class SDLVideo : public QWidget { 
    Q_OBJECT 

public: 
    SDLVideo(QWidget *parent = 0, Qt::WindowFlags f = 0) : QWidget(parent, f), m_Screen(0){ 
     setAttribute(Qt::WA_PaintOnScreen); 
     setUpdatesEnabled(false); 

     // Set the new video mode with the new window size 
     char variable[64]; 
     snprintf(variable, sizeof(variable), "SDL_WINDOWID=0x%lx", winId()); 
     putenv(variable); 

     SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE); 

     // initialize default Video 
     if((SDL_Init(SDL_INIT_VIDEO) == -1)) { 
      std:cerr << "Could not initialize SDL: " << SDL_GetError() << std::endl; 
     } 

     m_Screen = SDL_SetVideoMode(640, 480, 8, SDL_HWSURFACE | SDL_DOUBLEBUF); 
     if (m_Screen == 0) { 
      std::cerr << "Couldn't set video mode: " << SDL_GetError() << std::endl; 
     } 
    } 

    virtual ~SDLVideo() { 
     if(SDL_WasInit(SDL_INIT_VIDEO) != 0) { 
      SDL_QuitSubSystem(SDL_INIT_VIDEO); 
      m_Screen = 0; 
     } 
    } 
private: 
    SDL_Surface *m_Screen; 
}; 

espero que esto ayude

Nota: Por lo general, tiene sentido establecer el tamaño mínimo y máximo de este widget en el tamaño de superficie SDL.

+0

¿El ID de la ventana hackea el trabajo en Mac? No parece funcionar en OSX. He intentado tanto putenv como SDL_putenv sin suerte. –

+0

Sé que esto es muy tarde, pero ¿alguien podría explicarme cómo me funciona? – Whyrusleeping