diff --git a/include/osgDB/Input b/include/osgDB/Input index 74f4b05b9..ecbfa9540 100644 --- a/include/osgDB/Input +++ b/include/osgDB/Input @@ -26,6 +26,8 @@ namespace osgDB { +struct basic_type_wrapper; + /** Class for managing the reading of ASCII .osg files.*/ class OSGDB_EXPORT Input : public FieldReaderIterator { @@ -35,6 +37,7 @@ class OSGDB_EXPORT Input : public FieldReaderIterator virtual ~Input(); virtual osg::Object* readObjectOfType(const osg::Object& compObj); + virtual osg::Object* readObjectOfType(const basic_type_wrapper &btw); virtual osg::Object* readObject(); virtual osg::Image* readImage(); diff --git a/include/osgDB/Registry b/include/osgDB/Registry index b28f0f2f9..553c27acd 100644 --- a/include/osgDB/Registry +++ b/include/osgDB/Registry @@ -29,6 +29,24 @@ namespace osgDB { +/** basic structure for custom runtime inheritance checking */ +struct basic_type_wrapper { + virtual bool matches(const osg::Object *proto) const = 0; +}; + +/** a class template that checks inheritance between a given + Object's class and a class defined at compile time through + the template parameter T. + This is used in conjunction with readObjectOfType() to + specify an abstract class as reference type. +**/ +template +struct type_wrapper: basic_type_wrapper { + bool matches(const osg::Object *proto) const + { + return dynamic_cast(proto) != 0; + } +}; /** list of directories to search through which searching for files. */ typedef std::deque FilePathList; @@ -84,7 +102,8 @@ class OSGDB_EXPORT Registry : public osg::Referenced /** get a reader writer which handles specified extension.*/ ReaderWriter* getReaderWriterForExtension(const std::string& ext); - osg::Object* readObjectOfType(const osg::Object& compObj,Input& fr); + osg::Object* readObjectOfType(const osg::Object& compObj,Input& fr); + osg::Object* readObjectOfType(const basic_type_wrapper &btw, Input& fr); osg::Object* readObject(Input& fr); osg::Image* readImage(Input& fr); diff --git a/src/osgDB/Input.cpp b/src/osgDB/Input.cpp index 56e56c35e..7021226c6 100644 --- a/src/osgDB/Input.cpp +++ b/src/osgDB/Input.cpp @@ -47,6 +47,11 @@ osg::Object* Input::readObjectOfType(const osg::Object& compObj) return Registry::instance()->readObjectOfType(compObj,*this); } +osg::Object* Input::readObjectOfType(const basic_type_wrapper &btw) +{ + return Registry::instance()->readObjectOfType(btw,*this); +} + osg::Object* Input::readObject() { return Registry::instance()->readObject(*this); diff --git a/src/osgDB/Registry.cpp b/src/osgDB/Registry.cpp index 9a4a51311..4695bb0ea 100644 --- a/src/osgDB/Registry.cpp +++ b/src/osgDB/Registry.cpp @@ -566,6 +566,20 @@ ReaderWriter* Registry::getReaderWriterForExtension(const std::string& ext) osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr) +{ + struct concrete_wrapper: basic_type_wrapper { + concrete_wrapper(const osg::Object *myobj) : myobj_(myobj) {} + bool matches(const osg::Object *proto) const + { + return myobj_->isSameKindAs(proto); + } + const osg::Object *myobj_; + }; + + return readObjectOfType(concrete_wrapper(&compObj), fr); +} + +osg::Object* Registry::readObjectOfType(const basic_type_wrapper &btw,Input& fr) { const char *str = fr[0].getStr(); if (str==NULL) return NULL; @@ -575,7 +589,7 @@ osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr) if (fr[1].isString()) { Object* obj = fr.getObjectForUniqueID(fr[1].getStr()); - if (obj && compObj.isSameKindAs(obj)) + if (obj && btw.matches(obj)) { fr+=2; return obj; @@ -602,11 +616,11 @@ osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr) // first try the standard nodekit library. std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName); - if (loadLibrary(nodeKitLibraryName)) return readObjectOfType(compObj,fr); + if (loadLibrary(nodeKitLibraryName)) return readObjectOfType(btw,fr); // otherwise try the osgdb_ plugin library. std::string pluginLibraryName = createLibraryNameForExtension(libraryName); - if (loadLibrary(pluginLibraryName)) return readObjectOfType(compObj,fr); + if (loadLibrary(pluginLibraryName)) return readObjectOfType(btw,fr); } } else if (fr[1].isOpenBracket()) @@ -620,7 +634,7 @@ osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr) return NULL; } - if (!compObj.isSameKindAs(proto)) + if (!btw.matches(proto)) { return NULL; } @@ -672,6 +686,7 @@ osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr) } + // // read object from input iterator. // diff --git a/src/osgPlugins/3dc/ReaderWriter3DC.cpp b/src/osgPlugins/3dc/ReaderWriter3DC.cpp index 98d74cc79..bae952f1c 100644 --- a/src/osgPlugins/3dc/ReaderWriter3DC.cpp +++ b/src/osgPlugins/3dc/ReaderWriter3DC.cpp @@ -100,7 +100,8 @@ class ReaderWriter3DC : public osgDB::ReaderWriter if (vertices->size()>=targetNumVertices) { // finishing setting up the current geometry and add it to the geode. - geometry->setUseDisplayList(false); + geometry->setUseDisplayList(true); + geometry->setUseVertexBufferObjects(true); geometry->setVertexArray(vertices); geometry->setNormalArray(normals); geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); @@ -133,7 +134,8 @@ class ReaderWriter3DC : public osgDB::ReaderWriter } - geometry->setUseDisplayList(false); + geometry->setUseDisplayList(true); + geometry->setUseVertexBufferObjects(true); geometry->setVertexArray(vertices); geometry->setNormalArray(normals); geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); diff --git a/src/osgPlugins/osg/Drawable.cpp b/src/osgPlugins/osg/Drawable.cpp index 4a621d6f8..6f1a46205 100644 --- a/src/osgPlugins/osg/Drawable.cpp +++ b/src/osgPlugins/osg/Drawable.cpp @@ -35,15 +35,11 @@ bool Drawable_readLocalData(Object& obj, Input& fr) iteratorAdvanced = true; } - ref_ptr readObject = fr.readObject(); - if (readObject.valid()) - { - osg::Shape* shape = dynamic_cast(readObject.get()); - if (shape) drawable.setShape(shape); - else notify(WARN)<<"Warning:: "<className()<<" loaded but cannot not be attached to Drawable."<(fr.readObjectOfType(type_wrapper())); + if (shape) { + drawable.setShape(shape); + iteratorAdvanced = true; + } if (fr[0].matchWord("supportsDisplayList")) { diff --git a/src/osgPlugins/osg/Shape.cpp b/src/osgPlugins/osg/Shape.cpp index c04f92f0f..a5f21b5f0 100644 --- a/src/osgPlugins/osg/Shape.cpp +++ b/src/osgPlugins/osg/Shape.cpp @@ -502,11 +502,10 @@ bool CompositeShape_readLocalData(Object& obj, Input& fr) } } - while((readObject=fr.readObject()).valid()) + while((readObject=fr.readObjectOfType(type_wrapper())).valid()) { - osg::Shape* shape = dynamic_cast(readObject.get()); - if (shape) composite.addChild(shape); - else notify(WARN)<<"Warning:: "<className()<<" loaded but cannot not be attached to Drawable."<(readObject.get()); + composite.addChild(shape); iteratorAdvanced = true; } diff --git a/src/osgPlugins/osg/ShapeDrawable.cpp b/src/osgPlugins/osg/ShapeDrawable.cpp index 8cfe7eaee..ddefbc2af 100644 --- a/src/osgPlugins/osg/ShapeDrawable.cpp +++ b/src/osgPlugins/osg/ShapeDrawable.cpp @@ -42,13 +42,10 @@ bool ShapeDrawable_readLocalData(Object& obj, Input& fr) iteratorAdvanced = true; } - ref_ptr readObject = fr.readObject(); + ref_ptr readObject = fr.readObjectOfType(type_wrapper()); if (readObject.valid()) { - TessellationHints* hints = dynamic_cast(readObject.get()); - if (hints) - geom.setTessellationHints(hints); - else - notify(WARN) << "Warning: " << readObject->className() << " loaded but cannot be attached to ShapeDrawable.\n"; + TessellationHints* hints = static_cast(readObject.get()); + geom.setTessellationHints(hints); iteratorAdvanced = true; } diff --git a/src/osgPlugins/osgParticle/IO_ModularEmitter.cpp b/src/osgPlugins/osgParticle/IO_ModularEmitter.cpp index 3d2f31976..35eab2cf0 100644 --- a/src/osgPlugins/osgParticle/IO_ModularEmitter.cpp +++ b/src/osgPlugins/osgParticle/IO_ModularEmitter.cpp @@ -25,23 +25,19 @@ bool ModularEmitter_readLocalData(osg::Object &obj, osgDB::Input &fr) osgParticle::ModularEmitter &myobj = static_cast(obj); bool itAdvanced = false; - // we cannot use readObjectOfType() because the Coutner, Placer and Shooter classes are - // abstract and we can't create instances to use as prototypes. - // So, we call readObject() and then dynamic cast to the desired class. - - osgParticle::Counter *counter = dynamic_cast(fr.readObject()); + osgParticle::Counter *counter = static_cast(fr.readObjectOfType(osgDB::type_wrapper())); if (counter) { myobj.setCounter(counter); itAdvanced = true; } - osgParticle::Placer *placer = dynamic_cast(fr.readObject()); + osgParticle::Placer *placer = static_cast(fr.readObjectOfType(osgDB::type_wrapper())); if (placer) { myobj.setPlacer(placer); itAdvanced = true; } - osgParticle::Shooter *shooter = dynamic_cast(fr.readObject()); + osgParticle::Shooter *shooter = static_cast(fr.readObjectOfType(osgDB::type_wrapper())); if (shooter) { myobj.setShooter(shooter); itAdvanced = true; diff --git a/src/osgPlugins/osgParticle/IO_ModularProgram.cpp b/src/osgPlugins/osgParticle/IO_ModularProgram.cpp index 7cf338d76..db9ef37a4 100644 --- a/src/osgPlugins/osgParticle/IO_ModularProgram.cpp +++ b/src/osgPlugins/osgParticle/IO_ModularProgram.cpp @@ -25,7 +25,7 @@ bool ModularProgram_readLocalData(osg::Object &obj, osgDB::Input &fr) osgParticle::ModularProgram &myobj = static_cast(obj); bool itAdvanced = false; - osgParticle::Operator *op = dynamic_cast(fr.readObject()); + osgParticle::Operator *op = static_cast(fr.readObjectOfType(osgDB::type_wrapper())); if (op) { myobj.addOperator(op); itAdvanced = true;