I have a program that uses GLUT for its OpenGL rendering. Now I need it to be inside of a MFC project so that it can work with another program component.
I've followed this tutorial: http://www.codeguru.com/cpp/g-m/opengl/openfaq/article.php/c10975__1/Setting-Up-OpenGL-in-an-MFC-Control.htm
I am calling the function that was the GLUT display callback when the timer fires, but that's not working because the rendering depends on something that happens in the GLUT idle callback. I don't understand where I should call the GLUT idle callback in my MFC program. Is there a separate event handler I should make for it, and if so, which event? Or am I doing something else completely wrong? I'm fairly familiar with OpenGL but this is my first experience with MFC so I am probably erring on that side.
Thanks so much for your time; I really appreciate it!
I just browsed the tutorial you've linked to; on page two, something along the following lines can be found (I cleaned up the code a little bit):
void COpenGLControl::OnTimer(UINT nIDEvent)
{
if(nIDEvent==1)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
oglDrawScene();
// try to insert your idle function code here
SwapBuffers(hdc);
}
CWnd::OnTimer(nIDEvent);
}
So, basically this is the replacement for glutIdleFunc suggested by the tutorial. I'd simply try to insert the code called in your idle function before the call to SwapBuffers.
I hope that helps.
Related
I'm trying to build an application that can spawn a window on a separate thread. Let me explain a simple version. My main creates an object that has a window, let's call this object a menu. From the menu you can select what to do, for example open up an image to a new window. This whole object, or the object's "game loop" needs to be on a separate thread so that I can still keep interacting with the menu. I also need to interact with the image viewer.
My question is, what is the proper way of doing this?
I haven't really used threads a lot before. But from what I understand I need to detach the thread to create a daemon thread.
I tried to play around with the thread to create this but I kept getting these errors:
Failed to activate the window's context
Failed to activate OpenGL context: The requested resource is in use.
I'm not certain what causes this, all objects, like my windows are different instances. The application will still run fine even with these errors.
My application is quite big so here's an extremely simplified version of the code I've tried.
int main()
{
Menu menu; // this spawns a window
menu.run(); // let's say for simplicity this doesn't do anything else other than
// create a new window (the image viewer)
}
...
void caller(Image_view *img_view)
{
img_view->run();
}
void Menu::run()
{
Image_view *img_view = new Image_view(); // This creates the window
this->thread = new std::thread(caller, img_view);
this->thread->detach();
while (1); // This is here to keep the application running,
// in a real application this method would look different.
// This whole thread call would be in an event handler instead,
// but for this example I tried to make it as simple as possible
}
...
void Image_view::run()
{
while (running)
{
update(); // Event handler and whatever
render(); // Renders the image and whatever
}
this->window->close();
}
I mostly want to know if I'm using the thread correctly or not in an application like this. Also if you have any insight as to what the error message means, explaining it would be greatly appreciated. I should also mention that I'm using SFML for rendering and creating the window instance.
The tutorials I found about the threads are always something extremely simple which doesn't involve any window or anything that could for example cause that error message. So I figured someone smarter here might know the proper use of the thread in my case.
Thanks in advance!
I have learned about setting up separate rendering thread for Qt QGLWidget here ,here and here .
I also managed to get a kind of "working" setup: clearing color in the viewport.Seems to be ok.But I am getting the following warning:
QOpenGLContext::swapBuffers() called with non-exposed window, behavior
is undefined
I first create a widget that inherits from QGLWidget.Where I also setup OpenGL Format:
In the Widget constructor:
QGLFormat format;
format.setProfile(QGLFormat::CompatibilityProfile);
format.setVersion(4,3);
format.setDoubleBuffer(true);
format.setSwapInterval(1);
setFormat(format);
setAutoBufferSwap(false);
Then I init the rendering thread in the same Widget:
void GLThreadedWidget::initRenderThread(void){
doneCurrent();
context()->moveToThread(&m_renderThread);
m_renderThread.start();
}
and from that point the whole rendering is done inside that thread:
RenderThread constructor:
RenderThread::RenderThread(GLThreadedWidget *parent)
:QThread(),glWidget(parent)
{
doRendering = true;
}
RenderThread run() method:
void RenderThread::run(){
glWidget->makeCurrent();
GLenum err = glewInit();
if (GLEW_OK != err) {
printf("GLEW error: %s\n", glewGetErrorString(err));
} else {
printf("Glew loaded; using version %s\n", glewGetString(GLEW_VERSION));
}
glInit();
while (doRendering){
glWidget->makeCurrent();
glClear(GL_COLOR_BUFFER_BIT );
paintGL(); // render actual frame
glWidget->swapBuffers();
glWidget->doneCurrent();
msleep(16);
}
}
Anyone can point out where is the issue?And if that message can be discarded? Also a straightforward and concise explanation on render thread setup in Qt would be extremely helpful.Using Qt 5.2 (Desktop OpenGL build)
With what you've shown, it looks like that message handler warning you were getting was because you started triggering buffer swaps "too soon" in the window setup sequence, either directly through QGLContext::/QOpenGLContext::swapBuffers() or indirectly through a number of possible ways, none of which are really detectable outside of manual debugging. What I mean by too soon is before the widget's parent window was marked "exposed" (before it was being displayed by the windowing system).
As far as whether the message can be discarded, it can...but it's not safe to do, as in it's possible to get undefined behavior for the 1st few frames or so where you do it and the window's not ready (especially if you're immediately resizing to different extents at startup than your .ui file specifies). Qt documentation says that before your window's exposed, Qt has to basically tell OpenGL to paint according to what are effectively non-trustworthy extents. I'm not sure that's all that can happen though personally.
With the code you showed, there's an easy fix--avoid even starting your render logic until your window says it's exposed. Detecting exposure using QGLWidget isn't obvious though. Here's an example roughly like what I use, assuming your subclass from QGLWidget was something like 'OGLRocksWidget', it was a child of a central widget, and that central widget was a child of your implementation of QMainWindow (so that your widget would have to call parentWidget()->parentWidget() to get at its QMainWindow):
OGLRocksWidget::paintGL()
{
QMainWindow *window_ptr =
dynamic_cast<QMainWindow *>(parentWidget() ? parentWidget()->parentWidget() : 0);
QWindow *qwindow_ptr = (window_ptr ? window_ptr->windowHandle() : 0);
if (qwindow_ptr && qwindow_ptr->isExposed())
{
// don't start rendering until you can get in here, just return...
// probably even better to make sure QGLWidget::isVisible() too
}
}
Of course you don't have to do this in your implementation of QGLWidget::paintGL(), but in your particular setup you're better off not even starting your render thread until your window tells you it's exposed.
It looks like you have might have slightly bigger problems than that though. You weren't hooking the right GL activity into the right places in your code vs QGLWidget's intent. I feel for the position you were in because the documentation on this is a little spotty and scattered. For that part, QGLWidget's detailed description down where it says "Here is a rough outline of how a QGLWidget subclass might look" is a good place to start getting the idea. You'll want to override any of the key virtuals in there that you have related code for and move them into those calls.
So for example, your widget's constructor is doing setup work that is probably safer to put in an initializeGL() override, since QGLWidget's intent is to signal you when it's safely time to do that through that call. What I mean by safer whenever I say that here is that you won't get seemingly random debug exceptions (that in release builds can silently wreak havok on your runtime stability).
Side advice: install Qt source, point your debugger at it, and watch your code run, including into Qt. Your setFormat() call, last time I watched it, actually deletes the current underlying QOpenGLContext. That's probably good to know because you'll want to create a new one soon after or at least test out your options.
The risk of instability is why I'm trying to put together at least some kind of answer here a year later. I just learned this through a lot (too much) debugging. I love what the Qt team's done with it, but Qt will be much better off when they finish migrating everything over to QOpenGL* calls (or wherever they see a final proper place for their OpenGL support including permanent considerations for it and windowing support together).
A QOpenglWidget comes with its own context. If you want a background thread to do the rendering, you have to pass a shared context to the thread and do a few steps correct.
Details in: https://stackoverflow.com/a/50368372/3082081
I'm using glutMouseFunc(mouseFunction); as a callback however I keep getting the Access violation reading location 0x000000b0 at this line glutMouseFunc(mouseFunction);
I'm not using any of the glutInit functions because they interfere with the program and they are not essential anyways.
Does anyone know why I'm getting this error when at this callback?
Here is my initialize function:
int Initialize()
{
/* Bunch of code here that is irrelevant to the problem.......*/
glutMouseFunc(mouseFunction); // Error occurs here.
}
And here is my mouseFunction:
void mouseFunction(int button, int state, int x, int y){
if(button==GLUT_MIDDLE_BUTTON && state==GLUT_DOWN)
{
printf("Pressed middle mouse button!");
}
}
I've noticed one thing though, there error does not occur when I call the mouseFunction() as a normal function call in my Initialize method however once I try to use the mouseFunction with glutMouseFunc(mouseFunction), than the error happens so I believe this is more of an error with glutMouseFunc.
I'm not using any of the glutInit functions because they interfere with the program and they are not essential anyways.
This is your problem. If you're going to use GLUT, use it correctly.
The glutInit() function is essential - part of what it does is initializing internal state within GLUT. As you've discovered, with this state not properly initialized, other parts of GLUT (such as mouse event handling!) may not work properly.
Given your comments to the other questions your problem is simply, that you call glutMouseFunc without a GLUT window. Trying to register GLUT event callbacks without proper initialization or without a GLUT window created will crash your program.
You also say "GLUT interferes" with your actual window. So why would you try to register a GLUT callback at all if you don't have a window that could actually receive the events for GLUT to dispatch?
You should use the mouse event handling of the window you've already got. And what are you using GLUT for then anyway? The whole purpose of GLUT is to create a window for you and do event management. If you don't use GLUT for that, then don't use GLUT at all.
If it's for the teapot, well, you can have that without GLUT as well.
I know that in order to write a GTK application, I write a bunch of code which describes what is put in the main window, then I call:
gtk_main();
Any code statements after this do not get executed.
Now let's suppose I'd like my GTK app to display something I wrote with glut, which itself contains a bunch of statements about what graphics need to be set etc. then ends with the statement:
glutMainLoop();
Anything after this is not executed.
So my problem is that either of these two statements prevents me from calling the other.
Is there a way to execute a glut main loop inside a GTK widget ?
Is there a way to write a code that could somehow simultaneously call both a GTK main loop and a glut main loop (but called from the main program and rendered in a separate X window, not within a widget)? I've got a feeling this could be done with "threads"...
You don't. There's generally no point to it.
GLUT is a library for creating and managing OpenGL windows. GTK already has an OpenGL window in it. If you're using GTK, then there's no point in using GLUT. It's like having two vector math libraries or something.
You are running the main loops. gtk_main() runs until gtk_quit() is called.
gtk_main() at GTK.org
Runs the main loop until gtk_main_quit() is called. You can nest calls to gtk_main(). In that case gtk_main_quit() will make the innermost invocation of the main loop return.
Also, glutMainLoop() works the same way, it processes GL events forever.
glutMainLoop() at OpenGL.org
glutMainLoop() enters the GLUT event processing loop. This routine should be called at most once in a GLUT program. Once called, this routine will never return. It will call as necessary any callbacks that have been registered.
So, you you wan't both of these things to execute at the same time (I think they might interfere with each other so you might get unexpected results) then you will need to call gtk_main_iteration() from inside glut.
gtk_main_iteration() at GTK.org
Runs a single iteration of the mainloop. If no events are waiting to be processed GTK+ will block until the next event is noticed. If you don't want to block look at gtk_main_iteration_do() or check if any events are pending with gtk_events_pending() first.
Now.. GLUT doesn't have an equivalent to gtk_main_iteration() so you are going to need to register GLUT callbacks.
You could register a callback with GLUT that runs gtk_main_iteration() using glutIdleFunc(void (*func)(void)) which will run a callback for every frame - glutIdleFunc()..
Or you could give a callback to glutTimerFunc(unsigned int msecs,
void (*func)(int value), value) to call and check the return value of gtk_main_iteration() every 200msec or so.
I'd probably experiment with both, glutIdleFunc() might not always get called regularly enough for good responsiveness.
It really is worth looking at driving GTK's GL support though.
My program takes a few seconds to start up. I am using clutter for the GUI, and I decided to try and make something pop up to indicate that the program is starting up. I wanted to just have a logo pop up and rotate, then disappear when the program starts.
So in clutter, I figured I could just make a new stage (window) add an actor to it, make the and actor spin, in the first section of the main function. The window will pop up right away, but with no content, but the content wont show until you launch the clutter main loop.
So I was just wondering how I might be able to achieve this using clutter or GTK+.
If you are familar with reaper 4, the audio recording program, this program does something similar to what I want to mine to do.
What you want is called a splash screen. I'm unfamiliar with clutter, but I found this GTK splash screen example.
However, I think you're taking the problem the wrong way. Splash screens are a bad idea because you just add overhead. What you need is improving your startup performance, by doing some CPU and/or IO profiling. Loading stuff on-demand, and not all at once will help.
Unfortunately I'm unfamiliar with Clutter. But I'm pretty sure it will be difficult to render an animation without a main loop running in any high level library.
I'd try to put the code that causes the delay into a separate thread and inform the main loop when the startup is done.
Something like this is what i use:
string splashfile = path_templ + "/splashimg.png";
GtkWidget *image=gtk_image_new_from_file(splashfile.c_str());
gtk_container_add(GTK_CONTAINER(SplashWindow), image);
gtk_widget_show_all(SplashWindow);
//Cycle through all iterations (refresh everything in the GUI)
while (gtk_events_pending()){
gtk_main_iteration();
}
sleep(1);
(... rest of code ...)
gtk_main ();
gdk_threads_leave ();
Especially that last part of while events pending is the key