// 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 //////////////////////////////////////////////////////////////////////////////// // // // **************** 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 ) { // 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: "< 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::CameraNode; camera->addChild(loadedModel.get()); osg::ref_ptr traits = new osg::GraphicsContext::Traits; traits->_windowName = "osgcamera"; 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"<