Limiting fps in glut

时间:2015-06-25 18:57:31

标签: c++ windows glut

When I try to limit fps using _ftime the framerate delay (aka. sleeping time) increases. After a minute the frames drop to almost zero. Is there a solution for this problem? I'm trying to make a delay in this style: void init(int unused){ Initilize(); glutDisplayFunc (render); glutReshapeFunc (reshape); glutKeyboardFunc (keyboard); glutMouseFunc (mouse); glutIdleFunc (timer); glutMainLoop(); timer(); //Get into the loop } void timer(void) { _ftime(&lasttime); //get the time glutPostRedisplay(); //Redraw all the elements and check for input long timetowait; _ftime(&curtime); //get the after time timetowait = ( (int) 1000/60 - ((1000 * (curtime.time - lasttime.time)) + curtime.millitm - lasttime.millitm)); //caculate the time to wait timetowait = max(timetowait, 0); //Don't want to have a negative sleep ;) glutTimerFunc(timetowait , timer, 0); //And now sleep } If this is a compatibility issue here are the specs: Windows 7 x86 on a x64 bit laptop (don't blame me about this) and using Dev C++ with glut extension (or in other words .DevPak file) The whole source code: #include <GL/glut.h> #include <GL/glu.h> #include <stdio.h> #include <string.h> #ifdef __unix__ #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <time.h> #define OS_Windows 0 #elif defined(_WIN32) || defined(WIN32) #include <io.h> #include <windows.h> #include <sys/timeb.h> #include <sys/types.h> #include <time.h> #define OS_Windows 1 #endif //Default variables char defaultcontrolconfig[5] = { 0x18, 0x19, 0x1A, 0x1B, 0x20 }; //UP,DOWN,LEFT,RIGHT,SPACE(JUMP) unsigned short defaultx = 500,defaulty = 500,defaultmode = 0; //X RES,Y RES, FULLSCREENMODE (0 NO ,1 YES) /** By default it should be UP - move on negative z axis DOWN - move on positive z axis LEFT - move left relative to the camera (mostly negative x axis) RIGHT - move right relative to the camera (mostly positive x axis) SPACE - jump (fxp. decreasing the Z value) **/ unsigned char controls[5],plsaply; unsigned short gamescreen; FILE *configuration; unsigned short displayx,displayy,displaymode,loop,clicked; int winIDMain,frames; double mainboxx = -1 ,mainboxy; int timetowait; #ifdef __unix__ struct timespec curtime,lasttime; #endif #ifdef OS_Windows struct _timeb curtime, lasttime; #endif void keyboard(unsigned char c, int x, int y) { if (gamescreen == 0){ if (c == 27) { exit(0); } }else if(gamescreen == 1){ if(c == 27) { gamescreen = 0; } }else if(gamescreen == 2){ switch(c){ case 27: gamescreen = 1; break; } } } void mouse(int button, int state, int x, int y) { int perpartpixels; if(clicked == 1){ loop = 1; clicked = 0; } if(loop > 0){ //To pervent gliched clicking loop--; }else{ if(gamescreen == 0) { perpartpixels = glutGet(GLUT_WINDOW_HEIGHT) / 40; //Aproxx 5% of the resolution if (button == GLUT_LEFT_BUTTON){ printf("X:%d Y:%d\n",x,y); if((y <= perpartpixels * 4 && y >= perpartpixels * 4 - 15) && (x >= 0 && x <= 81)){ printf("Play\n"); clicked = 1; }else if((y <= perpartpixels * 5 && y >= perpartpixels * 5 - 15) && (x >= 0 && x <= 72)){ gamescreen = 1; printf("Game Screen changed\n"); clicked = 1; }else if((y <= perpartpixels * 6 && y >= perpartpixels * 6 - 15) && (x >= 0 && x <= 36)){ exit(0); } } }else if(gamescreen == 1){ perpartpixels = glutGet(GLUT_WINDOW_HEIGHT) / 40; //Aproxx 5% of the resolution if (button == GLUT_LEFT_BUTTON){ printf("X:%d Y:%d\n",x,y); if((y >= perpartpixels * 4 - 15 && y <= perpartpixels * 4) && (x >= 0 && x <= 72)){ gamescreen = 2; printf("Game screen changed\n"); clicked = 1; }else if((y >= perpartpixels * 5 - 15 && y <= perpartpixels * 5) && (x >= 0 && x <= 162)){ configuration = fopen("configuration/controls.conf", "wb"); fwrite(defaultcontrolconfig,1,5,configuration); fclose(configuration); configuration = fopen("configuration/display.conf", "wb"); fprintf(configuration,"%hd\n%hd\n%hd",defaultx,defaulty,defaultmode); fclose(configuration); printf("Settings restored to default\n"); plsaply = 1; clicked = 1; }else if((y >= perpartpixels * 6 - 15 && y <= perpartpixels * 6) && (x >= 0 && x <= 36)){ gamescreen = 0; printf("Game screen changed\n"); clicked = 1; } } }else if(gamescreen == 2){ perpartpixels = glutGet(GLUT_WINDOW_HEIGHT) / 40; //Aproxx 5% of the resolution if(button == GLUT_LEFT_BUTTON){ if((y >= perpartpixels * 38 && y <= perpartpixels * 40) && (x >= 0 && x <= 36)){ gamescreen = 1; printf("Game screen changed\n"); clicked = 1; } } } } } void render(void) { glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); frames++; char str[50]; if(gamescreen == 0) { if(mainboxx >= 2.0){ mainboxx = -1; }else{ mainboxx+= 0.01; } if(mainboxx >= -0.4 && mainboxx <= -0.3){ mainboxy += 0.03; }else if(mainboxx >= -0.3 && mainboxx <= -0.2){ mainboxy += 0.01; }else if(mainboxx >= -0.2 && mainboxx <= 0.2){ mainboxy -= 0.01; }else if(mainboxx >= 0.2){ mainboxy = 0; } glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity; glColor3f(0.1,0.1,0.1); glTranslatef(-mainboxx, 0 , -1); glBegin(GL_QUADS); glVertex3f((mainboxx - 0.05),(mainboxy - 0.05),0); glVertex3f((mainboxx - 0.05),(mainboxy + 0.05),0); glVertex3f((mainboxx + 0.05),(mainboxy + 0.05),0); glVertex3f((mainboxx + 0.05),(mainboxy - 0.05),0); glVertex3f( -2, -0.05, 0); glVertex3f( -0.2, -0.05, 0); glVertex3f( -0.2, -1, 0); glVertex3f( -2, -1, 0); glVertex3f( 0.2, -0.05, 0); glVertex3f( 2.91, -0.05, 0); glVertex3f( 2.91, -1, 0); glVertex3f( 0.2, -1, 0); glEnd(); glPopMatrix(); sprintf(str, "%d", frames); char mainmenustring[9] = "Main Menu"; glColor3f(1, 1, 1); glRasterPos2f(-1, 0.9); int mainmenulen, mainmenui; mainmenulen = 9; for (mainmenui = 0; mainmenui < mainmenulen; mainmenui++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, mainmenustring[mainmenui]); } char startstring[5] = "Start"; glColor3f(1, 1, 1); glRasterPos2f(-1, 0.8); int startlen, starti; startlen = 5; for (starti = 0; starti < startlen; starti++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, startstring[starti]); } char settingsstring[8] = "Settings"; glColor3f(1, 1, 1); glRasterPos2f(-1, 0.75); int settingslen, settingsi; settingslen = 8; for (settingsi = 0; settingsi < settingslen; settingsi++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, settingsstring[settingsi]); } char exitstring[4] = "Exit"; glColor3f(1, 1, 1); glRasterPos2f(-1, 0.7); int exitlen, exiti; exitlen = 4; for (exiti = 0; exiti < exitlen; exiti++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, exitstring[exiti]); } glColor3f(1, 1, 1); glRasterPos2f(-1, -1); int flen, fi; flen = (int)strlen(str); for (fi = 0; fi < flen; fi++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, str[fi]); } }else if (gamescreen == 1) { if(plsaply){ sprintf(str, "%d Please restart to apply changes", frames); }else{ sprintf(str, "%d", frames); } char settingstring[8] = "Settings"; glColor3f(1, 1, 1); glRasterPos2f(-1, 0.9); int settinglen, settingi; settinglen = 8; for (settingi = 0; settingi < settinglen; settingi++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, settingstring[settingi]); } char constring[8] = "Controls"; glColor3f(1, 1, 1); glRasterPos2f(-1, 0.8); int conlen, coni; conlen = 8; for (coni = 0; coni < conlen; coni++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, constring[coni]); } char rtoodstring[18] = "Restore to Default"; glColor3f(1, 1, 1); glRasterPos2f(-1, 0.75); int rtoodlen, rtoodi; rtoodlen = 18; for (rtoodi = 0; rtoodi < rtoodlen; rtoodi++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, rtoodstring[rtoodi]); } char bckstring[4] = "Back"; glColor3f(1, 1, 1); glRasterPos2f(-1, 0.7); int bcklen, bcki; bcklen = 4; for (bcki = 0; bcki < bcklen; bcki++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, bckstring[bcki]); } glColor3f(1, 1, 1); glRasterPos2f(-1, -1); int flen, fi; flen = (int)strlen(str); for (fi = 0; fi < flen; fi++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, str[fi]); } }else if (gamescreen == 2){ char bckbtnstring[4] = "Back"; glColor3f(1, 1, 1); glRasterPos2f(-1, -0.9); int bckbtnlen, bckbtni; bckbtnlen = 4; for (bckbtni = 0; bckbtni < bckbtnlen; bckbtni++) { glutBitmapCharacter(GLUT_BITMAP_9_BY_15, bckbtnstring[bckbtni]); } } glutSwapBuffers(); } void reshape (int w, int h) { if(displaymode == 1){ glutFullScreen(); displayx = w; displayy = h; } glViewport (0, 0, w, h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); } void timer(void); void init(int unused); void Initilize(); void init(int unused){ Initilize(); glutDisplayFunc (render); glutReshapeFunc (reshape); glutKeyboardFunc (keyboard); glutMouseFunc (mouse); glutIdleFunc (timer); glutMainLoop(); timer(); } void timer(void) { _ftime(&lasttime); glutPostRedisplay(); long timetowait; _ftime(&curtime); timetowait = ( (int) 1000/60 - ((1000 * (curtime.time - lasttime.time)) + curtime.millitm - lasttime.millitm)); timetowait = max(timetowait, 0); glutTimerFunc(timetowait , timer, 0); } // Load config functions void loadconfiguration(void) { //Check if config folder is present otherwise create it #ifdef __unix__ int result = mkdir("configuration", 0777); #endif #ifdef OS_Windows int result = _mkdir("configuration"); #endif if(result == -1){ printf("Ignore creating folder:\nError -1 Directory already exists\n"); }else if(result != 0){ printf("Error: %d while creating configuration folder\n", result); } //Check if control configuration is present otherwise create it #ifdef __unix__ if (access("configuration/controls.conf",F_OK)!= -1) { printf ("Found controls configuration file\n"); configuration = fopen("configuration/controls.conf", "rb"); } else { configuration = fopen("configuration/controls.conf", "wb"); fwrite(defaultcontrolconfig,1,5,configuration); } #endif #ifdef OS_Windows if (INVALID_FILE_ATTRIBUTES == GetFileAttributes("configuration/controls.conf") && GetLastError()==ERROR_FILE_NOT_FOUND) { configuration = fopen("configuration/controls.conf", "wb"); fwrite(defaultcontrolconfig,1,5,configuration); } else { printf ("Found controls configuration file\n"); configuration = fopen("configuration/controls.conf", "rb"); } #endif fread(controls,1,5,configuration); printf("Finished loading controls configuration\n"); fclose(configuration); //Check if display configuration is present otherwise create it #ifdef __unix__ if (access("configuration/display.conf",F_OK)!= -1) { printf ("Found display configuration file\n"); configuration = fopen("configuration/display.conf", "rb"); } else { configuration = fopen("configuration/display.conf", "wb"); fprintf(configuration,"%hd\n%hd\n%hd",defaultx,defaulty,defaultmode); } #endif #ifdef OS_Windows if (INVALID_FILE_ATTRIBUTES == GetFileAttributes("configuration/display.conf") && GetLastError()==ERROR_FILE_NOT_FOUND) { configuration = fopen("configuration/display.conf", "wb"); fprintf(configuration,"%hd\n%hd\n%hd",defaultx,defaulty,defaultmode); } else { printf ("Found display configuration file\n"); configuration = fopen("configuration/display.conf", "rb"); } #endif rewind(configuration); fscanf(configuration,"%hd\n%hd\n%hd",&displayx,&displayy,&displaymode); printf("Finished loading display configuration\n"); fclose(configuration); printf("Finished loading configurations\n"); } void Initilize() { glClearColor(0, 0, 0, 0.1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); } int main() { loadconfiguration(); char *myargv [1]; int myargc=1; myargv [0]=strdup ("./file"); glutInit(&myargc, myargv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowPosition(100, 100); glutInitWindowSize(displayx, displayy); printf("Making a window\n"); winIDMain = glutCreateWindow("GL Game"); init(0); } Also I'am trying to get it as much as possible to be cross platform. Is it because of my code or the glut engine itself.

1 个答案:

答案 0 :(得分:0)

来自glut documentation

  

glutPostRedisplay将当前窗口标记为需要重新显示。

因此,此方法不会执行显示,但会告诉过剩。这意味着这种方法应该非常快。所以/Users与帧的长度有关。

然后,从glut documentation

  

glutTimerFunc注册一个定时器回调,以在指定的毫秒数内触发。

  

可以同时注册相同或不同时间的多个计时器回调。

所以我认为你最终注册了很多your mac <--X--> boot2docker VM <----> nginx container \_ /Users is mounted properly, but not other dir. 次调用,实际上阻止了GLUT进行任何显示。每次glut调用空闲Func,它都会创建一个新的递归timetowait调用链。

解决您的问题:

初始化时只调用timer()一次。并将您的功能更改为

timer()

这应该要求每隔60秒刷新一次。