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().
Related
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'm working with Cairo and GTK3.0 and I got problems that I have no clue on how to solve.
Currently I have 2 oddities that I do not have the knowledge of to solve.
The draw event is called whenever the terminal floats over the drawing window.
The program does not pas the gtk_main(); function.
I will provide my code below, which is very basic, it is based on this: http://zetcode.com/gfx/cairo/cairobackends/ , the GTK window part.
I eventually just need a window that I can call the draw event on whenever I want in my code.
#include <cairo.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int xStart;
int yStart;
int xEnd;
int yEnd;
} lineData;
int i = 0;
int gonnaDraw = 0;
lineData *lines;
int lineSize = 0;
/**
* The drawing with the cairo elements is done here.
* The new line is saved to an array.
* Eventually there should be a loop that draws all lines in the array.
*/
static void do_drawing(cairo_t *cr) {
printf("I'm endless, somehow.\n");
if(lineSize != 0) { //We only want to draw in the infinite for loop, not before it.
cairo_set_source_rgb(cr, 255, 0, 0);
cairo_set_line_width(cr, 1.0);
lineData newLine = { 10.0 + i, 50.0 + i, 100.0 + i, 50.0 + i };
//lines[lineSize - 1] = newLine;
cairo_move_to(cr, newLine.xStart, newLine.xEnd);
cairo_line_to(cr, newLine.yStart, newLine.yEnd);
cairo_stroke(cr);
i = i + 10;
printf("i: %d\n", i);
gonnaDraw = 1;
}
}
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data) {
do_drawing(cr);
return FALSE;
}
int main (int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *darea;
printf("1\n");
gtk_init(&argc, &argv);
printf("2\n");
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
printf("3\n");
darea = gtk_drawing_area_new();
printf("4\n");
gtk_container_add(GTK_CONTAINER(window), darea);
printf("5\n");
g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(on_draw_event), NULL);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
printf("6\n");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 800);
gtk_window_set_title(GTK_WINDOW(window), "GTK window");
printf("7\n");
gtk_widget_show_all(window);
printf("8\n");
gtk_main(); // If I'm removed I got no drawing window.
printf("9\n"); // I do not show up.
lines = (lineData *) malloc(lineSize * sizeof(lineData));
for(;;) {
if(gonnaDraw == 1) {
lineSize++;
printf("lineSize: %d\n", lineSize);
lines = (lineData *) realloc(lines, lineSize * sizeof(lineData));
gtk_widget_queue_draw(window);
gonnaDraw = 0;
}
}
return 0;
}
Compiled with standard method.
You almost understand the GTK+ drawing model now. Question 1 is a consequence of it: when another window goes over yours, the window system tells GTK+ that that area needs to be redrawn. This is what i meant when I talked about clipping.
Now the other part is understanding the GTK+ event model. All window systems operate in such a way that all programs run on a loop that consists of while the program is alive, get a message from the window system and act on it. This is what gtk_main() does. gtk_main() not returning is normal; it doesn't return until a call to gtk_main_quit(). Apart from using signals to perform actions when a widget is interacted with, there are two ways you can "hook into" the main loop: g_timeout_add(), which runs a function on schedule, and g_idle_add(), which runs a function when next possible. The former is useful if you want something to happen every so often; the latter is useful if you want a worker thread to signal the UI to update. The GLib documentation on main loops will tell you more. I'm still not sure what your end goal is, so I suppose you can try playing with both to see what happens.
– andlabs
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.
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...