Have add new osg::CopyOp which replaces last nights osg::Cloner, the new

class now combines Cloner and DeepCopy into one class. Cloner and DeepCopy
will be removed in next commit.

Also have added osgcopy app to Demos which shows how the CopyOp have be
subclassed to create users own specific handling of copying.

Have fixed copy constructor problems in GeoSet which fix the deep copy
problem experienced yesterday.
This commit is contained in:
Robert Osfield
2002-01-29 12:52:04 +00:00
parent f0174e34a3
commit 2487861fbc
17 changed files with 683 additions and 29 deletions

View File

@@ -1,7 +1,7 @@
#!smake
SHELL=/bin/sh
DIRS = sgv osgconv osgcube osgscribe osgreflect osgtexture osgimpostor osgviews hangglide
DIRS = sgv osgconv osgcube osgscribe osgreflect osgtexture osgimpostor osgviews osgcopy hangglide
# comment out if you don't have the freetype and GLU1.3 library installed.
DIRS += osgtext

View File

View File

@@ -0,0 +1,22 @@
#!smake
include $(OSGHOME)/Make/makedefs
C++FILES = \
osgcopy.cpp
TARGET = $(OSGHOME)/bin/osgcopy
TARGET_BIN_FILES = osgcopy
#note, standard library list.
LIBS = -losgGLUT -losgUtil -losgDB -losg $(GLUTLIB) $(GL_LIBS) $(X_LIBS)
#under Darwin we have to use the framework stuff to get GLUT OpenGL etc.
MACOSXLIBS = -losgGLUT -losgUtil -losgDB -losg -lm -ldl -lstdc++ -lobjc
C++FLAGS += -I$(OSGHOME)/include
LDFLAGS += -L$(OSGHOME)/lib
include $(OSGHOME)/Make/makerules

View File

