/** A callback function that will get called whenever the tracker * provides us with new data. This may be called repeatedly for each * record that we have missed if many records have been delivered * since the last call to the VRPN mainloop() function. */ static void VRPN_CALLBACK handle_tracker(void *name, vrpn_TRACKERCB t) { float fps = kuhl_getfps(&fps_state); if(fps_state.frame == 0) msg(INFO, "VRPN records per second: %.1f\n", fps); /* Some tracking systems return large values when a point gets * lost. If the tracked point seems to be lost, ignore this * update. */ float pos[3]; vec3f_set(pos, t.pos[0], t.pos[1], t.pos[2]); long microseconds = (t.msg_time.tv_sec* 1000000L) + t.msg_time.tv_usec; if(0) { printf("Current time %ld; VRPN record time: %ld\n", kuhl_microseconds(), microseconds); printf("Received position from vrpn: "); vec3f_print(pos); } if(vec3f_norm(pos) > 100) return; // Store the data in our map so that someone can use it later. std::string s = (char*)name; nameToCallbackData[s] = t; smooth(nameToCallbackData[s]); }
/** Performs a sanity check on the IPD to ensure that it is not too small, big, or reversed. @param viewmatrix View matrix for the viewportID @param viewportID The viewportID for this particular view matrix. */ static void viewmat_validate_ipd(float viewmatrix[16], int viewportID) { // First, if viewportID=0, save the matrix so we can do the check when we are called with viewportID=1. static float viewmatrix0[16]; static long viewmatrix0time; if(viewportID == 0) { mat4f_copy(viewmatrix0, viewmatrix); viewmatrix0time = kuhl_microseconds(); return; } // If rendering viewportID == 1, and if there are two viewports, // assume that we are running in a stereoscopic configuration and // validate the IPD value. if(viewportID == 1 && viewports_size == 2) { float flip = 1; /* In most cases, viewportID=0 is the left eye. However, * Oculus may cause this to get swapped. */ if(viewmat_viewport_to_eye(0) == VIEWMAT_EYE_RIGHT) flip = -1; // Get the position matrix information float pos1[4], pos2[4]; mat4f_getColumn(pos1, viewmatrix0, 3); // get last column mat4f_getColumn(pos2, viewmatrix, 3); // get last column // Get a vector between the eyes float diff[4]; vec4f_sub_new(diff, pos1, pos2); vec4f_scalarMult_new(diff, diff, flip); // flip vector if necessary /* This message may be triggered if a person is moving quickly * and/or when the FPS is low. This happens because the * position/orientation of the head changed between the * rendering of the left and right eyes. */ float ipd = diff[0]; long delay = kuhl_microseconds() - viewmatrix0time; if(ipd > .07 || ipd < .05) { msg(MSG_WARNING, "IPD=%.4f meters, delay=%ld us (IPD validation failed; occasional messages are OK!)\n", ipd, delay); } // msg(MSG_INFO, "IPD=%.4f meters, delay=%ld us\n", ipd, delay); } }
/** Performs a sanity check on how long it took us to render a * frame. At 60fps, we have approximately 16 milliseconds or 16000 * microseconds per frame. If the time between two subsequent * renderings of viewportID 0 is too large, a warning message is * printed. * * Even though the average FPS over a period of time may be above 60, * the rendering might not appear smooth if an occasional frame misses * the time budget. */ static void viewmat_validate_fps(void) { /* Set the time budget. If vblank syncing is turned on, we'd * expect to always get a FPS close to the monitor. Setting this * to 55 (instead of 60) will prevent messages from getting * printed out constantly on such machines. */ #define targetFps 55 // older compilers won't let us use a static const variable to calculate another static const variable. static const int timeBudget = 1000000.0f / targetFps; /* Initialize our warning message counter and the time that the * last frame was rendered. */ static int warnMsgCount = 0; static long lastTime = -1; if(lastTime < 0) // if our first time called, initialize time and return. { lastTime = kuhl_microseconds(); return; } /* If it took too long to render the frame, print a message. */ long delay = kuhl_microseconds() - lastTime; // msg(MSG_INFO, "Time to render frame %d\n", delay); if(delay > timeBudget) { warnMsgCount++; /* Don't print the message if the first few frames took too * long to render. Also, eventually stop printing the * message. */ if(warnMsgCount > 5 && warnMsgCount <= 100) msg(MSG_WARNING, "It took %ld microseconds to render a frame. Time budget for %d fps is %d microseconds.\n", delay, targetFps, timeBudget); if(warnMsgCount == 100) msg(MSG_WARNING, "That was your last warning about the time budget per frame.\n"); } lastTime = kuhl_microseconds(); }