diff --git a/examples/osganalysis/osganalysis.cpp b/examples/osganalysis/osganalysis.cpp index 176259412..cd5548b03 100644 --- a/examples/osganalysis/osganalysis.cpp +++ b/examples/osganalysis/osganalysis.cpp @@ -72,6 +72,247 @@ public: } }; +class SwapArrayVisitor : public osg::ArrayVisitor +{ +public: + SwapArrayVisitor(osg::Array* array): + _array(array) {} + + template + void apply_imp(ARRAY& array) + { + if (array.getType()!=_array->getType()) + { + OSG_NOTICE<<"Arrays incompatible"<(_array)); + } + + virtual void apply(osg::ByteArray& ba) { apply_imp(ba); } + virtual void apply(osg::ShortArray& ba) { apply_imp(ba); } + virtual void apply(osg::IntArray& ba) { apply_imp(ba); } + virtual void apply(osg::UByteArray& ba) { apply_imp(ba); } + virtual void apply(osg::UShortArray& ba) { apply_imp(ba); } + virtual void apply(osg::UIntArray& ba) { apply_imp(ba); } + virtual void apply(osg::Vec4ubArray& ba) { apply_imp(ba); } + virtual void apply(osg::FloatArray& ba) { apply_imp(ba); } + virtual void apply(osg::Vec2Array& ba) { apply_imp(ba); } + virtual void apply(osg::Vec3Array& ba) { apply_imp(ba); } + virtual void apply(osg::Vec4Array& ba) { apply_imp(ba); } + + osg::Array* _array; +}; + +class MemoryVisitor : public osg::NodeVisitor +{ +public: + MemoryVisitor(): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + + + void reset() + { + _nodes.clear(); + _geometryMap.clear(); + _arrayMap.clear(); + _primitiveSetMap.clear(); + } + + void apply(osg::Node& node) + { + _nodes.insert(&node); + traverse(node); + } + + void apply(osg::Geode& geode) + { + _nodes.insert(&geode); + for(unsigned int i=0; iasGeometry(); + if (geometry) + { + _geometryMap[geometry].insert(geode); + + apply(geometry, geometry->getVertexArray()); + apply(geometry, geometry->getNormalArray()); + apply(geometry, geometry->getColorArray()); + apply(geometry, geometry->getSecondaryColorArray()); + apply(geometry, geometry->getFogCoordArray()); + + for(unsigned int i=0; igetNumTexCoordArrays(); ++i) + { + apply(geometry, geometry->getTexCoordArray(i)); + } + for(unsigned int i=0; igetNumVertexAttribArrays(); ++i) + { + apply(geometry, geometry->getVertexAttribArray(i)); + } + + for(unsigned int i=0; igetNumPrimitiveSets(); ++i) + { + apply(geometry, geometry->getPrimitiveSet(i)); + } + } + } + + void apply(osg::Geometry* geometry, osg::Array* array) + { + if (!array) return; + _arrayMap[array].insert(geometry); + } + + void apply(osg::Geometry* geometry, osg::PrimitiveSet* primitiveSet) + { + if (!primitiveSet) return; + _primitiveSetMap[primitiveSet].insert(geometry); + } + + void report(std::ostream& out) + { + OSG_NOTICE<<"Nodes "<<_nodes.size()< > ArrayVector; + typedef std::vector< osg::ref_ptr > GeometryVector; + ArrayVector newArrays; + GeometryVector newGeometries; + for(GeometryMap::iterator itr = _geometryMap.begin(); + itr != _geometryMap.end(); + ++itr) + { + osg::Geometry* geometry = itr->first; + bool useVBO = geometry->getUseVertexBufferObjects(); + osg::Geometry* newGeometry = osg::clone(geometry, osg::CopyOp(osg::CopyOp::DEEP_COPY_ALL)); + newGeometry->setUseVertexBufferObjects(false); + newGeometry->setUseVertexBufferObjects(useVBO); + newGeometries.push_back(newGeometry); + } + + GeometryVector::iterator geom_itr = newGeometries.begin(); + for(GeometryMap::iterator itr = _geometryMap.begin(); + itr != _geometryMap.end(); + ++itr, ++geom_itr) + { + osg::Geometry* geometry = itr->first; + Geodes& geodes = itr->second; + for(Geodes::iterator gitr = geodes.begin(); + gitr != geodes.end(); + ++gitr) + { + osg::Geode* geode = const_cast(*gitr); + geode->replaceDrawable(geometry, geom_itr->get()); + } + } + } + + typedef std::vector< osg::ref_ptr > GeometryVector; + typedef std::pair ArrayPair; + typedef std::vector< ArrayPair > ArrayVector; + typedef std::pair PrimitiveSetPair; + typedef std::vector< PrimitiveSetPair > PrimitiveSetVector; + + osg::Array* cloneArray(ArrayVector& arrayVector, osg::Array* array) + { + if (!array) return 0; + osg::Array* newArray = static_cast(array->cloneType()); + arrayVector.push_back(ArrayPair(array,newArray)); + return newArray; + } + + osg::PrimitiveSet* clonePrimitiveSet(PrimitiveSetVector& psVector, osg::PrimitiveSet* ps) + { + if (!ps) return 0; + osg::PrimitiveSet* newPS = static_cast(ps->cloneType()); + psVector.push_back(PrimitiveSetPair(ps,newPS)); + return newPS; + } + + void reallocate2() + { + OSG_NOTICE<<"Reallocating Arrays"<first; + osg::ref_ptr newGeometry = osg::clone(geometry, osg::CopyOp::SHALLOW_COPY); + newGeometries.push_back(newGeometry.get()); + + newGeometry->setVertexArray(cloneArray(arrayVector, geometry->getVertexArray())); + newGeometry->setNormalArray(cloneArray(arrayVector, geometry->getNormalArray())); + newGeometry->setColorArray(cloneArray(arrayVector, geometry->getColorArray())); + newGeometry->setSecondaryColorArray(cloneArray(arrayVector, geometry->getSecondaryColorArray())); + newGeometry->setFogCoordArray(cloneArray(arrayVector, geometry->getFogCoordArray())); + for(unsigned int i=0; igetNumTexCoordArrays(); ++i) + { + newGeometry->setTexCoordArray(i, cloneArray(arrayVector, geometry->getTexCoordArray(i))); + } + for(unsigned int i=0; igetNumVertexAttribArrays(); ++i) + { + newGeometry->setVertexAttribArray(i, cloneArray(arrayVector, geometry->getVertexAttribArray(i))); + } + + for(unsigned int i=0; igetNumPrimitiveSets(); ++i) + { + newGeometry->setPrimitiveSet(i,clonePrimitiveSet(primitiveSetVector, geometry->getPrimitiveSet(i))); + } + } + + GeometryVector::iterator geom_itr = newGeometries.begin(); + for(GeometryMap::iterator itr = _geometryMap.begin(); + itr != _geometryMap.end(); + ++itr, ++geom_itr) + { + osg::Geometry* geometry = itr->first; + Geodes& geodes = itr->second; + for(Geodes::iterator gitr = geodes.begin(); + gitr != geodes.end(); + ++gitr) + { + osg::Geode* geode = const_cast(*gitr); + geode->replaceDrawable(geometry, geom_itr->get()); + } + } + } + +protected: + + typedef std::set Nodes; + typedef std::set Geodes; + typedef std::set Geometries; + typedef std::map GeometryMap; + typedef std::map ArrayMap; + typedef std::map PrimitiveSetMap; + + Nodes _nodes; + GeometryMap _geometryMap; + ArrayMap _arrayMap; + PrimitiveSetMap _primitiveSetMap; +}; + class SceneGraphProcessor : public osg::Referenced { public: @@ -101,6 +342,9 @@ public: while (arguments.read("--compress")) { modifyTextureSettings = true; compressImages = true; } while (arguments.read("--disable-mipmaps")) { modifyTextureSettings = true; disableMipmaps = true; } + while (arguments.read("--reallocate") || arguments.read("--ra") ) { reallocateMemory = true; } + + OSG_NOTICE<<"simplificatioRatio="<accept(ssv); } + MemoryVisitor mv; + node->accept(mv); + mv.report(osg::notify(osg::NOTICE)); + + if (reallocateMemory) + { + OSG_NOTICE<<"Running Reallocation of scene graph memory"<accept(mv); + mv.report(osg::notify(osg::NOTICE)); + return node; } @@ -174,6 +432,8 @@ protected: optimizeVertexCache = false; optimizeVertexOrder = false; + reallocateMemory = false; + modifyTextureSettings = false; buildImageMipmaps = false; compressImages = false; @@ -192,6 +452,8 @@ protected: bool optimizeVertexCache; bool optimizeVertexOrder; + bool reallocateMemory; + bool modifyTextureSettings; bool buildImageMipmaps; bool compressImages;