void VideoViewer::videoFrameCallback(const Video::FrameBuffer* frameBuffer) { double timeStamp=saveVideoTimer.peekTime(); /* Start a new value in the input triple buffer: */ Images::RGBImage& image=videoFrames.startNewValue(); /* Extract an RGB image from the provided frame buffer into the new value: */ videoExtractor->extractRGB(frameBuffer,image.modifyPixels()); /* Finish the new value in the triple buffer and wake up the main loop: */ videoFrames.postNewValue(); Vrui::requestUpdate(); if(saveVideoFrames) { /* Create a filename for the new video frame: */ char videoFrameFileName[1024]; snprintf(videoFrameFileName,sizeof(videoFrameFileName),saveVideoFrameNameTemplate.c_str(),saveVideoNextFrameIndex); /* Save the new video frame: */ Images::writeImageFile(image,videoFrameFileName); std::cout<<"Saving frame "<<videoFrameFileName<<" at "<<timeStamp*1000.0<<" ms"<<std::endl; /* Increment the frame counter: */ ++saveVideoNextFrameIndex; } }
int main(int argc,char* argv[]) { /* Parse the command line: */ SharedJelloServer::Index numAtoms(4,4,8); SharedJelloServer::Box domain(SharedJelloServer::Box::Point(-60.0,-36.0,0.0),SharedJelloServer::Box::Point(60.0,60.0,96.0)); int listenPortID=-1; // Assign any free port double updateTime=0.02; // Aim for 50 updates/sec for(int i=1;i<argc;++i) { if(argv[i][0]=='-') { if(strcasecmp(argv[i]+1,"numAtoms")==0) { /* Read the number of atoms: */ ++i; for(int j=0;j<3&&i<argc;++j,++i) numAtoms[j]=atoi(argv[i]); } else if(strcasecmp(argv[i]+1,"domain")==0) { /* Read the simulation domain: */ ++i; for(int j=0;j<3&&i<argc;++j,++i) domain.min[j]=SharedJelloServer::Box::Scalar(atof(argv[i])); for(int j=0;j<3&&i<argc;++j,++i) domain.max[j]=SharedJelloServer::Box::Scalar(atof(argv[i])); } else if(strcasecmp(argv[i]+1,"port")==0) { /* Read the server listening port: */ ++i; if(i<argc) listenPortID=atoi(argv[i]); } else if(strcasecmp(argv[i]+1,"tick")==0) { /* Read the server update time interval: */ ++i; if(i<argc) updateTime=atof(argv[i]); } } } /* Ignore SIGPIPE and leave handling of pipe errors to TCP sockets: */ struct sigaction sigPipeAction; sigPipeAction.sa_handler=SIG_IGN; sigemptyset(&sigPipeAction.sa_mask); sigPipeAction.sa_flags=0x0; sigaction(SIGPIPE,&sigPipeAction,0); /* Create a shared Jell-O server: */ SharedJelloServer sjs(numAtoms,domain,listenPortID); std::cout<<"SharedJelloServer::main: Created Jell-O server listening on port "<<sjs.getListenPortID()<<std::endl<<std::flush; /* Run the simulation loop full speed: */ Misc::Timer timer; double lastFrameTime=timer.peekTime(); double nextUpdateTime=timer.peekTime()+updateTime; int numFrames=0; while(true) { /* Calculate the current time step duration: */ double newFrameTime=timer.peekTime(); double timeStep=newFrameTime-lastFrameTime; lastFrameTime=newFrameTime; /* Perform a simulation step: */ sjs.simulate(timeStep); ++numFrames; /* Check if it's time for a state update: */ if(lastFrameTime>=nextUpdateTime) { /* Send a state update to all connected clients: */ sjs.sendServerUpdate(); // std::cout<<"\rFrame rate: "<<double(numFrames)/updateTime<<" fps"<<std::flush; nextUpdateTime+=updateTime; numFrames=0; } } return 0; }
void* ClusterJello::simulationThreadMethodMaster(void) { /* Enable immediate cancellation of this thread: */ Threads::Thread::setCancelState(Threads::Thread::CANCEL_ENABLE); Threads::Thread::setCancelType(Threads::Thread::CANCEL_ASYNCHRONOUS); /* Simulate the crystal state until interrupted: */ Misc::Timer timer; double lastFrameTime=timer.peekTime(); double nextUpdateTime=timer.peekTime()+updateTime; while(true) { /* Calculate the current time step duration: */ double newFrameTime=timer.peekTime(); double timeStep=newFrameTime-lastFrameTime; lastFrameTime=newFrameTime; /* Check if the simulation parameters have been changed: */ if(simulationParameters.hasNewValue()) { /* Update the Jell-O crystal's simulation parameters: */ const SimulationParameters& sp=simulationParameters.lockNewValue(); crystal->setAtomMass(sp.atomMass); crystal->setAttenuation(sp.attenuation); crystal->setGravity(sp.gravity); } /* Check if the application has delivered new dragger states: */ if(draggerStates.hasNewValue()) { /* Process the new dragger states: */ const DraggerStates& ds=draggerStates.lockNewValue(); for(int draggerIndex=0;draggerIndex<ds.numDraggers;++draggerIndex) { if(ds.draggerActives[draggerIndex]) { /* Check if this dragger has just become active: */ if(!atomLocks.isEntry(ds.draggerIDs[draggerIndex])) { /* Find the atom picked by the dragger: */ AtomLock al; if(ds.draggerRayBaseds[draggerIndex]) al.draggedAtom=crystal->pickAtom(ds.draggerRays[draggerIndex]); else al.draggedAtom=crystal->pickAtom(ds.draggerTransformations[draggerIndex].getOrigin()); /* Try locking the atom: */ if(crystal->lockAtom(al.draggedAtom)) { /* Calculate the dragging transformation: */ al.dragTransformation=ds.draggerTransformations[draggerIndex]; al.dragTransformation.doInvert(); al.dragTransformation*=crystal->getAtomState(al.draggedAtom); /* Store the atom lock in the hash table: */ atomLocks.setEntry(AtomLockHasher::Entry(ds.draggerIDs[draggerIndex],al)); } } /* Check if the dragger has an atom lock: */ AtomLockHasher::Iterator alIt=atomLocks.findEntry(ds.draggerIDs[draggerIndex]); if(!alIt.isFinished()) { /* Set the position/orientation of the locked atom: */ ONTransform transform=ds.draggerTransformations[draggerIndex]; transform*=alIt->getDest().dragTransformation; crystal->setAtomState(alIt->getDest().draggedAtom,transform); } } else { /* Check if this dragger has just become inactive: */ AtomLockHasher::Iterator alIt=atomLocks.findEntry(ds.draggerIDs[draggerIndex]); if(!alIt.isFinished()) { /* Release the atom lock: */ crystal->unlockAtom(alIt->getDest().draggedAtom); atomLocks.removeEntry(alIt); } } } } /* Advance the simulation time by the last frame time: */ crystal->simulate(timeStep); /* Update the application's Jell-O state if the update interval is over: */ if(lastFrameTime>=nextUpdateTime) { if(clusterPipe!=0) { /* Broadcast the crystal state to all slave nodes: */ crystal->writeAtomStates(*clusterPipe); clusterPipe->finishMessage(); } /* Update the application's proxy crystal state: */ JelloCrystal& pc=proxyCrystal.startWrite(); pc.copyAtomStates(*crystal); proxyCrystal.finishWrite(); Vrui::requestUpdate(); /* Start the next update interval: */ nextUpdateTime+=updateTime; } } return 0; }