@@ -0,0 +1,274 @@
#include <osg/Transform>
#include <osg/Billboard>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Notify>
#include <osg/Texture>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/TrackballManipulator>
#include <osgUtil/FlightManipulator>
#include <osgUtil/DriveManipulator>
#include <osgGLUT/glut>
#include <osgGLUT/Viewer>
#include <osgUtil/Optimizer>
void write_usage(std::ostream& out,const std::string& name)
{
out << std::endl;
out <<"usage:"<< std::endl;
out <<" "<<name<<" [options] infile1 [infile2 ...]"<< std::endl;
out << std::endl;
out <<"options:"<< std::endl;
out <<" -l libraryName - load plugin of name libraryName"<< std::endl;
out <<" i.e. -l osgdb_pfb"<< std::endl;
out <<" Useful for loading reader/writers which can load"<< std::endl;
out <<" other file formats in addition to its extension."<< std::endl;
out <<" -e extensionName - load reader/wrter plugin for file extension"<< std::endl;
out <<" i.e. -e pfb"<< std::endl;
out <<" Useful short hand for specifying full library name as"<< std::endl;
out <<" done with -l above, as it automatically expands to"<< std::endl;
out <<" the full library name appropriate for each platform."<< std::endl;
out <<std::endl;
out <<" -stereo - switch on stereo rendering, using the default of,"<< std::endl;
out <<" ANAGLYPHIC or the value set in the OSG_STEREO_MODE "<< std::endl;
out <<" environmental variable. See doc/stereo.html for "<< std::endl;
out <<" further details on setting up accurate stereo "<< std::endl;
out <<" for your system. "<< std::endl;
out <<" -stereo ANAGLYPHIC - switch on anaglyphic(red/cyan) stereo rendering."<< std::endl;
out <<" -stereo QUAD_BUFFER - switch on quad buffered stereo rendering."<< std::endl;
out <<std::endl;
out <<" -stencil - use a visual with stencil buffer enabled, this "<< std::endl;
out <<" also allows the depth complexity statistics mode"<< std::endl;
out <<" to be used (press 'p' three times to cycle to it)."<< std::endl;
out << std::endl;
}
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 Referenced* operator() (const Referenced* ref) const
{
writeIndent(); std::cout << "copying Referenced "<<ref<<std::endl;
moveIn();
osg::Referenced* ret_ref = osg::CopyOp::operator()(ref);
moveOut();
return ret_ref;
}
virtual Object* operator() (const Object* obj) const
{
writeIndent(); std::cout << "copying Object "<<obj;
if (obj) std::cout<<" "<<obj->className();
std::cout<<std::endl;
moveIn();
osg::Object* ret_obj = osg::CopyOp::operator()(obj);
moveOut();
return ret_obj;
}
virtual Node* operator() (const Node* node) const
{
writeIndent(); std::cout << "copying Node "<<node;
if (node) std::cout<<" "<<node->className()<<" '"<<node->getName()<<"'";
std::cout<<std::endl;
moveIn();
osg::Node* ret_node = osg::CopyOp::operator()(node);
moveOut();
return ret_node;
}
virtual Drawable* operator() (const Drawable* drawable) const
{
writeIndent(); std::cout << "copying Drawable "<<drawable;
if (drawable) std::cout<<" "<<drawable->className();
std::cout<<std::endl;
moveIn();
osg::Drawable* ret_drawable = osg::CopyOp::operator()(drawable);
moveOut();
return ret_drawable;
}
virtual StateSet* operator() (const StateSet* stateset) const
{
writeIndent(); std::cout << "copying StateSet "<<stateset;
if (stateset) std::cout<<" "<<stateset->className();
std::cout<<std::endl;
moveIn();
osg::StateSet* ret_stateset = osg::CopyOp::operator()(stateset);
moveOut();
return ret_stateset;
}
virtual StateAttribute* operator() (const StateAttribute* attr) const
{
writeIndent(); std::cout << "copying StateAttribute "<<attr;
if (attr) std::cout<<" "<<attr->className();
std::cout<<std::endl;
moveIn();
osg::StateAttribute* ret_attr = osg::CopyOp::operator()(attr);
moveOut();
return ret_attr;
}
virtual Texture* operator() (const Texture* text) const
{
writeIndent(); std::cout << "copying Texture "<<text;
if (text) std::cout<<" "<<text->className();
std::cout<<std::endl;
moveIn();
osg::Texture* ret_text = osg::CopyOp::operator()(text);
moveOut();
return ret_text;
}
virtual Image* operator() (const Image* image) const
{
writeIndent(); std::cout << "copying Image "<<image;
if (image) std::cout<<" "<<image->className();
std::cout<<std::endl;
moveIn();
Image* ret_image = osg::CopyOp::operator()(image);
moveOut();
return ret_image;
}
protected:
// must be mutable since CopyOp is passed around as const to
// the various clone/copy constructors.
mutable int _indent;
mutable int _step;
};
int main( int argc, char **argv )
{
// initialize the GLUT
glutInit( &argc, argv );
if (argc<2)
{
write_usage(osg::notify(osg::NOTICE),argv[0]);
return 0;
}
// create the commandline args.
std::vector<std::string> commandLine;
for(int i=1;i<argc;++i) commandLine.push_back(argv[i]);
// initialize the viewer.
osgGLUT::Viewer viewer;
// configure the viewer from the commandline arguments, and eat any
// parameters that have been matched.
viewer.readCommandLine(commandLine);
// configure the plugin registry from the commandline arguments, and
// eat any parameters that have been matched.
osgDB::readCommandLine(commandLine);
// load the nodes from the commandline arguments.
osg::Node* rootnode = osgDB::readNodeFiles(commandLine);
if (!rootnode)
{
write_usage(osg::notify(osg::NOTICE),argv[0]);
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<osg::Node*>(rootnode->clone(osg::CopyOp::DEEP_COPY_ALL));
std::cout << "Doing a deep copy of scene graph"<<std::endl;
// note, we need the dyanmic_cast because MS Visual Studio can't handle covarient
// return types, so that clone has return just Object*. bahh hum bug
osg::Node* deep_copy = dynamic_cast<osg::Node*>(rootnode->clone(MyCopyOp(osg::CopyOp::DEEP_COPY_ALL)));
std::cout << "----------------------------------------------------------------"<<std::endl;
// do a shallow copy.
std::cout << "Doing a shallow copy of scene graph"<<std::endl;
osg::Node* shallow_copy = dynamic_cast<osg::Node*>(rootnode->clone(MyCopyOp(osg::CopyOp::SHALLOW_COPY)));
std::cout << std::endl << "Writing out the original scene graph as 'original.osg'"<<endl;
osgDB::writeNodeFile(*rootnode,"original.osg");
std::cout << "Writing out the deep copied scene graph as 'deep_copy.osg'"<<endl;
osgDB::writeNodeFile(*deep_copy,"deep_copy.osg");
std::cout << "Writing out the shallow copied scene graph as 'shallow_copy.osg'"<<endl;
osgDB::writeNodeFile(*shallow_copy,"shallow_copy.osg");
// You can use a bit mask to control which parts of the scene graph are shallow copied
// vs deep copied. The options are (from include/osg/CopyOp) :
// enum Options {
// SHALLOW_COPY = 0,
// DEEP_COPY_OBJECTS = 1,
// DEEP_COPY_NODES = 2,
// DEEP_COPY_DRAWABLES = 4,
// DEEP_COPY_STATESETS = 8,
// DEEP_COPY_STATEATTRIBUTES = 16,
// DEEP_COPY_TEXTURES = 32,
// DEEP_COPY_IMAGES = 64,
// DEEP_COPY_ALL = 0xffffffff
// };
//
// These options you can use together such as :
// osg::Node* mycopy = dynamic_cast<osg::Node*>(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 -------------------------------------------------------
// add a viewport to the viewer and attach the scene graph.
viewer.addViewport( rootnode );
// register trackball, flight and drive.
viewer.registerCameraManipulator(new osgUtil::TrackballManipulator);
viewer.registerCameraManipulator(new osgUtil::FlightManipulator);
viewer.registerCameraManipulator(new osgUtil::DriveManipulator);
// open the viewer window.
viewer.open();
// fire up the event loop.
viewer.run();
return 0;
}

74
src/osg/CopyOp.cpp Normal file
View File

@@ -0,0 +1,74 @@
#include <osg/CopyOp>
#include <osg/Node>
#include <osg/StateSet>
#include <osg/Texture>
#include <osg/Drawable>
using namespace osg;
Referenced* CopyOp::operator() (const Referenced* ref) const
{
return const_cast<Referenced*>(ref);
}
Object* CopyOp::operator() (const Object* obj) const
{
if (obj && _flags&DEEP_COPY_OBJECTS)
return obj->clone(*this);
else return const_cast<Object*>(obj);
}
Node* CopyOp::operator() (const Node* node) const
{
if (node && _flags&DEEP_COPY_NODES)
return dynamic_cast<Node*>(node->clone(*this));
else
return const_cast<Node*>(node);
}
Drawable* CopyOp::operator() (const Drawable* drawable) const
{
if (drawable && _flags&DEEP_COPY_DRAWABLES)
return dynamic_cast<Drawable*>(drawable->clone(*this));
else
return const_cast<Drawable*>(drawable);
}
StateSet* CopyOp::operator() (const StateSet* stateset) const
{
if (stateset && _flags&DEEP_COPY_STATESETS)
return dynamic_cast<StateSet*>(stateset->clone(*this));
else
return const_cast<StateSet*>(stateset);
}
StateAttribute* CopyOp::operator() (const StateAttribute* attr) const
{
if (attr && _flags&DEEP_COPY_STATEATTRIBUTES)
{
const Texture* text = dynamic_cast<const Texture*>(attr);
if (text)
{
return operator()(text);
}
else
return dynamic_cast<StateAttribute*>(attr->clone(*this));
}
else
return const_cast<StateAttribute*>(attr);
}
Texture* CopyOp::operator() (const Texture* text) const
{
if (text && _flags&DEEP_COPY_TEXTURES)
return dynamic_cast<Texture*>(text->clone(*this));
else
return const_cast<Texture*>(text);
}
Image* CopyOp::operator() (const Image* image) const
{
if (image && _flags&DEEP_COPY_IMAGES)
return dynamic_cast<Image*>(image->clone(*this));
else return const_cast<Image*>(image);
}

View File

@@ -66,8 +66,8 @@ GeoSet::GeoSet(const GeoSet& geoset,const Cloner& cloner):
_flat_shaded_skip = geoset._flat_shaded_skip;
if (geoset._primLengths)
{
_primLengths = new int [_primlength];
memcpy(_primLengths,geoset._primLengths,_primlength);
_primLengths = new int [_numprims];
memcpy(_primLengths,geoset._primLengths,_numprims*sizeof(int));
}
else
{
@@ -79,7 +79,7 @@ GeoSet::GeoSet(const GeoSet& geoset,const Cloner& cloner):
if (geoset._coords)
{
_coords = new Vec3 [_numcoords];
memcpy(_coords,geoset._coords,_numcoords);
memcpy(_coords,geoset._coords,_numcoords*sizeof(Vec3));
}
else
{
@@ -92,7 +92,7 @@ GeoSet::GeoSet(const GeoSet& geoset,const Cloner& cloner):
if (geoset._normals)
{
_normals = new Vec3 [_numnormals];
memcpy(_normals,geoset._normals,_numnormals);
memcpy(_normals,geoset._normals,_numnormals*sizeof(Vec3));
}
else
{
@@ -105,7 +105,7 @@ GeoSet::GeoSet(const GeoSet& geoset,const Cloner& cloner):
if (geoset._colors)
{
_colors = new Vec4 [_numcolors];
memcpy(_colors,geoset._colors,_numcolors);
memcpy(_colors,geoset._colors,_numcolors*sizeof(Vec4));
}
else
{
@@ -118,7 +118,7 @@ GeoSet::GeoSet(const GeoSet& geoset,const Cloner& cloner):
if (geoset._tcoords)
{
_tcoords = new Vec2 [_numtcoords];
memcpy(_tcoords,geoset._tcoords,_numtcoords);
memcpy(_tcoords,geoset._tcoords,_numtcoords*sizeof(Vec2));
}
else
{

View File

@@ -18,7 +18,7 @@ Geode::Geode(const Geode& geode,const Cloner& cloner):
++itr)
{
Drawable* drawable = cloner(itr->get());
if (drawable) _drawables.push_back(drawable);
if (drawable) addDrawable(drawable);
}
}

View File

@@ -21,7 +21,7 @@ Group::Group(const Group& group,const Cloner& cloner):
++itr)
{
Node* child = cloner(itr->get());
if (child) _children.push_back(child);
if (child) addChild(child);
}
}

View File

@@ -10,6 +10,7 @@ C++FILES = \
ClipPlane.cpp \
ColorMask.cpp \
ColorMatrix.cpp \
CopyOp.cpp \
CullFace.cpp\
Depth.cpp \
DisplaySettings.cpp\
@@ -75,9 +76,9 @@ TARGET_INCLUDE_FILES = \
osg/ClippingVolume\
osg/ColorMask\
osg/ColorMatrix\
osg/CopyOp\
osg/CullFace\
osg/Depth\
osg/DeepCopy\
osg/DisplaySettings\
osg/Drawable\
osg/EarthSky\
@@ -114,7 +115,6 @@ TARGET_INCLUDE_FILES = \
osg/Plane\
osg/Quat\
osg/Referenced\
osg/ShallowCopy\
osg/State\
osg/StateAttribute\
osg/StateSet\

View File

@@ -27,9 +27,9 @@ Node::Node(const Node& node,const Cloner& cloner):
_name(node._name),
_parents(), // leave empty as parentList is managed by Group.
_appCallback(node._appCallback),
_numChildrenRequiringAppTraversal(node._numChildrenRequiringAppTraversal),
_numChildrenRequiringAppTraversal(0), // assume no children yet.
_cullingActive(node._cullingActive),
_numChildrenWithCullingDisabled(node._numChildrenWithCullingDisabled),
_numChildrenWithCullingDisabled(0), // assume no children yet.
_userData(cloner(node._userData.get())),
_nodeMask(node._nodeMask),
_descriptions(node._descriptions),

View File

@@ -23,11 +23,17 @@ StateSet::StateSet()
StateSet::StateSet(const StateSet& rhs,const Cloner& cloner):Object(rhs,cloner)
{
// shallow copy right now, we should go through each attribute and
// use the cloner instead of attribute list copy.. on the TODO list. Robert. Jan 2002.
_modeList = rhs._modeList;
_attributeList = rhs._attributeList;
for(AttributeList::const_iterator itr=rhs._attributeList.begin();
itr!=rhs._attributeList.end();
++itr)
{
StateAttribute::Type type = itr->first;
const RefAttributePair& rap = itr->second;
StateAttribute* attr = cloner(rap.first.get());
if (attr) _attributeList[type]=RefAttributePair(attr,rap.second);
}
_renderingHint = rhs._renderingHint;