void display() { dgr_update(); dgr_setget("style", &renderStyle, sizeof(int)); // Clear the screen to black, clear the depth buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 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); /* 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. */ for(int viewportID=0; viewportID<viewmat_num_viewports(); 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]); /* Get the frustum information which will be later used to generate a perspective projection matrix. */ float f[6]; // left, right, top, bottom, near>0, far>0 projmat_get_frustum(f, viewport[2], viewport[3]); /* Get the view or camera matrix; update the frustum values if needed. */ float viewMat[16]; viewmat_get(viewMat, f, viewportID); glUseProgram(program); /* Communicate matricies to OpenGL */ float perspective[16]; mat4f_frustum_new(perspective,f[0], f[1], f[2], f[3], f[4], f[5]); glUniformMatrix4fv(kuhl_get_uniform("Projection"), 1, // count 0, // transpose perspective); // value float modelMat[16]; get_model_matrix(modelMat); // modelview = view * model float modelview[16]; mat4f_mult_mat4f_new(modelview, viewMat, modelMat); glUniformMatrix4fv(kuhl_get_uniform("ModelView"), 1, // count 0, // transpose modelview); // value glUniform1i(kuhl_get_uniform("renderStyle"), renderStyle); // Copy far plane value into vertex program so we can render depth buffer. glUniform1f(kuhl_get_uniform("farPlane"), f[5]); kuhl_errorcheck(); kuhl_draw_model_file_ogl3(modelFilename, modelTexturePath, program); kuhl_errorcheck(); glUseProgram(0); // stop using a GLSL program. } // finish viewport loop int time = glutGet(GLUT_ELAPSED_TIME); float fps = kuhl_getfps(time); if(time % 1000 == 0) printf("Frames per second: %0.1f\n", fps); /* Check for errors. If there are errors, consider adding more * calls to kuhl_errorcheck() in your code. */ kuhl_errorcheck(); glFlush(); glFinish(); /* Display the buffer we just drew (necessary for double buffering). */ glutSwapBuffers(); // 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(); }
/* 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(); glClearColor(.2,.2,.2,0); // set clear color to grey // Clear the screen to black, clear the depth buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); // turn on depth testing kuhl_errorcheck(); /* 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. */ for(int viewportID=0; viewportID<viewmat_num_viewports(); 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]); /* Get the frustum information which will be later used to generate a perspective projection matrix. */ float f[6]; // left, right, top, bottom, near>0, far>0 projmat_get_frustum(f, viewport[2], viewport[3]); /* Get the view or camera matrix; update the frustum values if needed. */ float viewMat[16]; viewmat_get(viewMat, f, viewportID); /* Create a 4x4 perspective projection matrix from the frustum values. */ float perspective[16]; mat4f_frustum_new(perspective,f[0], f[1], f[2], f[3], f[4], f[5]); /* Calculate an angle to rotate the * object. glutGet(GLUT_ELAPSED_TIME) is the number of * milliseconds since glutInit() was called. */ int count = glutGet(GLUT_ELAPSED_TIME) % 10000; // get a counter that repeats every 10 seconds float angle = count / 10000.0 * 360; // rotate 360 degrees every 10 seconds /* Make sure all computers/processes use the same angle */ dgr_setget("angle", &angle, sizeof(GLfloat)); /* Create a 4x4 rotation matrix based on the angle we computed. */ float rotateMat[16]; mat4f_rotateAxis_new(rotateMat, angle, 0,1,0); /* Create a scale matrix. */ float scaleMatrix[16]; mat4f_scale_new(scaleMatrix, 3, 3, 3); // Modelview = (viewMatrix * scaleMatrix) * rotationMatrix float modelview[16]; mat4f_mult_mat4f_new(modelview, viewMat, scaleMatrix); mat4f_mult_mat4f_new(modelview, modelview, rotateMat); kuhl_errorcheck(); 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 /* Send the modelview matrix to the vertex program. */ glUniformMatrix4fv(kuhl_get_uniform("ModelView"), 1, // number of 4x4 float matrices 0, // transpose modelview); // value kuhl_errorcheck(); /* Draw the geometry using the matrices that we sent to the * vertex programs immediately above */ kuhl_geometry_draw(&triangle); kuhl_geometry_draw(&quad); glUseProgram(0); // stop using a GLSL program. } // finish viewport loop /* Check for errors. If there are errors, consider adding more * calls to kuhl_errorcheck() in your code. */ kuhl_errorcheck(); /* Display the buffer we just drew (necessary for double buffering). */ glutSwapBuffers(); /* 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(); }
/** Get a 4x4 view matrix. Some types of systems also need to update * the frustum based on where the virtual camera is. For example, on * the IVS display wall, the frustum is adjusted dynamically based on * where a person is relative to the screens. * * @param viewmatrix A 4x4 view matrix for viewmat to fill in. * * @param projmatrix A 4x4 projection matrix for viewmat to fill in. * * @param viewportID If there is only one viewport, set this to * 0. This value must be smaller than the value reported by * viewmat_num_viewports(). In an HMD, typically viewportID=0 is the * left eye and viewportID=1 is the right eye. However, some Oculus * HMDs will result in this being swapped. To definitively know which * eye this view matrix corresponds to, examine the return value of * this function. * * @return A viewmat_eye enum which indicates if this view matrix is * for the left, right, middle, or unknown eye. * */ viewmat_eye viewmat_get(float viewmatrix[16], float projmatrix[16], int viewportID) { viewmat_eye eye = viewmat_viewport_to_eye(viewportID); int viewport[4]; // x,y of lower left corner, width, height viewmat_get_viewport(viewport, viewportID); /* Get the view or camera matrix; update the frustum values if needed. */ float f[6]; // left, right, bottom, top, near>0, far>0 projmat_get_frustum(f, viewport[2], viewport[3], viewportID); /* If we are running in IVS mode and using the tracking systems, * all computers need to update their frustum differently. The * master process will be controlled by VRPN, and all slaves will * have their controllers set to "none". Here, we detect for this * situation and make sure all processes work correctly. */ if(viewmat_display_mode == VIEWMAT_IVS && viewmat_control_mode == VIEWMAT_CONTROL_VRPN) { // Will update view matrix and frustum information viewmat_get_ivs(viewmatrix, f); mat4f_frustum_new(projmatrix, f[0], f[1], f[2], f[3], f[4], f[5]); } else { switch(viewmat_control_mode) { case VIEWMAT_CONTROL_MOUSE: // mouse movement viewmat_get_mouse(viewmatrix, viewportID); mat4f_frustum_new(projmatrix, f[0], f[1], f[2], f[3], f[4], f[5]); break; case VIEWMAT_CONTROL_NONE: // Get the view matrix from the mouse movement code...but // we haven't registered mouse movement callback // functions, so mouse movement won't work. viewmat_get_mouse(viewmatrix, viewportID); mat4f_frustum_new(projmatrix, f[0], f[1], f[2], f[3], f[4], f[5]); break; case VIEWMAT_CONTROL_ORIENT: viewmat_get_orient_sensor(viewmatrix, viewportID); mat4f_frustum_new(projmatrix, f[0], f[1], f[2], f[3], f[4], f[5]); break; case VIEWMAT_CONTROL_OCULUS: viewmat_get_hmd_oculus(viewmatrix, projmatrix, viewportID); // previous function sets projmatrix for us... break; case VIEWMAT_CONTROL_VRPN: viewmat_get_vrpn(viewmatrix, viewportID); mat4f_frustum_new(projmatrix, f[0], f[1], f[2], f[3], f[4], f[5]); break; default: msg(MSG_FATAL, "Unknown viewmat control mode: %d\n", viewmat_control_mode); exit(EXIT_FAILURE); } } /* Send the view matrix to DGR. At some point in the future, we * may have multiple computers using different view matrices. For * now, even in IVS mode, all processes will use the same view * matrix (IVS uses different view frustums per process). */ char dgrkey[128]; snprintf(dgrkey, 128, "!!viewmat%d", viewportID); dgr_setget(dgrkey, viewmatrix, sizeof(float)*16); /* Sanity checks */ viewmat_validate_ipd(viewmatrix, viewportID); return eye; }