I'm programming in C with GLUT and OPENGL, i want my window redrawing itself again and again. I know that i can rerender with glutPostRedisplay(), if I put it in the idle function of Glut my pc lags.
My code is following atm
void on_idle() {
glutPostRedisplay();
}
void on_draw() {
...
glClearColor(1.f, 1.f, 1.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
...
glFlush();
}
int main(int argc, char** argv) {
...
glutDisplayFunc(&on_draw);
glutIdleFunc(&on_idle);
...
}
Try this:
void on_timer(int value) {
glutPostRedisplay();
glutTimerFunc(33, on_timer, 0);
}
void on_draw() {
...
glClearColor(1.f, 1.f, 1.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
...
glFlush();
}
int main(int argc, char** argv) {
...
glutDisplayFunc(on_draw);
glutTimerFunc(33, on_timer, 0)
...
}
Make idle yielding any left CPU cycles on the time slice right before the glutPostRedisplay:
void on_idle() {
#ifdef WIN32
Sleep(0); // zero sleep = yield
#else ifdef _POSIX_PRIORITY_SCHEDULING
sched_yield(); // #include <sched.h>
#endif
glutPostRedisplay();
}
I don't quite understand your question... what do yo mean "you want your window redrawing itself again and again" ?
GLUT does that itself with the glutMainLoop() function that keeps calling the display call back function (Usually the problem is the reversed... people ask how they can leave the infinite loop programmatically.. which is impossible with GLUT, but not with FreeGLUT)
No need to put the redisplay in the idle function, which is only called when nothing else is happening...
Related
Here, I have two loops. The first loop processes the graphics for a few seconds and then the code goes to the second loop. I process the graphical events via glutMainLoopEvent in the first loop. Before the second loop starts, I would like to close the graphic window. It seems the command glutLeaveMainLoop cannot close the window. What other function should I use to force the window closed right after the first loop?
#include <stdio.h>
#include <GL/freeglut.h>
#include <boost/thread/thread.hpp> // for sleep
void cback_render()
{
if(!glutGetWindow())
return ;
static float rotations = 0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(rotations, 0, 0, 1);
glBegin(GL_TRIANGLES);
glVertex3f(0,0,0);
glVertex3f(1,0,0);
glVertex3f(0,1,0);
glEnd();
glutSwapBuffers();
if (++rotations > 360) rotations -= 360;
}
void timer(int )
{
if(!glutGetWindow())
return ;
glutPostRedisplay();
glutMainLoopEvent();
glutTimerFunc(30, timer, 1);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(512, 512);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glutCreateWindow("freegluttest");
glutDisplayFunc (cback_render);
glutTimerFunc(30, timer, 1);
long i=0;
while(glutGetWindow() && i< 30)
{
printf("[%ld]\n",i);
i++;
glutMainLoopEvent();
boost::this_thread::sleep( boost::posix_time::milliseconds(100) );
}
glutMainLoopEvent();
glutLeaveMainLoop(); // does not work
glutMainLoopEvent();
// do something else ....
while(1)
{
// other calculations
boost::this_thread::sleep( boost::posix_time::milliseconds(100) );
}
return 0;
}
Ok from the freeglut docs at http://freeglut.sourceforge.net/docs/api.php#EventProcessing
The function you are using glutLeaveMainLoop() is to simply stop the glut's main loop, if it is started by glutMainLoop() not glutMainLoopEvent().
Since you are controlling the loop yourself in your example, glutLeaveMainLoop() won't do anything.
It is intended to leave glut's main loop IF glut is controlling it not you.
Since you have a while(1) at the end with a 100ms sleep, the app will do nothing else when it gets there after all the frames have been rendered. If you want to destroy the window use some window function like glutDestroyWindow().
I keep calling glutMainLoopEvent to process the graphics. However, after someone closed the window, I would like to exit the loop and show Code reached here. . it seems when a window is closed, an exit function is called and the entire application stops. While I need the application to continue. How should I fix the code?
#include <stdio.h>
#include <GL/freeglut.h>
//display function - draws a triangle rotating about the origin
void cback_render()
{
//keeps track of rotations
static float rotations = 0;
//OpenGL stuff for triangle
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(rotations, 0, 0, 1);
glBegin(GL_TRIANGLES);
glVertex3f(0,0,0);
glVertex3f(1,0,0);
glVertex3f(0,1,0);
glEnd();
//display on screen
glutSwapBuffers();
//rotate triangle a little bit, wrapping around at 360°
if (++rotations > 360) rotations -= 360;
}
void timer(int value )
{
glutPostRedisplay();
glutMainLoopEvent();
glutTimerFunc(30, timer, 1);
}
int main(int argc, char **argv)
{
//initialisations
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(512, 512);
//create window and register display callback
glutCreateWindow("freegluttest");
glutDisplayFunc (cback_render);
glutTimerFunc(30, timer, 1);
//loop forever
long i=0;
while(1)
{
printf("[%ld]\n",i);
i++;
glutMainLoopEvent();
}
printf("Code reached here.");
return 0;
}
Use GLUT_ACTION_ON_WINDOW_CLOSE to allow your program to continue when a window is closed.
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS);
Sources:
http://www.lighthouse3d.com/cg-topics/glut-and-freeglut/
http://freeglut.sourceforge.net/docs/api.php
I am developing an application using GLFW, whereby the user can input some information into the console, the program does some processing on the information, then opens an opengl window (using GLFW) to display the results. The user can then close the window, and be returned to the main menu and enter more information if they want.
Currently the problem I'm having is that once closing the GLFW/OpenGL window the console no longer accepts any input from scanf(). I am fairly certain that I am closing GLFW properly, so I am unsure as to what the problem is.
The code I am using is below:
Main.c:
#include <stdio.h>
#include <stdlib.h>
#include "glfw.h"
#include "pantograph.h"
int main(int argc, char** argv)
{
printf("program start");
int a = 0;
scanf("%i",&a); //this works
printf("%c",a);
p_open_window(1000, 500, 0, "hi there");
int i = 0;
for(i=0;i<1000;i++)
{
p_begin_render();
glBegin(GL_POINTS);
glVertex2i(i,i/2);
glEnd();
scanf("%i",&a);
p_end_render();
}
p_close_window();
scanf("%i",&a); //this does not work
printf("%i",a);
return 0;
}
pantograph.h:
int p_open_window(int width, int height, int fullscreen, const char* title)
{
glfwInit();
glfwDisable(GLFW_AUTO_POLL_EVENTS);
if(fullscreen)
{
glfwOpenWindow(width,height,8,8,8,8,0,0,GLFW_FULLSCREEN);
}else{
glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, GL_TRUE);
glfwOpenWindow(width,height,8,8,8,8,0,0,GLFW_WINDOW);
}
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
return 1;
}
void p_begin_render()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor4f(1.0, 1.0, 1.0, 1.0);
glLoadIdentity();
}
void p_end_render()
{
glfwSwapBuffers();
}
void p_close_window()
{
glfwCloseWindow();
glfwTerminate();
}
I'm a little confused by your program flow. You say 'the user can close the window and be returned to the main menu'. But how does the program exit from the (i<1000) loop? If the user just closes the window it seems like it would still be executing the for loop (especially because of the scanf inside the loop).
Have you used a debugger to see which point your program gets caught on?
Thanks to the people at #glfw I've managed to find a somewhat hackish solution...
If you "flush" the input buffer directly after closing the glfw window scanf will start to work again. I'm not entirely sure why, but it seems to work for now, so I'm satsfied.
The code I'm using to do it is as follows (after closing the window):
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
After this, scanf began working again.
I'm trying out a simple implementation of trying to render a bitmap font, as given in the Red book. The problem is that my viewport is blank throughout and nothing comes on the screen.
Here's the code:
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
GLubyte A[14] = {
0xc0,0x00,
0x60,0xc0,
0x3f,0x80,
0x11,0x00,
0x0a,0x00,
0x0a,0x00,
0x04,0x00,
};
void init(void)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glClearColor(0,0,0,0);
}
void display(void)
{
float c[4];
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);
glGetFloatv(GL_CURRENT_RASTER_POSITION, c);
printf("%f %f %f %f\n", c[0],c[1],c[2],c[3]);
printf("%x\n",A[0]);
glRasterPos2f(20,20);
glGetFloatv(GL_CURRENT_RASTER_POSITION_VALID, c);
printf("%f\n", c[0]);
glBitmap(12,7,0,0,11,0,A);
//glBitmap(12,7,0,0,11,0,A);
//glBitmap(12,7,0,0,11,0,A);
glGetFloatv(GL_CURRENT_RASTER_POSITION, c);
printf("%f %f %f %f\n", c[0],c[1],c[2],c[3]);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0,0,(GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,w,0, h, -1.0, 1.0);
//gluOrtho2D(0,1,0,1);
glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 27:
exit(0);
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(100,100);
glutCreateWindow("FOnt");
init();
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Works for me:
FreeGLUT on Vista64 (compiled as 32-bit), Radeon HD 6570. VS 2008.
EDIT: On Linux too:
Ubuntu 10.04 amd64, Intel HD Graphics 3000, Mesa DRI Intel(R) Sandybridge Mobile GEM 20100330 DEVELOPMENT
EDIT2:
Try using double-buffering via glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB) or glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA) and adding glutSwapBuffers() to the end of your display() function.
And/or try disabling your compositor (compiz, kwin, unity, GNOME Shell, etc) if you have one enabled.
Might be a driver bug.
Replace GL_SINGLE with GLUT_DOUBLE
Replace glFlush() with glutSwapBuffers()
Add glLoadIdentity() after glMatrixMode(GL_MODELVIEW)
Then it should work
Here is a simple opengl program by me. I'm trying to clear the screen before I draw a triangle. I've called glClear() in my init() function, however, it seemed that it failed to clear the screen.
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
void myIdleFunc()
{
glBegin(GL_TRIANGLES);
{
glColor3f(1.0f, 1.0f, 1.0f);
glVertex2f(0.0f, 1.0f);
glVertex2f(-1.0f, -1.0f);
glVertex2f(1.0f, -1.0f);
}
glEnd();
glFlush();
usleep(1000000);
}
void init()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutCreateWindow("Hello, World!");
init();
glutIdleFunc(myIdleFunc);
glutMainLoop();
return 1;
}
Here is a screen-shot, the text is from the gnome terminal in the back ground.
Where's your display callback? You shouldn't use the idle function for drawing.
All drawing needs to take place in the appropriate callbacks, the GL context might not be active until glutMainLoop starts running, and with no active context, your commands simply get ignored (without a context, there might not even be a place to store errors for retrieval with glGetError).
NOTE: Usually you want to clear the buffer at the beginning of every frame. You might get away with clearing just once with single-buffering, but double-buffering is better and requires you to somehow render the entire area between each swap.
Your problem is, that you do clear the screen in your initialization code. But you need to clear it every frame, so right at the start of your display (or in your case idle) function.
I don't use GLUT but a really simple way to display something like this is:
while( !done ) { /* Loop until done. Do drawing. */
glClear( GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glBegin(GL_TRIANGLES);
{
glColor3f(1.0f, 1.0f, 1.0f);
glVertex2f(0.0f, 1.0f);
glVertex2f(-1.0f, -1.0f);
glVertex2f(1.0f, -1.0f);
}
glEnd();
glFlush();
SwapBuffers( );
etc... event handling....
}
Run this code and probably you will get the solution.
#include<GL/gl.h>
#include<GL/glut.h>
#include<stdio.h>
double x_0 = -100;
double y_0 = -25;
double x_1 = 100;
double y_1 = -25;
double x_2 = 100;
double y_2 = 25;
double x_3 = -100;
double y_3 = 25;
void
init(void)
{
/*initialize the x-y co-ordinate*/
glClearColor(0,0,0,0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-320, 319,-240, 239);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
void
drawRectangle()
{
glBegin(GL_LINES);
glVertex2d(x_0, y_0);
glVertex2d(x_1, y_1);
glVertex2d(x_1, y_1);
glVertex2d(x_2, y_2);
glVertex2d(x_2, y_2);
glVertex2d(x_3, y_3);
glVertex2d(x_3, y_3);
glVertex2d(x_0, y_0);
glEnd();
glFlush();
}
int
main(int argc, char *argv[])
{
double x_0, y_0, x_1, y_1;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(400, 400);
glutCreateWindow("Clear Screen");
init();
drawRectangle();
/* clear the screen. You can uncomment following three lines to view the effect of clearing */
// glClearColor(0, 0, 0, 0);
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// /* don't forget to flush */
// glFlush();
/***/
glutMainLoop();
}
Compile and run -
gcc file.c -lglut -lGLU -lGL
./a.out