From 4c5eb02ec59fdb9c355a0ae5c12901c9a03570d9 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 9 Feb 2007 14:54:54 +0000 Subject: [PATCH] From Yefei He, " I wrote a class derived from CopyOp that preserves the multi-parent structure of scene graphs. I only considered the case of DEEP_COPY_NODES, but it is sufficient for me. It is not the most elegant way -- I used a map to list all the already cloned nodes with multiple parents, to be looked up whenever such a node is revisited. The good part is, it works." From Robert Osfield, fixed build problems under Linux 64 due to use of int's to store Node* in internal maps used in above custom CopyOp. Added ref_ptr<> usage to main to prevent memory leaks --- examples/osgcopy/osgcopy.cpp | 61 ++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/examples/osgcopy/osgcopy.cpp b/examples/osgcopy/osgcopy.cpp index 1b5eaa56a..a21f44b9f 100644 --- a/examples/osgcopy/osgcopy.cpp +++ b/examples/osgcopy/osgcopy.cpp @@ -127,6 +127,50 @@ class MyCopyOp : public osg::CopyOp mutable int _step; }; +// this CopyOp class will preserve the multi-parent structure of the copied +// object, instead of expanding it into a tree. Works with the +// DEEP_COPY_NODES flag. +class GraphCopyOp : public osg::CopyOp +{ + public: + + inline GraphCopyOp(CopyFlags flags=SHALLOW_COPY): + osg::CopyOp(flags) { _nodeCopyMap.clear();} + + virtual osg::Node* operator() (const osg::Node* node) const + { + if (node && _flags&DEEP_COPY_NODES) + { + if ( node->getNumParents() > 1 ) + { + if ( _nodeCopyMap.find(node) != _nodeCopyMap.end() ) + { + std::cout<<"Copy of node "<getName()<<", " + << _nodeCopyMap[node]<<", will be reused"<( node->clone(*this) ); + _nodeCopyMap[node] = newNode; + return newNode; + } + } + else + return dynamic_cast( node->clone(*this) ); + } + else + return const_cast(node); + } + + protected: + + // must be mutable since CopyOp is passed around as const to + // the various clone/copy constructors. + mutable std::map _nodeCopyMap; + +}; + int main( int argc, char **argv ) { // use an ArgumentParser object to manage the program arguments. @@ -151,17 +195,23 @@ int main( int argc, char **argv ) // 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)); + osg::ref_ptr 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))); + osg::ref_ptr deep_copy = dynamic_cast(rootnode->clone(MyCopyOp(osg::CopyOp::DEEP_COPY_ALL))); std::cout << "----------------------------------------------------------------"< graph_copy = dynamic_cast(rootnode->clone(GraphCopyOp(osg::CopyOp::DEEP_COPY_NODES))); + + // do a shallow copy. std::cout << "Doing a shallow copy of scene graph"<(rootnode->clone(MyCopyOp(osg::CopyOp::SHALLOW_COPY))); + osg::ref_ptr shallow_copy = dynamic_cast(rootnode->clone(MyCopyOp(osg::CopyOp::SHALLOW_COPY))); // write out the various scene graphs so that they can be browsed, either @@ -169,6 +219,9 @@ int main( int argc, char **argv ) std::cout << std::endl << "Writing out the original scene graph as 'original.osg'"<