I'm having problems running my opengl 4 program. When the window is in focus, nothing appears to happen (even alt+f4 doesn't register until the window is out of focus).
If the window containing my program is in focus, then the main loop for my program stops executing (I checked using printf statements, within my while(true) loop, and the output stops completely when focused on the window). When the window is not focused, the program runs as expected (including mouse movements inside the window changing the camera direction).
I've narrowed it down to this line of code, which is executed within my mouse callback method
glfwSetCursorPos ( window, middleX, middleY);
If this is commented out, the program runs fine when in focus, but the mouse is no longer centred, so the camera logic no longer works.
I'm using 32 bit versions of glfw3 and glew.
This program has worked on other machines in the past. Is there any way to fix this without restructuring the code to poll the mouse input?
If you execute glfwSetCursorPos() inside your mouse callback, you can get to the situation that this creates a new mouse event, and after your callback exited, glfwPollEvents() will loop over the remaining events, so you effectively enter some endless loop here. You should just delay such actions after the input callbacks have been handled.
However, even with that approach, you will generate a new event for each frame, so that I suggest dropping the callback overhead alltogether and just quering the mouse position with glfwGetCursorPos() directly every frame.
Related
I have a problem handling GLFW poll events. As far as I know, all user input events are handled via callbacks or via constantly checking keyboard / mouse states. The latter is not so efficient an can even result in missing some input (e. g. when button pressed and then released between checking state). What is more, some events like window resizing cannot be handled without callbacks.
So, the problem is that whenever user starts resizing window (presses mouse button but doesn't move mouse), the app seems to freeze. This is, assuming resize callback is enabled and defined validly (even when copied right from GLFW API). And the problem is not that window doesn't redraw. Redraw on callback can be done with creating and calling own render() function in callback function.
The actual problem is that even when I handle resize event properly and redraw on callback, there is still some lag. This lag is after mouse press on decorated window border and when mouse is not moving. Here's a demonstration (button click is highlighted green):
Sorry for messed up GIF. All callbacks listed in GLFW API are enabled and handled (window-, input-, joystick- and monitor-callbacks) and redraw is called in each one. It seems that I'm missing some of the callbacks or GLFW just works like that.
According to this answer, this can't be done without threading:
That only works when the user moves the mouse while holding - just holding left-click on the resize window part still stalls. To fix that, you need to render in a separate thread in addition to this. (No, you can't do that without threading. Sorry, this is how GLFW works, no one except them can change it.)
So, the questions are:
How can I fix this issue without threading? If I can't, I guess I can emulate resizing with different cursors shapes and resizing zones or smth like that...
If this is still impossible to solve in GLFW, do other GLFW alternatives have this issue?
Are there any problems with GLFW similar to this one?
GLFW is not at fault here. It's how the operating system handles certain user input events like mouse down on the decorator resize handles of a window or moving the whole window.
See this answer for a more elaborate detail: Win32: My Application freezes while the user resizes the window
GLFW uses the standard Windows PeekMessage -> TranslateMessage/DispatchMessage loop which you will find in any GUI Windows application. This will get invoked when you call glfwPollEvents() and it processes all Window event messages that the OS has accumulated so far for all windows in this process. After all messages so far have been processed, the call to glfwPollEvents() will return and will allow your own window/game loop to continue.
What happens is that once the user clicks down the window decoration's resize handles, effectively the call to glfwPollEvents() will block within the OS itself in order for the OS / window-manager to intercept the mouse and keyboard messages to do its window resizing/reshaping thing.
I'm afraid that even though Windows will inform the process about the start of a window resize or move action (after which the OS will have control of the window message processing) and GLFW already handling these events internally, right now GLFW will not notify the client application about this. It would be possible though for GLFW to provide an appropriate event callback to the application, so that the application can start a timer or thread only for as long as the window resize/move action happens (as is also mentioned in the linked other Stackoverflow answer).
So, the only thing that you can do in order to keep rendering while the user holds onto the resize handles or while the user moves the window around, is to render in a separate thread.
I am reading an introductory book code about SDL and there is sample code like this:
void Game::handleEvents()
{
SDL_Event event;
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
m_bRunning = false;
break;
default:
break;
}
}
}
I understand that this will look into the event queue and if there is anything, retrieve it and the run it to the switch statement. Before I added this code, the window was displayed but you cannot drag or drop, close, or resize the window. Now that I added this code, I can close the window which was what I expected. What I didn't expect was I am able to drag and drop the window.
I thought this would be a separate event that I would need to include in the switch statement in the future. Why did drag and drop also work? Its the SDL_PollEvent (because I commented the switch statement but left the 'if', I was still able to drag) but why is that? Also, why only drag and drop was automatically functional? Why not resize?
We do not need to handle all events, some SDL will take care of for us. Events related to the window properties will be taken care of automatically. In order to resize a window, you will have to add the flag SDL_WINDOW_RESIZABLE when creating the window. While SDL will take care of the actual resizing of the window, it might still require some event handling as the surface will have a different size to paint at, it will not automatically resize any images we try to draw in it.
While I have not found an answer in the documentation to why SDL_PollEvent behave as you describe above, or if this is behavior is intended, it works slightly different on different systems. At osx it is possible to move the window without the above function, but the X for closing will not be displayed. By adding the function again, the window can be moved, minimized and closed properly.
According to documentation, SDL_PollEvent is meant to do what you describe, look if there are any events and retrieve them.
Events are not happening right now, they have already occurred in the past, you are getting notifications that they did occur in the order they occured.
The frozen window is a side effect of an implementation detail, set appropriate flags to enable/disable window properties and functionality like resizing, fullscreen, etc.
SDL_PollEvent calls SDL_PumpEvents, removes the first event in the stack and copies it into the pointer given.
SDL_PumpEvents calls into the operating system's event processing API and transforms platform events into SDL_Events, pushing them onto the SDL event stack.
Now the reason windows are frozen on some platforms is that, that is how that platform event loop works, unless you "pump" its event loop it will be considered an unresponsive window and the window manager will want to kill it and its process.
Here is a part of SDL2 code
SDL main function
int main(int argc,char *argv[])
{
...
...
bool quit=false;
SDL_Event e;
while(!quit) ///First while (say)
{
while(SDL_PollEvent(&e)) ///Second while (say)
{
if(e.type==SDL_QUIT)
{
quit=true;
}
handleEvent(e) ;///Function for executing certain event
}
...
SDL_RenderPresent((SDL_Renderer)renderer);
}
}
My question is,what does this SDL_PollEvent() actually do ,and suppose an event occur does the execution goes out of the second while() and call the SDL_RenderPresent() or it waits for all the events to take poll and then SDL_RenderPresent() is called , i am totally confused ?
The above is a very common single thread event loop:
Basically the application is constantly inside the outer while loop. To get the smoothest user experience we try to keep this loop under 17ms (for a 60 frames a sec rate)
Every 'frame' starts by responding to all the events that are waiting in the queue (the inner while):
while(SDL_PollEvent(&e)) ///Second while (say)
{
if(e.type==SDL_QUIT)
{
quit=true;
}
handleEvent(e) ;///Function for executing certain event
}
Events are notifications from the operating system that something happened. It might be that the window is closing SDL_QUIT or that the mouse was moved.
You must respond to these events for the application to be responsive. Usually the response is to change the state of the application.
For example we might see a left-mouse is down event we might find what is "under" the mouse button and indicate that it is now selected. This is normally just finding the object and calling a function that will change its state. All that changes is the boolean value that indicates the object is now selected.
Maybe moving the mouse needs to change the point of view of the next frame so we will update the vector that stores the direction we are looking at. So we update the vector in memory.
You may have long stretches where the event queue is empty and the application does not have any events to handle. And there might be flurries of activity (for instance the user moving the mouse) where you will get lots of events to respond to.
SDL_PollEvent will not "wait" for events. If there is an event in the queue you will get the information. If there is no event it will return false.
Handling events should be done quickly (remember we have to be finished in 17ms) don't worry it is quite a lot of time on a PC.
Once you are done with all the events and out of the inner loop you are ready to move on to updating the world and rendering.
At this point you will normally do stuff like AI. Calling physics engine. For instance you might iterate over the objects and change their position based on their velocity.
The next step is to actually do the drawing.
SDL_RenderClear(renderer);
...
SDL_RenderPresent((SDL_Renderer)renderer);
The first call will clear the screen. You then go and based on the state of different objects do the rendering. For instance maybe because we changed the object state to selected we will now draw a glowing border around it.
Your final call is for SDL_RenderPresent(renderer) to present the new screen to the user
If you are using Vsync (quite common) then this final call will hide a small wait time to synch the screen update with the graphics card capabilities. This will produce a smoother graphics. Assuming a 60Hz refresh rate (60 frames per second) and assuming you are running under 16.6 ms in your frame rendering logic the app will wait the remaining time.
Now the application is ready to go back to the start of the loop and check if there are any events in SDL_PollEvent. Since the entire loop typically only takes a few milliseconds the application will always feel responsive.
I need to clear any mouse clicks which has happened before the end of an animation.Only mouse clicks afterwards have to be considered.
I tried enabling my mouse function after the animation,but any clicks that happened during the animation was considered.
To my understanding there is a buffer where mouseclicks are stored and during any mouse callback , it takes the co-ordinates and any other info of the first click stored in that buffer.so i need to know how to clear this.
I used fflush(stdin) but it doesnt clear keyboard or the mouse buffer.
Am using windowsxp and programming in visualsudio2008 in c language.i also use glut.h
i also use glut.h
Then you can't. If you're doing an animation, it's up to you to process (or choose not to process) any messages.
You should not be animating something by looping within your display method. Instead, you should set up a timer callback or something that will call glutPostRedisplay that will constantly call your drawing method. During this time, you should ignore any messages if you don't want to process them.
I've made a project with Qt and OpenGL.
In Qt paintGL() was repeatedly call I beleive, so I was able to change values outside of that function and call update() so that it would paint a new image.
I also believe that it called initializeGL() as soon as you start up the program.
Now my question is:
I want that same functionality in a different program. I do not need to draw any images, etc. I just was wondering if there was a way to make a function like paintGL() that keeps being called so the application never closes. I tried just using a while(true) loop that kept my program running, but the GUI was inactive because of the while loop.
Any tips, other than threading preferably.
Thanks.
The exact mechanism will depend on which GUI toolkit you are using. In general, your app needs to service the run loop constantly for events to be dispatched. That is why your app was unresponsive when you had it running in a while loop.
If you need something repainted constantly, the easiest way is to create a timer when your window is created, and then in the timer even handler or callback, you invalidate your window which forces a repaint. Your paint handler can then be called at the frequency of your timer, such as 25 times per second.