void idle(void*) { if (previousPlayButtonStatus == ON) { // it means we should measure the interval between two frames // if it is too tiny, we should slow down the motion performanceCounter.StopCounter(); double actualTimeCostOneFrame = performanceCounter.GetElapsedTime(); // in seconds // time spent on saving the screen in previous time-step should be excluded if (saveFileTimeCost > 0.0) actualTimeCostOneFrame -= saveFileTimeCost; framesIncrementDoublePrecision = actualTimeCostOneFrame * expectedFPS; } // start counter at the beginning of the new round if (playButton == ON) performanceCounter.StartCounter(); if(rewindButton == ON) { currentFrameIndex = 0; currentFrameIndexDoublePrecision = 0.0; for (int i = 0; i < displayer.GetNumSkeletons(); i++) { if (displayer.GetSkeletonMotion(i) != NULL) { Posture * initSkeleton = displayer.GetSkeletonMotion(i)->GetPosture(0); displayer.GetSkeleton(i)->setPosture(*initSkeleton); } } rewindButton = OFF; } // Initialization saveFileTimeCost = -1.0; if(playButton == ON) { if (saveScreenToFile == SAVE_CONTINUOUS) { saveFileTimeCounter.StartCounter(); CreateScreenFilename(SAVE_CONTINUOUS, saveScreenToFileContinuousCount, saveScreenToFileContinuousFilename); saveScreenshot(640, 480, saveScreenToFileContinuousFilename); printf("%s is saved to disk.\n", saveScreenToFileContinuousFilename); saveScreenToFileContinuousCount++; saveFileTimeCounter.StopCounter(); saveFileTimeCost = saveFileTimeCounter.GetElapsedTime(); } if (saveScreenToFile == SAVE_CONTINUOUS) { currentFrameIndexDoublePrecision += 1.0; } else { currentFrameIndexDoublePrecision += framesIncrementDoublePrecision; } currentFrameIndex = (int)currentFrameIndexDoublePrecision; if(currentFrameIndex >= maxFrames) { if (repeatButton == ON) { currentFrameIndex = 0; currentFrameIndexDoublePrecision = 0.0; } else // repeat button is OFF { currentFrameIndex = maxFrames - 1; currentFrameIndexDoublePrecision = currentFrameIndex; playButton = OFF; // important, especially in "recording" mode } } if (currentFrameIndex < 0) { currentFrameIndex = 0; currentFrameIndexDoublePrecision = 0.0; } SetSkeletonsToSpecifiedFrame(currentFrameIndex); frame_slider->value((double) currentFrameIndex + 1); } // if(playButton == ON) if (minusOneButton == ON) if (displayer.GetNumSkeletons() != 0) { currentFrameIndex--; if (currentFrameIndex < 0) currentFrameIndex = 0; frame_slider->value((double) currentFrameIndex + 1); SetSkeletonsToSpecifiedFrame(currentFrameIndex); if (saveScreenToFile == SAVE_CONTINUOUS) { CreateScreenFilename(SAVE_CONTINUOUS, saveScreenToFileContinuousCount, saveScreenToFileContinuousFilename); saveScreenshot(640, 480, saveScreenToFileContinuousFilename); printf("%s is saved to disk.\n", saveScreenToFileContinuousFilename); saveScreenToFileContinuousCount++; } minusOneButton = OFF; } if (plusOneButton == ON) { if (displayer.GetNumSkeletons() != 0) { currentFrameIndex++; if (currentFrameIndex >= maxFrames) currentFrameIndex = maxFrames - 1; frame_slider->value((double) currentFrameIndex + 1); SetSkeletonsToSpecifiedFrame(currentFrameIndex); if (saveScreenToFile == SAVE_CONTINUOUS) { CreateScreenFilename(SAVE_CONTINUOUS, saveScreenToFileContinuousCount, saveScreenToFileContinuousFilename); saveScreenshot(640, 480, saveScreenToFileContinuousFilename); printf("%s is saved to disk.\n", saveScreenToFileContinuousFilename); saveScreenToFileContinuousCount++; } plusOneButton = OFF; } } frame_slider->value((double)(currentFrameIndex + 1)); previousPlayButtonStatus = playButton; // Super important updating glwindow->redraw(); }
int main(int argc, char **argv) { // Initialize form, sliders and buttons form = make_window(); performanceCounter.StartCounter(); // init saveFileTimeCounter.StartCounter(); // init groundPlane_button->value(groundPlane); fog_button->value(useFog); worldAxes_button->value(renderWorldAxes); frame_slider->value(1); if (saveScreenToFile == SAVE_CONTINUOUS) record_button->value(1); // ON else record_button->value(0); // OFF // just do some timing, no special purpose // because the first data is always not trustable according to experience performanceCounter.StopCounter(); performanceCounter.GetElapsedTime(); saveFileTimeCounter.StopCounter(); saveFileTimeCounter.GetElapsedTime(); performanceCounter.StartCounter(); // show form, and do initial draw of model form->show(); glwindow->show(); // glwindow is initialized when the form is built performanceCounter.StopCounter(); if (argc > 2) { char *filename; filename = argv[1]; if(filename != NULL) { //Read skeleton from asf file pSkeleton = new Skeleton(filename, MOCAP_SCALE); //Set the rotations for all bones in their local coordinate system to 0 //Set root position to (0, 0, 0) pSkeleton->setBasePosture(); displayer.LoadSkeleton(pSkeleton); lastSkeleton++; } if (displayer.GetNumSkeletons()) { filename = argv[2]; if(filename != NULL) { //Read motion (.amc) file and create a motion pMotion = new Motion(filename, MOCAP_SCALE,pSkeleton); //set sampled motion for display displayer.LoadMotion(pMotion); lastMotion++; //Tell skeleton to perform the first pose ( first posture ) pSkeleton->setPosture(*(displayer.GetSkeletonMotion(0)->GetPosture(0))); // Set skeleton to perform the first pose ( first posture ) int currentFrames = displayer.GetSkeletonMotion(0)->GetNumFrames(); if (currentFrames > maxFrames) { maxFrames = currentFrames; frame_slider->maximum((double)maxFrames); } frame_slider->maximum((double)maxFrames); currentFrameIndex=0; } // if(filename != NULL) } else printf("Load a skeleton first.\n"); framesIncrementDoublePrecision = 1.0; // Current frame and frame increment playButton = ON; repeatButton = OFF; groundPlane = ON; glwindow->redraw(); } // if (argc > 2) Fl::add_idle(idle); return Fl::run(); }
// the "idle" routine; called periodically by GLUT void idleFunction(void) { cpuLoadCounter.StartCounter(); glutSetWindow(windowID); if (!lockScene) { // determine force in case user is pulling on a vertex if (g_iLeftMouseButton) { if (pulledVertex != -1) { double forceX = (g_vMousePos[0] - dragStartX); double forceY = -(g_vMousePos[1] - dragStartY); double externalForce[3]; camera->CameraVector2WorldVector_OrientationOnly3D( forceX, forceY, 0, externalForce); renderingModalMatrix->ProjectSingleVertex(pulledVertex, externalForce[0], externalForce[1], externalForce[2], fq); for(int i=0; i<r; i++) fq[i] = fqBase[i] + deformableObjectCompliance * fq[i]; } } else { memcpy(fq,fqBase,sizeof(double) * r); } // set the reduced external forces implicitNewmarkDense->SetExternalForces(fq); // integrate the dynamics via implicit Newmark for(int i=0; i<substepsPerTimeStep; i++) { int code = implicitNewmarkDense->DoTimestep(); if (code != 0) { printf("The integrator went unstable. Reduce the timestep, or increase the number of substeps per timestep.\n"); implicitNewmarkDense->ResetToRest(); for(int i=0; i<r; i++) { fqBase[i] = 0; fq[i] = 0; } implicitNewmarkDense->SetExternalForces(fq); explosionFlag = 1; explosionCounter.StartCounter(); break; } /* printf("q =\n"); double * q = implicitNewmarkDense->Getq(); for(int i=0; i<r; i++) printf("%G ", q[i]); printf("\n"); */ } memcpy(q, implicitNewmarkDense->Getq(), sizeof(double) * r); } if (explosionFlag) { explosionCounter.StopCounter(); if (explosionCounter.GetElapsedTime() > 4.0) // the message will appear on screen for 4 seconds explosionFlag = 0; } // compute u=Uq deformableObjectRenderingMeshReduced->Setq(q); deformableObjectRenderingMeshReduced->Compute_uUq(); graphicFrame++; // update title bar information at 4 Hz titleBarCounter.StopCounter(); double elapsedTime = titleBarCounter.GetElapsedTime(); if (elapsedTime >= 1.0 / 4) { titleBarCounter.StartCounter(); fps = graphicFrame / elapsedTime; // update menu bar char windowTitle[4096]; sprintf(windowTitle,"%s | Num modes = %d | %.1f Hz | Deformation CPU Load: %d%%", windowTitleBase, implicitNewmarkDense->GetNumDOFs() , fps, (int)(100 * cpuLoad + 0.5) ); glutSetWindowTitle(windowTitle); graphicFrame = 0; if (syncTimeStepWithGraphics) { timeStep = 1.0 / fps; implicitNewmarkDense->SetTimestep(timeStep / substepsPerTimeStep); Sync_GLUI(); } } cpuLoadCounter.StopCounter(); double cpuTimePerGraphicsFrame = cpuLoadCounter.GetElapsedTime(); cpuLoad = cpuTimePerGraphicsFrame * fps; glutPostRedisplay(); }