/** Get a view matrix from VRPN and adjust the view frustum * appropriately. * @param viewmatrix The location where the viewmatrix should be stored. * @param frustum The location of the view frustum that should be adjusted. */ static void viewmat_get_ivs(float viewmatrix[16], float frustum[6]) { /* Only get information from VRPN if we are DGR master, or if DGR * is being used at all. */ float pos[3]; if((dgr_is_enabled() && dgr_is_master()) || dgr_is_enabled()==0) { if(viewmat_control_mode == VIEWMAT_CONTROL_VRPN && viewmat_vrpn_obj != NULL) { /* get information from vrpn */ float orient[16]; vrpn_get(viewmat_vrpn_obj, NULL, pos, orient); } else { /* If no head tracking is available, assume the person is * standing at the origin with a normal eye height */ pos[0] = 0; pos[1] = 1.5; // normal eye height pos[2] = 0; } } /* Make sure all DGR hosts can get the position so that they * can update the frustum appropriately */ dgr_setget("!!viewMatPos", pos, sizeof(float)*3); /* Update view frustum if it was provided. */ if(frustum != NULL) { frustum[0] -= pos[0]; frustum[1] -= pos[0]; frustum[2] -= pos[1]; frustum[3] -= pos[1]; frustum[4] += pos[2]; frustum[5] += pos[2]; } /* calculate a lookat point */ float lookat[3]; float forwardVec[3] = { 0, 0, -1 }; for(int i=0; i<3; i++) lookat[i] = pos[i]+forwardVec[i]; float up[3] = {0, 1, 0}; mat4f_lookatVec_new(viewmatrix, pos, lookat, up); }
void display() { /* If we are using DGR, send or receive data to keep multiple * processes/computers synchronized. */ dgr_update(); /* Get current frames per second calculations. */ float fps = kuhl_getfps(&fps_state); if(dgr_is_enabled() == 0 || dgr_is_master()) { // If DGR is being used, only display dgr counter if we are // the master process. // Check if FPS value was just updated by kuhl_getfps() if(fps_state.frame == 0) { char label[1024]; snprintf(label, 1024, "FPS: %0.1f", fps); /* Delete old label if it exists */ if(fpsLabel != 0) glDeleteTextures(1, &fpsLabel); /* Make a new label */ float labelColor[3] = { 1,1,1 }; float labelBg[4] = { 0,0,0,.3 }; /* Change the last parameter (point size) to adjust the * size of the texture that the text is rendered in to. */ fpsLabelAspectRatio = kuhl_make_label(label, &fpsLabel, labelColor, labelBg, 24); if(fpsLabel != 0) kuhl_geometry_texture(&labelQuad, fpsLabel, "tex", 1); } } /* Ensure the slaves use the same render style as the master * process. */ dgr_setget("style", &renderStyle, sizeof(int)); /* Render the scene once for each viewport. Frequently one * viewport will fill the entire screen. However, this loop will * run twice for HMDs (once for the left eye and once for the * right. */ viewmat_begin_frame(); for(int viewportID=0; viewportID<viewmat_num_viewports(); viewportID++) { viewmat_begin_eye(viewportID); /* Where is the viewport that we are drawing onto and what is its size? */ int viewport[4]; // x,y of lower left corner, width, height viewmat_get_viewport(viewport, viewportID); glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); /* Clear the current viewport. Without glScissor(), glClear() * clears the entire screen. We could call glClear() before * this viewport loop---but on order for all variations of * this code to work (Oculus support, etc), we can only draw * after viewmat_begin_eye(). */ glScissor(viewport[0], viewport[1], viewport[2], viewport[3]); glEnable(GL_SCISSOR_TEST); glClearColor(.2,.2,.2,0); // set clear color to grey glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); glEnable(GL_DEPTH_TEST); // turn on depth testing kuhl_errorcheck(); /* Turn on blending (note, if you are using transparent textures, the transparency may not look correct unless you draw further items before closer items.). */ glEnable(GL_BLEND); glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); /* Get the view or camera matrix; update the frustum values if needed. */ float viewMat[16], perspective[16]; viewmat_get(viewMat, perspective, viewportID); glUseProgram(program); kuhl_errorcheck(); /* Send the perspective projection matrix to the vertex program. */ glUniformMatrix4fv(kuhl_get_uniform("Projection"), 1, // number of 4x4 float matrices 0, // transpose perspective); // value float modelMat[16]; get_model_matrix(modelMat); float modelview[16]; mat4f_mult_mat4f_new(modelview, viewMat, modelMat); // modelview = view * model /* Send the modelview matrix to the vertex program. */ glUniformMatrix4fv(kuhl_get_uniform("ModelView"), 1, // number of 4x4 float matrices 0, // transpose modelview); // value glUniform1i(kuhl_get_uniform("renderStyle"), renderStyle); // Copy far plane value into vertex program so we can render depth buffer. float f[6]; // left, right, bottom, top, near>0, far>0 projmat_get_frustum(f, viewport[2], viewport[3]); glUniform1f(kuhl_get_uniform("farPlane"), f[5]); kuhl_errorcheck(); kuhl_geometry_draw(modelgeom); /* Draw the model */ kuhl_errorcheck(); if(showOrigin) { /* Save current line width */ GLfloat origLineWidth; glGetFloatv(GL_LINE_WIDTH, &origLineWidth); glLineWidth(4); // make lines thick /* Object coordinate system origin */ kuhl_geometry_draw(origingeom); /* Draw the origin marker */ /* World coordinate origin */ mat4f_copy(modelview, viewMat); glUniformMatrix4fv(kuhl_get_uniform("ModelView"), 1, // number of 4x4 float matrices 0, // transpose modelview); // value kuhl_geometry_draw(origingeom); /* Draw the origin marker */ /* Restore line width */ glLineWidth(origLineWidth); } if(dgr_is_enabled() == 0 || dgr_is_master()) { /* The shape of the frames per second quad depends on the * aspect ratio of the label texture and the aspect ratio of * the window (because we are placing the quad in normalized * device coordinates). */ int windowWidth, windowHeight; viewmat_window_size(&windowWidth, &windowHeight); float windowAspect = windowWidth / (float)windowHeight; float stretchLabel[16]; mat4f_scale_new(stretchLabel, 1/8.0 * fpsLabelAspectRatio / windowAspect, 1/8.0, 1); /* Position label in the upper left corner of the screen */ float transLabel[16]; mat4f_translate_new(transLabel, -.9, .8, 0); mat4f_mult_mat4f_new(modelview, transLabel, stretchLabel); glUniformMatrix4fv(kuhl_get_uniform("ModelView"), 1, 0, modelview); /* Make sure we don't use a projection matrix */ float identity[16]; mat4f_identity(identity); glUniformMatrix4fv(kuhl_get_uniform("Projection"), 1, 0, identity); /* Don't use depth testing and make sure we use the texture * rendering style */ glDisable(GL_DEPTH_TEST); glUniform1i(kuhl_get_uniform("renderStyle"), 1); kuhl_geometry_draw(&labelQuad); /* Draw the quad */ glEnable(GL_DEPTH_TEST); kuhl_errorcheck(); } glUseProgram(0); // stop using a GLSL program. } // finish viewport loop viewmat_end_frame(); /* Update the model for the next frame based on the time. We * convert the time to seconds and then use mod to cause the * animation to repeat. */ int time = glutGet(GLUT_ELAPSED_TIME); dgr_setget("time", &time, sizeof(int)); kuhl_update_model(modelgeom, 0, ((time%10000)/1000.0)); /* Check for errors. If there are errors, consider adding more * calls to kuhl_errorcheck() in your code. */ kuhl_errorcheck(); //kuhl_video_record("videoout", 30); /* Ask GLUT to call display() again. We shouldn't call display() * ourselves recursively because it will not leave time for GLUT * to call other callback functions for when a key is pressed, the * window is resized, etc. */ glutPostRedisplay(); }
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 }
/** Called by GLUT whenever the window needs to be redrawn. This * function should not be called directly by the programmer. Instead, * we can call glutPostRedisplay() to request that GLUT call display() * at some point. */ void display() { /* If we are using DGR, send or receive data to keep multiple * processes/computers synchronized. */ dgr_update(); /* Get current frames per second calculations. */ float fps = kuhl_getfps(&fps_state); if(dgr_is_enabled() == 0 || dgr_is_master()) { // If DGR is being used, only display dgr counter if we are // the master process. // Check if FPS value was just updated by kuhl_getfps() if(fps_state.frame == 0) msg(INFO, "FPS: %0.1f", fps); } /* Render the scene once for each viewport. Frequently one * viewport will fill the entire screen. However, this loop will * run twice for HMDs (once for the left eye and once for the * right. */ viewmat_begin_frame(); for(int viewportID=0; viewportID<viewmat_num_viewports(); viewportID++) { viewmat_begin_eye(viewportID); /* Where is the viewport that we are drawing onto and what is its size? */ int viewport[4]; // x,y of lower left corner, width, height viewmat_get_viewport(viewport, viewportID); glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); /* Clear the current viewport. Without glScissor(), glClear() * clears the entire screen. We could call glClear() before * this viewport loop---but on order for all variations of * this code to work (Oculus support, etc), we can only draw * after viewmat_begin_eye(). */ glScissor(viewport[0], viewport[1], viewport[2], viewport[3]); glEnable(GL_SCISSOR_TEST); glClearColor(.2,.2,.2,0); // set clear color to grey glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); glEnable(GL_DEPTH_TEST); // turn on depth testing kuhl_errorcheck(); /* Turn on blending (note, if you are using transparent textures, the transparency may not look correct unless you draw further items before closer items.). */ glEnable(GL_BLEND); glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); /* Get the view or camera matrix; update the frustum values if needed. */ float viewMat[16], perspective[16]; viewmat_get(viewMat, perspective, viewportID); glUseProgram(program); kuhl_errorcheck(); /* Send the perspective projection matrix to the vertex program. */ glUniformMatrix4fv(kuhl_get_uniform("Projection"), 1, // number of 4x4 float matrices 0, // transpose perspective); // value for(int i=1; i<global_argc; i++) drawObject(i, viewMat); glUseProgram(0); // stop using a GLSL program. } // finish viewport loop viewmat_end_frame(); /* Update the model for the next frame based on the time. We * convert the time to seconds and then use mod to cause the * animation to repeat. */ int time = glutGet(GLUT_ELAPSED_TIME); dgr_setget("time", &time, sizeof(int)); kuhl_update_model(modelgeom, 0, ((time%10000)/1000.0)); /* Check for errors. If there are errors, consider adding more * calls to kuhl_errorcheck() in your code. */ kuhl_errorcheck(); //kuhl_video_record("videoout", 30); /* Ask GLUT to call display() again. We shouldn't call display() * ourselves recursively because it will not leave time for GLUT * to call other callback functions for when a key is pressed, the * window is resized, etc. */ glutPostRedisplay(); }