// // OpenFlightŪ loader for OpenSceneGraph // // Copyright (C) 2005-2006 Brede Johansen // #include #include #include #include #include #include #include using namespace osgFlightUtil; void Optimizer::optimize(osg::Node* node) { unsigned int options = 0; const char* env = getenv("OSG_FLIGHTUTIL_OPTIMIZER"); if (env) { std::string str(env); if(str.find("OFF")!=std::string::npos) options = 0; if(str.find("~DEFAULT")!=std::string::npos) options ^= DEFAULT_OPTIMIZATIONS; else if(str.find("DEFAULT")!=std::string::npos) options |= DEFAULT_OPTIMIZATIONS; if(str.find("~TESSELATE_POLYGON")!=std::string::npos) options ^= TESSELATE_POLYGON; else if(str.find("TESSELATE_POLYGON")!=std::string::npos) options |= TESSELATE_POLYGON; if(str.find("~MAKE_LIT")!=std::string::npos) options ^= MAKE_LIT; else if(str.find("MAKE_LIT")!=std::string::npos) options |= MAKE_LIT; if(str.find("~MERGE_GEODES")!=std::string::npos) options ^= MERGE_GEODES; else if(str.find("MERGE_GEODES")!=std::string::npos) options |= MERGE_GEODES; } else { options = DEFAULT_OPTIMIZATIONS; } optimize(node,options); } void Optimizer::optimize(osg::Node* node, unsigned int options) { if (options & TESSELATE_POLYGON) { osg::notify(osg::INFO)<<"osgFlightUtil::Optimizer::optimize() doing TESSELATE_POLYGON"<accept(visitor); } if (options & MAKE_LIT) { osg::notify(osg::INFO)<<"osgFlightUtil::Optimizer::optimize() doing MAKE_LIT"<accept(visitor); } if (options & MERGE_GEODES) { osg::notify(osg::INFO)<<"osgFlightUtil::Optimizer::optimize() doing MERGE_GEODES"<accept(visitor); } } void Optimizer::TesselateVisitor::apply(osg::Geode& geode) { for (unsigned int i=0; i(geode.getDrawable(i)); if (geometry) { if (hasPolygons(*geometry)) { // Tesselate osgUtil::Tesselator tesselator; tesselator.retesselatePolygons(*geometry); } } } } bool Optimizer::TesselateVisitor::hasPolygons(osg::Geometry& geometry) { for (unsigned int i=0; igetMode() == osg::PrimitiveSet::POLYGON) return true; } return false; } void Optimizer::MakeLitVisitor::apply(osg::Geode& /*geode*/) { #if 0 // TODO osg::StateSet* stateset = geode.getStateSet(); if (stateset) { // Not lit? if (!(stateset->getMode(GL_LIGHTING)&osg::StateAttribute::ON)) { stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON); for (unsigned int i=0; i(geode.getDrawable(i)); if (geometry) { if () TODO Compare vertex array length and normal array length + normal binding. { // generate normals osgUtil::SmoothingVisitor smoother; smoother.smooth(*geometry); } } } } } #endif } /** Need to share stateset before merging geodes. */ class GeodeStateOptimizer : public osgUtil::Optimizer::StateVisitor { public: GeodeStateOptimizer(): osgUtil::Optimizer::StateVisitor() {} void optimize(osg::Group& group) { for (unsigned int i=0; igetStateSet(),geode); } } osgUtil::Optimizer::StateVisitor::optimize(); } }; void Optimizer::MergeGeodesVisitor::apply(osg::Group& group) { mergeGeodes(group); traverse(group); } // Requires shared stateset to work. Run GeodeStateOptimizer before MergeGeodesVisitor. struct LessGeode { bool operator() (const osg::Geode* lhs,const osg::Geode* rhs) const { if (lhs->getStateSet()getStateSet()) return true; // if (rhs->getStateSet()getStateSet()) return false; return false; } }; void Optimizer::MergeGeodesVisitor::mergeGeodes(osg::Group& group) { { GeodeStateOptimizer gsopt; gsopt.optimize(group); } typedef std::vector DuplicateList; typedef std::map GeodeDuplicateMap; GeodeDuplicateMap geodeDuplicateMap; for (unsigned int i=0; isecond.size()>1) { osg::Geode* lhs = itr->second[0]; for(DuplicateList::iterator dupItr=itr->second.begin()+1; dupItr!=itr->second.end(); ++dupItr) { osg::Geode* rhs = *dupItr; if (mergeGeode(*lhs,*rhs)) { group.removeChild(rhs); static int co = 0; osg::notify(osg::INFO)<<"merged and removed Geode "<<++co<