void display() { /* If we are using DGR, send or receive data to keep multiple * processes/computers synchronized. */ dgr_update(); /* Syncronize the DGR objects */ dgr_setget("paddleA", &paddleA, sizeof(Paddle)); dgr_setget("paddleB", &paddleB, sizeof(Paddle)); dgr_setget("ball", &ball, sizeof(Ball)); dgr_setget("planet", planet, sizeof(float)*3); dgr_setget("state", &gameState, sizeof(int)); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); glEnable(GL_NORMALIZE); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glColor3f(1,1,1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float frustum[6]; projmat_get_frustum(frustum, -1, -1); glOrtho(frustum[0], frustum[1], frustum[2], frustum[3], frustum[4], frustum[5]); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Pick a depth that is between the near and far planes. float depth = -(frustum[4] + frustum[5])/2.0; // Move the light source GLfloat position[] = { 1.0f, -1.0f, depth+5.5f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, position); // Draw the background stars float masterfrust[6]; projmat_get_master_frustum(masterfrust); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, texIdStars); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Draw the background quad with the scrolling star texture float tickmod = ticks / 200.0f; glBegin(GL_QUADS); glTexCoord2f(tickmod+1.0f, -tickmod); glVertex3f(masterfrust[1], masterfrust[3], depth-3.0); glTexCoord2f(tickmod, -tickmod); glVertex3f(masterfrust[0], masterfrust[3], depth-3.0); glTexCoord2f(tickmod, 1.0f-tickmod); glVertex3f(masterfrust[0], masterfrust[2], depth-3.0); glTexCoord2f(tickmod+1.0f, 1.0f-tickmod); glVertex3f(masterfrust[1], masterfrust[2], depth-3.0); glEnd(); //Draw the earth glMatrixMode(GL_MODELVIEW); glPushMatrix(); glBindTexture(GL_TEXTURE_2D, texIdEarth); glTranslatef(planet[0], planet[1], depth-3.0); glRotatef(25.0f, 0.0f, 0.0f, 1.0f); glRotatef(-90, 1.0f, 0.0f, 0.0f); glRotatef(ticks, 0.0f, 0.0f, 1.0f); ticks += .005; if(ticks > 360.0f)ticks = 0.0f; gluSphere(earth, planet[2]*1.65f, 200, 200); glPopMatrix(); //Draw the clouds glEnable(GL_BLEND); glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR); glPushMatrix(); glBindTexture(GL_TEXTURE_2D, texIdClouds); glLoadIdentity(); glTranslatef(planet[0], planet[1], depth-3.0); glRotatef(25.0f, 0.0f, 0.0f, 1.0f); glRotatef(-90, 1.0f, 0.0f, 0.0f); glRotatef(ticks, 1.0f, 0.0f, 1.0f); gluSphere(clouds, planet[2]*1.652f, 200, 200); glPopMatrix(); // Reset somethings for the rest of the scene glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // top player (player 1) paddle drawPaddle(paddleA, depth+5.0f); // bottom player (player 2) paddle drawPaddle(paddleB, depth+5.0f); glDisable(GL_BLEND); // ball glEnable(GL_LIGHTING); glColor3fv(ball.color); glPushMatrix(); glTranslatef(ball.xpos, ball.ypos, depth+4.0f); glutSolidSphere(ball.radius, 100, 100); glPopMatrix(); /* If DGR is enabled, only do this in the master*/ if(dgr_is_enabled() == 0 || dgr_is_master()) { // Run the game code game(); } glFlush(); glutSwapBuffers(); glutPostRedisplay(); // call display() repeatedly }
void display(void) { kuhl_limitfps(100); dgr_update(); // Make sure slaves get updates ASAP dgr_setget("currentTex", ¤tTexture, sizeof(int)); /* If the texture has changed since we were previously in display() */ if(alreadyDisplayedTexture != currentTexture) { // Load the new texture loadTexture(currentTexture); // Keep a record of which texture we are currently displaying // so we can detect when DGR changes currentTexture on a // slave. alreadyDisplayedTexture = currentTexture; } /* The view frustum is an orthographic frustum for this * application. The size of the frustum doesn't matter much, but * the aspect ratio of the frustum should match the aspect ratio * of the screen/window. */ float frustum[6], masterFrustum[6]; /* The following two methods will get the master view frustum and * the current process view frustum. If we are running in a * standalone version, these two frustums will be the same. */ projmat_get_master_frustum(masterFrustum); projmat_get_frustum(frustum, -1, -1); // frustum of this process (master or slave) /* Set this view frustum for this process. */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(frustum[0],frustum[1], frustum[2],frustum[3], -1, 1); glMatrixMode(GL_MODELVIEW); // Middle of master frustum in the vertical direction. It divides the top // tiles from the bottom tiles. float masterFrustumMid = (masterFrustum[2]+masterFrustum[3])/2; // Dimensions of the master view frustum float masterFrustumWidth = masterFrustum[1]-masterFrustum[0]; float masterFrustumHeight = masterFrustum[3]-masterFrustum[2]; // The width of the quad (in frustum units). Since the image will // be stretched to fit the screen vertically, and our units are in // frustum units, the width of the tile is the height of the // frustum times the aspect ratio divided by the number of tiles // in the horizontal direction. float quadWidth = aspectRatio * masterFrustumHeight; float tileWidth = quadWidth/numTiles; // TODO: Maybe just scale the image vertically if the image almost fits in the screen horizontally? int msSincePictureDisplayed = glutGet(GLUT_ELAPSED_TIME)-lastAdvance; int scrollStatus = 0; // 0=don't need to scroll or done scrolling, 1=currently scrolling if(masterFrustumWidth < quadWidth)// do we need to scroll on this image { // Do we still need to scroll? if(scrollAmount < quadWidth-masterFrustumWidth) scrollStatus = 1; if(scrollStatus == 1) { // Wait a few seconds before scrolling. It takes a while // for all slaves on IVS to get the images. if(msSincePictureDisplayed > 5000) scrollAmount = ((msSincePictureDisplayed-5000) / (SCROLL_SPEED*1000.0))*masterFrustumWidth; else scrollAmount = 0; // If we calculated the scroll amount to be the largest // scrollAmount we'll need if(scrollAmount > quadWidth-masterFrustumWidth) { // dwell at the end of the image even if autoadvance is on. int now = glutGet(GLUT_ELAPSED_TIME); // make sure we still have a few seconds before advancing if(SLIDESHOW_WAIT*1000-(now-lastAdvance) < 3000) { // Go back and set lastAdvance time so we have // some time to dwell here. lastAdvance = now-SLIDESHOW_WAIT*1000+3000; } } } } dgr_setget("scrollAmount", &scrollAmount, sizeof(float)); /* If autoadvance is set and we are not scrolling (or done * scrolling) figure out if it is now time to advance to the next * image. */ if(autoAdvance == 1 && scrollStatus != 1) { // printf("time since last advance %d\n", glutGet(GLUT_ELAPSED_TIME)-lastAdvance); if(glutGet(GLUT_ELAPSED_TIME)-lastAdvance > SLIDESHOW_WAIT*1000) // time to show new image: { currentTexture = getNextTexture(); loadTexture(currentTexture); return; } } glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glColor3f(1,1,1); // color of quad // Draw the top and bottom quad for each of the tiles going across the screen horizontally. */ for(GLuint i=0; i<numTiles*2; i=i+2) { float tileLeft = (i/2 )*tileWidth + masterFrustum[0]; float tileRight = (i/2+1)*tileWidth + masterFrustum[0]; // Draw bottom tile glBindTexture(GL_TEXTURE_2D, texNames[i]); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex2d(tileLeft -scrollAmount, masterFrustum[2]); // lower left glTexCoord2f(1.0, 0.0); glVertex2d(tileRight-scrollAmount, masterFrustum[2]); // lower right glTexCoord2f(1.0, 1.0); glVertex2d(tileRight-scrollAmount, masterFrustumMid); // upper right glTexCoord2f(0.0, 1.0); glVertex2d(tileLeft -scrollAmount, masterFrustumMid); // upper left glEnd(); // Draw top tile glBindTexture(GL_TEXTURE_2D, texNames[i+1]); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex2d(tileLeft -scrollAmount, masterFrustumMid); // lower left glTexCoord2f(1.0, 0.0); glVertex2d(tileRight-scrollAmount, masterFrustumMid); // lower right glTexCoord2f(1.0, 1.0); glVertex2d(tileRight-scrollAmount, masterFrustum[3]); // upper right glTexCoord2f(0.0, 1.0); glVertex2d(tileLeft -scrollAmount, masterFrustum[3]); // upper left glEnd(); } glDisable(GL_TEXTURE_2D); /* Draw filename label on top of a quad. */ glColor4f(0,0,0,.3); glBegin(GL_QUADS); glVertex2d(-1,-1); glVertex2d(-.5,-1); glVertex2d(-.5,-.96); glVertex2d(-1,-.96); glEnd(); glColor4f(1,1,1,.9); glRasterPos2f(-.98,-.98); void *font = GLUT_BITMAP_TIMES_ROMAN_24; char *str = globalargv[currentTexture]; for(GLuint i=0; i<strlen(str); i++) glutBitmapCharacter(font, str[i]); /* Flush and swap the OpenGL buffers. */ glFlush(); glutSwapBuffers(); glutPostRedisplay(); }