#include #include #include #include #include #include #include #include #include #include #include using namespace osg; // Customize the CopyOp so that we add our own verbose // output of what's being copied. class MyCopyOp : public osg::CopyOp { public: inline MyCopyOp(CopyFlags flags=SHALLOW_COPY): osg::CopyOp(flags), _indent(0), _step(4) {} inline void moveIn() const { _indent += _step; } inline void moveOut() const { _indent -= _step; } inline void writeIndent() const { for(int i=0;i<_indent;++i) std::cout << " "; } virtual osg::Referenced* operator() (const osg::Referenced* ref) const { writeIndent(); std::cout << "copying Referenced "<className(); std::cout<className()<<" '"<getName()<<"'"; std::cout<className(); std::cout<className(); std::cout<className(); std::cout<className(); std::cout<className(); std::cout<setDescription(arguments.getApplicationName()+" is the example which demonstrates use of deep vs shallow vs custom copying of scene graphs."); arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ..."); arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information"); // initialize the viewer. osgProducer::Viewer viewer(arguments); // if user request help write it out to cout. if (arguments.read("-h") || arguments.read("--help")) { arguments.getApplicationUsage()->write(std::cout); return 1; } // any option left unread are converted into errors to write out later. arguments.reportRemainingOptionsAsUnrecognized(); // report any errors if they have occured when parsing the program aguments. if (arguments.errors()) { arguments.writeErrorMessages(std::cout); return 1; } if (arguments.argc()<=1) { arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION); return 1; } // load the nodes from the commandline arguments. osg::Node* rootnode = osgDB::readNodeFiles(arguments); if (!rootnode) { return 1; } // run optimization over the scene graph osgUtil::Optimizer optimzer; optimzer.optimize(rootnode); // ------------- Start of copy specific code ------------------------------------------------------- // do a deep copy, using MyCopyOp to reveal whats going on under the good, // in your own code you'd typically just use the basic osg::CopyOp something like // osg::Node* mycopy = dynamic_cast(rootnode->clone(osg::CopyOp::DEEP_COPY_ALL)); std::cout << "Doing a deep copy of scene graph"<(rootnode->clone(MyCopyOp(osg::CopyOp::DEEP_COPY_ALL))); std::cout << "----------------------------------------------------------------"<(rootnode->clone(MyCopyOp(osg::CopyOp::SHALLOW_COPY))); // write out the various scene graphs so that they can be browsed, either // in an editor or using a graphics diff tool gdiff/xdiff/xxdiff. std::cout << std::endl << "Writing out the original scene graph as 'original.osg'"<(rootnode->clone(osg::CopyOp::DEEP_COPY_NODES | DEEP_COPY_DRAWABLES)); // Which shares state but creates copies of all nodes and drawables (which contain the geometry). // // You may also want to subclass from CopyOp to provide finer grained control of what gets shared (shallow copy) vs // cloned (deep copy). // ------------- End of copy specific code ------------------------------------------------------- // set the scene to render viewer.setSceneData(rootnode); // create the windows and run the threads. viewer.realize(); while( !viewer.done() ) { // wait for all cull and draw threads to complete. viewer.sync(); // update the scene by traversing it with the the update visitor which will // call all node update callbacks and animations. viewer.update(); // fire off the cull and draw traversals of the scene. viewer.frame(); } // wait for all cull and draw threads to complete. viewer.sync(); // run a clean up frame to delete all OpenGL objects. viewer.cleanup_frame(); // wait for all the clean up frame to complete. viewer.sync(); return 0; }