The Code So Far VII
Prev: glutPostRedisplay | Next: Source Code and Projects |
The source code using glutPostRedisplay
instead of registering an idle function. As usual check out the source code at GitHub.
#include <stdio.h> #include <stdlib.h> #include <math.h> #ifdef __APPLE__ #include <GLUT/glut.h> #else #include <GL/glut.h> #endif // angle of rotation for the camera direction float angle = 0.0f; // actual vector representing the camera's direction float lx=0.0f,lz=-1.0f, ly = 0.0f; // XZ position of the camera float x=0.0f, z=5.0f, y = 1.75f; // the key states. These variables will be zero //when no key is being presses float deltaAngle = 0.0f; float deltaMove = 0; int xOrigin = -1; // width and height of the window int h,w; // variables to compute frames per second int frame; long time, timebase; char s[50]; // variables to hold window identifiers int mainWindow, subWindow1,subWindow2,subWindow3; //border between subwindows int border = 6; void setProjection(int w1, int h1) { float ratio; // Prevent a divide by zero, when window is too short // (you cant make a window of zero width). ratio = 1.0f * w1 / h1; // Reset the coordinate system before modifying glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Set the viewport to be the entire window glViewport(0, 0, w1, h1); // Set the clipping volume gluPerspective(45,ratio,0.1,1000); glMatrixMode(GL_MODELVIEW); } void changeSize(int w1,int h1) { if(h1 == 0) h1 = 1; // we're keeping these values cause we'll need them latter w = w1; h = h1; // set subwindow 1 as the active window glutSetWindow(subWindow1); // resize and reposition the sub window glutPositionWindow(border,border); glutReshapeWindow(w-2*border, h/2 - border*3/2); setProjection(w-2*border, h/2 - border*3/2); // set subwindow 2 as the active window glutSetWindow(subWindow2); // resize and reposition the sub window glutPositionWindow(border,(h+border)/2); glutReshapeWindow(w/2-border*3/2, h/2 - border*3/2); setProjection(w/2-border*3/2,h/2 - border*3/2); // set subwindow 3 as the active window glutSetWindow(subWindow3); // resize and reposition the sub window glutPositionWindow((w+border)/2,(h+border)/2); glutReshapeWindow(w/2-border*3/2,h/2 - border*3/2); setProjection(w/2-border*3/2,h/2 - border*3/2); } void drawSnowMan() { glColor3f(1.0f, 1.0f, 1.0f); // Draw Body glTranslatef(0.0f ,0.75f, 0.0f); glutSolidSphere(0.75f,20,20); // Draw Head glTranslatef(0.0f, 1.0f, 0.0f); glutSolidSphere(0.25f,20,20); // Draw Eyes glPushMatrix(); glColor3f(0.0f,0.0f,0.0f); glTranslatef(0.05f, 0.10f, 0.18f); glutSolidSphere(0.05f,10,10); glTranslatef(-0.1f, 0.0f, 0.0f); glutSolidSphere(0.05f,10,10); glPopMatrix(); // Draw Nose glColor3f(1.0f, 0.5f, 0.5f); glRotatef(0.0f,1.0f, 0.0f, 0.0f); glutSolidCone(0.08f,0.5f,10,2); glColor3f(1.0f, 1.0f, 1.0f); } void renderBitmapString( float x, float y, float z, void *font, char *string) { char *c; glRasterPos3f(x, y,z); for (c=string; *c != '\0'; c++) { glutBitmapCharacter(font, *c); } } void restorePerspectiveProjection() { glMatrixMode(GL_PROJECTION); // restore previous projection matrix glPopMatrix(); // get back to modelview mode glMatrixMode(GL_MODELVIEW); } void setOrthographicProjection() { // switch to projection mode glMatrixMode(GL_PROJECTION); // save previous matrix which contains the //settings for the perspective projection glPushMatrix(); // reset matrix glLoadIdentity(); // set a 2D orthographic projection gluOrtho2D(0, w, h, 0); // switch back to modelview mode glMatrixMode(GL_MODELVIEW); } void computePos(float deltaMove) { x += deltaMove * lx * 0.1f; z += deltaMove * lz * 0.1f; } // Common Render Items for all subwindows void renderScene2() { // Draw ground glColor3f(0.9f, 0.9f, 0.9f); glBegin(GL_QUADS); glVertex3f(-100.0f, 0.0f, -100.0f); glVertex3f(-100.0f, 0.0f, 100.0f); glVertex3f( 100.0f, 0.0f, 100.0f); glVertex3f( 100.0f, 0.0f, -100.0f); glEnd(); // Draw 36 SnowMen for(int i = -3; i < 3; i++) for(int j=-3; j < 3; j++) { glPushMatrix(); glTranslatef(i*10.0f, 0.0f, j * 10.0f); drawSnowMan(); glPopMatrix(); } } // Display func for main window void renderScene() { glutSetWindow(mainWindow); glClear(GL_COLOR_BUFFER_BIT); glutSwapBuffers(); } // Display func for sub window 1 void renderScenesw1() { glutSetWindow(subWindow1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(x, y, z, x + lx,y + ly,z + lz, 0.0f,1.0f,0.0f); renderScene2(); // display fps in the top window frame++; time=glutGet(GLUT_ELAPSED_TIME); if (time - timebase > 1000) { sprintf(s,"Lighthouse3D - FPS:%4.2f", frame*1000.0/(time-timebase)); timebase = time; frame = 0; } setOrthographicProjection(); glPushMatrix(); glLoadIdentity(); renderBitmapString(5,30,0,GLUT_BITMAP_HELVETICA_12,s); glPopMatrix(); restorePerspectiveProjection(); glutSwapBuffers(); } // Display func for sub window 2 void renderScenesw2() { glutSetWindow(subWindow2); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(x, y+15, z, x ,y - 1,z, lx,0,lz); // Draw red cone at the location of the main camera glPushMatrix(); glColor3f(1.0,0.0,0.0); glTranslatef(x,y,z); glRotatef(180-(angle+deltaAngle)*180.0/3.14,0.0,1.0,0.0); glutSolidCone(0.2,0.8f,4,4); glPopMatrix(); renderScene2(); glutSwapBuffers(); } // Display func for sub window 3 void renderScenesw3() { glutSetWindow(subWindow3); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(x-lz*10 , y, z+lx*10, x ,y ,z , 0.0f,1.0f,0.0f); // Draw red cone at the location of the main camera glPushMatrix(); glColor3f(1.0,0.0,0.0); glTranslatef(x,y,z); glRotatef(180-(angle+deltaAngle)*180.0/3.14,0.0,1.0,0.0); glutSolidCone(0.2,0.8f,4,4); glPopMatrix(); renderScene2(); glutSwapBuffers(); } // Global render func void renderSceneAll() { // check for keyboard movement if (deltaMove) { computePos(deltaMove); glutSetWindow(mainWindow); glutPostRedisplay(); } renderScene(); renderScenesw1(); renderScenesw2(); renderScenesw3(); } // ----------------------------------- // KEYBOARD // ----------------------------------- void processNormalKeys(unsigned char key, int xx, int yy) { if (key == 27) { glutDestroyWindow(mainWindow); exit(0); } } void pressKey(int key, int xx, int yy) { switch (key) { case GLUT_KEY_UP : deltaMove = 0.5f; break; case GLUT_KEY_DOWN : deltaMove = -0.5f; break; } glutSetWindow(mainWindow); glutPostRedisplay(); } void releaseKey(int key, int x, int y) { switch (key) { case GLUT_KEY_UP : case GLUT_KEY_DOWN : deltaMove = 0;break; } } // ----------------------------------- // MOUSE // ----------------------------------- void mouseMove(int x, int y) { // this will only be true when the left button is down if (xOrigin >= 0) { // update deltaAngle deltaAngle = (x - xOrigin) * 0.001f; // update camera's direction lx = sin(angle + deltaAngle); lz = -cos(angle + deltaAngle); glutSetWindow(mainWindow); glutPostRedisplay(); } } void mouseButton(int button, int state, int x, int y) { // only start motion if the left button is pressed if (button == GLUT_LEFT_BUTTON) { // when the button is released if (state == GLUT_UP) { angle += deltaAngle; deltaAngle = 0.0f; xOrigin = -1; } else {// state = GLUT_DOWN xOrigin = x; } } } // ----------------------------------- // MAIN and INIT // ----------------------------------- void init() { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); // register callbacks glutIgnoreKeyRepeat(1); glutKeyboardFunc(processNormalKeys); glutSpecialFunc(pressKey); glutSpecialUpFunc(releaseKey); glutMouseFunc(mouseButton); glutMotionFunc(mouseMove); } int main(int argc, char **argv) { // init GLUT and create main window glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100,100); glutInitWindowSize(800,800); mainWindow = glutCreateWindow("Lighthouse3D - GLUT Tutorial"); // callbacks for main window glutDisplayFunc(renderSceneAll); glutReshapeFunc(changeSize); // Removing the idle function to save CPU and GPU //glutIdleFunc(renderSceneAll); init(); // sub windows subWindow1 = glutCreateSubWindow(mainWindow, border,border,w-2*border, h/2 - border*3/2); glutDisplayFunc(renderScenesw1); init(); subWindow2 = glutCreateSubWindow(mainWindow, border,(h+border)/2,w/2-border*3/2, h/2 - border*3/2); glutDisplayFunc(renderScenesw2); init(); subWindow3 = glutCreateSubWindow(mainWindow, (w+border)/2,(h+border)/2,w/2-border*3/2,h/2 - border*3/2); glutDisplayFunc(renderScenesw3); init(); // enter GLUT event processing cycle glutMainLoop(); return 1; }
Prev: glutPostRedisplay | Next: Source Code and Projects |
7 Responses to “The Code So Far VII”
Leave a Reply Cancel reply
This site uses Akismet to reduce spam. Learn how your comment data is processed.
Hi,
Some of the functions seem to be deprecated, what is the replacement for them (gluPerspective and glMatrixMode) in OpenGL 4.2, been searching online but I haven’t found anything and pretty new to GLUT and using GL (outside of writing shaders).
Thanks
Your tutorial was very useful. I think you deserve a medal or something. Thanks a billion
Hi Justin,
Thanks for the feedback
I skipped ahead… somewhere along the line “esc” is now a crashing my program (and I don’t mean close).
Excellent tutorials, two issues however.
1) Everytime Game Mode is initialised it goes to full screen then promptly exits, I have changed bit depth, resolution and the program runs in windowed mode fine, everytime I assign it to a function key, such as F4 it doesn’t do anything, yet the other function keys, F3, F2, F1 etc work fine.
2) Ever since the last tutorial where I changed from Idle Function to glutPostRedisplay, the FPS counter isn’t always running, is there a way to maintain the FPS counter whilst yeilding the control back to the CPU? Do games constantly render seeing as the FPS counter is always updating?
Thanks Wilksey,
1) I have no clue as to why it is behaving like that. 🙁
2) Yes, to have the FPS counter you must keep rendering as often as possible, either with the Idle function or keep calling glutPostRedisplay at the end of every frame.
Your tutorials are simply AWESOME! Just what I needed to start making a game with OpenGL.
Thank you Thank you Thank you Thank you Thank you so much!!! 🙂
p.s: “void main” is no longer relevant in c or c++. It’s always “int main”.