EDITED WITH SOLUTION
So I am making a particle system in opengl. I am working in Linux. I want to make it more interactive, so, for example, when the user presses the spacebar, a new firework shoots out.
I am using GLUT to capture keyboard input, and when the user hits the spacebar, it shoots a firework out, then goes in a loop that loops for a while, and if I press spacebar again, it has to wait til that loop (mentioned above) is done executing before it registers the keypress.
So my question is this:
Is there a way for me to, at the start of the loop, to check the buffer that glut stores the keypress in? I feel like there has to be some sort of a buffer that it stores keypresses in, because yeah, once that loop above is finished executing, it registers the keypress.
SOLUTION:
I do not actually do any loops now anywhere (except to loop through arrays to update locations of my fireworks, etc), I do something like
in main, add this:
int main(int argc, char** argv){
//Usual glut initializations
glutTimerFunc(30, update, -1);//says in 30miliseconds call update
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Then in your update function (in the parameters for glutTimerFunc, so something like this:
void update(int k){
//UPDATE POSITION OF FIREWORKS
glutTimerFunc(30, update, -1);//it is important to add this
glutPostRedisplay();//calls display() on the next iteration of glut's main loop
}
Then finally in your display function, do what ever you need to do to draw one frame (in my case, loop through each firework and draw it!)
Hope this helps :)
You're going about this the wrong way.
Your keypress handler should not be looping over anything. Your keypress handler should simply set some variable and return.
Your main display function (which should be driven by a timer function that calls glutPostRedisplay) should check this variable. If it is set, then it should be firing your firework and looping for some duration.
During that time, your keypress handler should simply ignore any further pressing of the spacebar. Once the display function finishes with the firework, then it can respond to further key presses.
Related
If I run the following loop as part of my OpenGL program:
void Loop(int state)
{
glutPostRedisplay();
glutTimerFunc(1, Loop, 0);
}
Then, my program runs fine, and I am able to move the camera around the scene by dragging my mouse.
However, if I use this loop:
void Loop(int state)
{
glutPostRedisplay();
Loop();
}
I am not able to move around the scene with my mouse. The loop is being called, but it is just not processing any mouse or keyboard inputs.
I don't understand why this is. The only difference is that in the first example, a timer function is used to call Loop(), whereas in the second example, Loop() is called explicitly, without any delay.
So what is it that glutTimerFunc() is actually doing, besides calling Loop()?
In the first example, glutTimerFunc ensures Loop is called after 1 millisecond, however it returns and does not wait, meaning Loop in this case returns almost immediately.
In the second example, Loop is calling itself which results in infinite recursion and locks up your program's main thread, which would explain why nothing works in that case. Loop, then, never returns. If you left your program running long enough, your system would run out of memory due to the infinite recursion.
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.
I am trying to make a man jump on the y axis, so I use a loop of 2 seconds, the first second it should move down and bend its knees, and the second second it should move up and then finish in the starting position. Right now am just starting to make the man go down and bend it's knees in the first second, I haven't programmed the rest of the animation. The problem is that glutPostRedisplay is not refreshing the screen inside the loop as needed so it looks like an animation, it just re displays the screen after the loop has completed. How do I get glutPostRedisplay to refresh the screen inside my loop so it looks like an animation?
case ' ':
miliseconds = 0;
MoveManY = 0;
start = clock();
i=0;
while (miliseconds<2000)
{
finish = clock();
miliseconds = (finish - start);
Sleep(1);
if (miliseconds<1000)
{
MoveManY=MoveManY-0.02;
}
glutPostRedisplay();
}
break;
glutPostRedisplay does not directly trigger redrawing the screen. It only indicates to the system that the screen needs redrawing as soon as possible. Calling it multiple times in a loop, like you do, actually has the same effect as calling it once. See here for more details.
I cannot tell where the code you posted is called from. However, what you want to do is use glutIdleFunc to designate a method to be called when there's nothing else to do and, in it, do what you need for a single frame of your animation and call glutPostRedisplay once. This will require to move your timer somewhere else.
I found this tutorial to be really helpful with GLUT animations.
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 have a program which updates it the program output then the state of the program changes. This happens when a ticker of the time (not an openGL timer, one implemented in threads) happens, and when keyboard input is registered from glut (using glutKeyboardFunc callback).
Both of these events update the programs state and call glutPostRedisplay; the problem is only the when the keyboard is pressed does it actually do anything. When the timer ticks the display function is ignored, but when the keyboard is pressed the display function is called.
Does glut ignore other threads? And if so is there a way to get it to register them.
You cannot call glutPostRedisplay or most other GLUT functions from a thread other than the one GLUT was initialized in. GLUT is not thread-safe.