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
Related
This is the code I am using
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
int main(){
if(!glfwInit()){
fprintf(stderr,"failed glfw initialization");
return -1;
}
GLFWwindow* window = glfwCreateWindow(800,800,"i hope this works",NULL,NULL);
if (!window){
fprintf(stderr,"window creation failed");
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = 1;
if(glewInit() != GLEW_OK){
fprintf(stderr,"glew failed to initialize");
return -1;
}
while(!glfwWindowShouldClose(window)){
}
}
Whenever I run the program, the window shows up, but it has the image of whatever was behind it when the window was opened.
Sometimes it changes when I resize or move the window.
You need to clear your buffers. If you're using two buffers then write:
// Render
// Clear the colorbuffer
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
at the beginning of you Game Loop.
Also write:
// Swap the screen buffers
glfwSwapBuffers(window);
at the end of your Game Loop.
So all together:
while(!glfwWindowShouldClose(window)){
// Render
// Clear the colorbuffer
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* ... Code ... */
// Swap the screen buffers
glfwSwapBuffers(window);
}
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 am trying to draw a line using OpenGL while the both end coordinates of the line are set in the idle function , but it is not getting drawn while I am sending the endpoint coordinates over the network using sockets.
below is the snap of the code
int main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitWindowSize( 1024,1024); /* A x A pixel screen window */
glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE);
glutCreateWindow("Skeleton Tracker"); /* window title */
glutDisplayFunc(display); /* tell OpenGL main loop what */
glutIdleFunc(idle);
//first create the connection then we wil talk about the data transfer...
/*****Code for server connection *****/
processRequest();
return 0;
}
void processrequest()
{
byte_sent = send(ClientSocket,(char*)&msg_pkt,sizeof(MSG_PACKET),0);
ofile<<"\nByte sent for start generating "<<byte_sent<<endl;
Sleep(1000);
memset(buf,0,sizeof(buf));
glutMainLoop();
}
void display(void)
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); /* clear the window */
glColor3f ( 0.0, 1.0 , 0.0); /* draw in light red */
glBegin(GL_LINES);
glVertex2f(x[0] , y[0]);
glVertex2f(x[1] , y[1]);
glEnd();
glEnd();
glFlush();
}
void idle(void)
{
printf("\nIn Idle function\n");
nRetVal = recv(ClientSocket , (char*)mainbuf , 192,0);
printf("\nAmount of data received : %d\n" , nRetVal);
memcpy(buf , mainbuf , sizeof(buf)); //buf is of 8 bytes to hold 2 floating nos.
memcpy( &x[p] ,buf , 4); // upto 3
x[p] = x[p]/10.0;
memcpy( &y[p] ,buf+4 , 4); //upto 7
y[p] = y[p]/10.0;
glutPostRedisplay();
}
Design of your program is questionable - you have blocking recv() function in your idle function which is not good, idle should be as fast as possible to not affect your rendering.
consider creating one thread for rendering and the second thread for network communication, or at least use non-blockable recv() in your idle function to check whether there is any data on the socket available before reading (recv'ing) from it.
Thanks buddies for your time ... actually I forget to define the orthographic projection matrix before calling the glutMainloop ...
gluOrtho2D( -250, 250, -250, 250);
its working now.
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.
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