// C++ source file - (C) 2003 Robert Osfield, released under the OSGPL. // // Simple example of use of Producer::RenderSurface to create an OpenGL // graphics window, and OSG for rendering. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(_WIN32) #include #include void renderCamera(osg::Camera* camera) { osg::GraphicsContext* gc = camera->getGraphicsContext(); if (!gc) return; osgUtil::SceneView* sceneView = dynamic_cast(camera->getRenderingCache(0)); if (!sceneView) return; gc->makeCurrent(); sceneView->cull(); sceneView->draw(); gc->swapBuffers(); } void setUpFrameStamp(osg::Camera* camera, osg::FrameStamp* frameStamp, osg::Node* loadedModel) { osgUtil::SceneView* sceneView = dynamic_cast(camera->getRenderingCache(0)); if (!sceneView) return; sceneView->setFrameStamp(frameStamp); sceneView->setSceneData(loadedModel); } int main( int argc, char **argv ) { if (argc<2) { std::cout << argv[0] <<": requires filename argument." << std::endl; return 1; } // load the scene. osg::ref_ptr loadedModel = osgDB::readNodeFile(argv[1]); if (!loadedModel) { std::cout << argv[0] <<": No data loaded." << std::endl; return 1; } // initialize the view to look at the center of the scene graph const osg::BoundingSphere& bs = loadedModel->getBound(); osg::Matrix viewMatrix; viewMatrix.makeLookAt(bs.center()-osg::Vec3(0.0,2.0f*bs.radius(),0.0),bs.center(),osg::Vec3(0.0f,0.0f,1.0f)); osg::ref_ptr viewer = new osgViewer::Viewer; viewer->setUpViewAcrossAllScreens(); viewer->realize(); viewer->getCamera()->setClearColor(osg::Vec4f(0.6f,0.6f,0.8f,1.0f)); osg::ref_ptr frameStamp = new osg::FrameStamp; unsigned int frameNum = 0; osgUtil::UpdateVisitor updateVisitor; updateVisitor.setFrameStamp(frameStamp.get()); setUpFrameStamp(viewer->getCamera(), frameStamp.get(), loadedModel.get()); for(unsigned i=0; igetNumSlaves(); ++i) { osg::View::Slave& slave = viewer->getSlave(i); setUpFrameStamp(slave._camera.get(), frameStamp.get(), loadedModel.get()); } // record the timer tick at the start of rendering. osg::Timer_t start_tick = osg::Timer::instance()->tick(); osg::Timer_t previous_tick = start_tick; while(true) { osg::Timer_t current_tick = osg::Timer::instance()->tick(); frameStamp->setReferenceTime(osg::Timer::instance()->delta_s(start_tick,current_tick)); frameStamp->setFrameNumber(frameNum++); //std::cout<<"Frame rate "<<1.0/osg::Timer::instance()->delta_s(previous_tick,current_tick)<accept(updateVisitor); viewer->getCamera()->setViewMatrix(viewMatrix); viewer->updateSlaves(); if (viewer->getCamera() && viewer->getCamera()->getGraphicsContext()) renderCamera(viewer->getCamera()); for(unsigned i=0; igetNumSlaves(); ++i) { osg::View::Slave& slave = viewer->getSlave(i); if (slave._camera.valid() && slave._camera->getGraphicsContext()) renderCamera(slave._camera.get()); } } } #else ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // ORIGINAL osgcamera example code. //////////////////////////////////////////////////////////////////////////////// // // // **************** THIS IS AN EXPERIMENTAL IMPLEMENTATION *************** // ************************** PLEASE DO NOT COPY ************************ // // /////////////////////////////////////////////////////////////////////////////// // Compile operation, that compile OpenGL objects. struct CompileOperation : public osg::GraphicsThread::Operation { CompileOperation(osg::Node* scene): osg::GraphicsThread::Operation("Compile",false), _scene(scene) { } virtual void operator () (osg::GraphicsContext* context) { std::cout<<"Compile"<getState()); // do the compile traversal _scene->accept(compileVisitor); } osg::ref_ptr _scene; }; // Cull operation, that does a cull on the scene graph. struct CullOperation : public osg::GraphicsThread::Operation { CullOperation(osgUtil::SceneView* sceneView): osg::GraphicsThread::Operation("Cull",true), _sceneView(sceneView) { } virtual void operator () (osg::GraphicsContext* context) { _sceneView->setState(context->getState()); _sceneView->cull(); } osg::ref_ptr _sceneView; }; // Draw operation, that does a draw on the scene graph. struct DrawOperation : public osg::GraphicsThread::Operation { DrawOperation(osgUtil::SceneView* sceneView): osg::GraphicsThread::Operation("Draw",true), _sceneView(sceneView) { } virtual void operator () (osg::GraphicsContext*) { _sceneView->draw(); } osg::ref_ptr _sceneView; }; struct CleanUpOperation : public osg::GraphicsThread::Operation { CleanUpOperation(osgUtil::SceneView* sceneView): osg::GraphicsThread::Operation("CleanUp",false), _sceneView(sceneView) { } virtual void operator () (osg::GraphicsContext*) { _sceneView->releaseAllGLObjects(); _sceneView->flushAllDeletedGLObjects(); } osg::ref_ptr _sceneView; }; // main does the following steps to create a multi-thread, multiple camera/graphics context view of a scene graph. // // 1) load the scene graph // // 2) create a list of camera, each with their own graphis context, with a graphics thread for each context. // // 3) set up the graphic threads so that the do an initial compile OpenGL objects operation, this is done once, and then this compile op is disgarded // // 4) set up the graphics thread so that it has all the graphics ops required for the main loop, these ops are: // 4.a) frame begin barrair, syncronizes all the waiting graphic threads so they don't run while update is occuring // 4.b) frame operation - the cull and draw for each camera // 4.c) frame end barrier, releases the update thread once all graphic threads have dispatched all their OpenGL commands // 4.d) pre swap barrier, barrier which ensures that all graphics threads have sent their data down to the gfx card. // 4.e) swap buffers, do the swap buffers on all the graphics contexts. // // 5. The main loop: // 5.a) update // 5.b) join the frame begin barrrier, releasing all the graphics threads to do their stuff // 5.c) block on the frame end barrier, waiting till all the graphics threads have done their cull/draws. // 5.d) check to see if any of the windows has been closed. // int main( int argc, char **argv ) { osg::Referenced::setThreadSafeReferenceCounting(true); // use an ArgumentParser object to manage the program arguments. osg::ArgumentParser arguments(&argc,argv); std::string windowingLibrary("osgProducer"); while (arguments.read("--windowing",windowingLibrary)) {} // load the osgProducer library manually. osg::ref_ptr windowingLib = osgDB::DynamicLibrary::loadLibrary(osgDB::Registry::instance()->createLibraryNameForNodeKit(windowingLibrary)); if (!windowingLib) { std::cout<<"Error: failed to loading windowing library: "< view = new osgViewer::View; view->setUpViewAcrossAllScreens(); unsigned int numScreens = wsi->getNumScreens(); unsigned int numberCameras = numScreens; while (arguments.read("--cameras",numberCameras)) {} unsigned int xpos = 0; unsigned int ypos = 400; unsigned int width = 400; unsigned int height = 400; while (arguments.read("--xpos",xpos)) {} while (arguments.read("--ypos",ypos)) {} while (arguments.read("--height",height)) {} while (arguments.read("--width",width)) {} unsigned int maxNumFrames = 1000; while (arguments.read("--max-num-frames",maxNumFrames)) {} // load the scene. osg::ref_ptr loadedModel = osgDB::readNodeFiles(arguments); if (!loadedModel) { std::cout << argv[0] <<": No data loaded." << std::endl; return 1; } // set up the frame stamp for current frame to record the current time and frame number so that animtion code can advance correctly osg::ref_ptr frameStamp = new osg::FrameStamp; unsigned int frameNum = 0; osgUtil::UpdateVisitor updateVisitor; updateVisitor.setFrameStamp(frameStamp.get()); typedef std::list< osg::ref_ptr > CameraList; typedef std::set< osg::GraphicsContext* > GraphicsContextSet; CameraList cameraList; GraphicsContextSet graphicsContextSet; // create the cameras, graphic contexts and graphic threads. bool shareContexts = false; osg::GraphicsContext* previousContext = 0; for(unsigned int i=0; i< numberCameras; ++i) { osg::ref_ptr camera = new osg::Camera; camera->addChild(loadedModel.get()); osg::ref_ptr traits = new osg::GraphicsContext::Traits; traits->_windowName = "osgcamera"; traits->_screenNum = i % numScreens; traits->_x = xpos; traits->_y = ypos; traits->_width = width; traits->_height = height; traits->_windowDecoration = true; traits->_doubleBuffer = true; traits->_sharedContext = shareContexts ? previousContext : 0; xpos += width; osg::ref_ptr gfxc = osg::GraphicsContext::createGraphicsContext(traits.get()); if (!gfxc) { std::cout<<"Unable to create window."<setGraphicsContext(gfxc.get()); // initialize the view to look at the center of the scene graph const osg::BoundingSphere& bs = loadedModel->getBound(); osg::Matrix viewMatrix; viewMatrix.makeLookAt(bs.center()-osg::Vec3(0.0,2.0f*bs.radius(),0.0),bs.center(),osg::Vec3(0.0f,0.0f,1.0f)); camera->setViewport(0,0,traits->_width,traits->_height); camera->setProjectionMatrixAsPerspective(50.0f,1.4f,1.0f,10000.0f); camera->setViewMatrix(viewMatrix); // graphics thread will realize the window. gfxc->createGraphicsThread(); cameraList.push_back(camera); previousContext = gfxc.get(); } // build the list of unique graphics contexts. CameraList::iterator citr; for(citr = cameraList.begin(); citr != cameraList.end(); ++citr) { graphicsContextSet.insert(const_cast((*citr)->getGraphicsContext())); } std::cout<<"Number of cameras = "<delta_s(previous_tick,current_tick)<accept(updateVisitor); // dispatch the frame. frameBeginBarrierOp->block(); // wait till the frame is done. frameEndBarrierOp->block(); // check if any of the windows are closed for(gitr = graphicsContextSet.begin(); gitr != graphicsContextSet.end(); ++gitr) { osg::GraphicsContext* context = *gitr; if (!context->isRealized()) done = true; } } std::cout<<"Exiting application"<getGraphicsThread(); if (thread) { thread->removeAllOperations(); thread->setDone(true); } } std::cout<<"Removed all operations"<