diff --git a/CMakeLists.txt b/CMakeLists.txt index 17d25504..adef8b1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,7 +161,7 @@ else() endif() endif(ENABLE_SOUND) - find_package(OpenSceneGraph 3.4.1 REQUIRED osgText osgSim osgDB osgParticle osgGA osgViewer osgUtil) + find_package(OpenSceneGraph 3.4.1 REQUIRED osgText osgSim osgDB osgParticle osgGA osgViewer osgUtil osgTerrain) if (MSVC) set(CMAKE_REQUIRED_INCLUDES ${OPENSCENEGRAPH_INCLUDE_DIRS}) diff --git a/simgear/scene/model/ModelRegistry.cxx b/simgear/scene/model/ModelRegistry.cxx index 4fdef219..ad3db305 100644 --- a/simgear/scene/model/ModelRegistry.cxx +++ b/simgear/scene/model/ModelRegistry.cxx @@ -48,6 +48,8 @@ #include #include +#include + #include #include @@ -56,6 +58,8 @@ #include #include +#include + #include #include #include @@ -869,6 +873,145 @@ struct IVEOptimizePolicy : public OptimizeModelPolicy { } }; +template +class FindTopMostNodeOfTypeVisitor : public osg::NodeVisitor +{ +public: + FindTopMostNodeOfTypeVisitor(): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + _foundNode(0) + {} + + void apply(osg::Node& node) + { + T* result = dynamic_cast(&node); + if (result) + { + _foundNode = result; + } + else + { + traverse(node); + } + } + + T* _foundNode; +}; + +template +T* findTopMostNodeOfType(osg::Node* node) +{ + if (!node) return 0; + + FindTopMostNodeOfTypeVisitor fnotv; + node->accept(fnotv); + + return fnotv._foundNode; +} + +class CleanTechniqueVisitor : public osg::NodeVisitor +{ +public: + CleanTechniqueVisitor(): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + + void apply(osg::Node& node) + { + osgTerrain::TerrainTile* tile = dynamic_cast(&node); + if (tile) + { + if (tile->getTerrainTechnique()) + { + // OSG_NOTICE<<"Resetting TerrainTechnhique "<getTerrainTechnique()->className()<<" to 0"<setTerrainTechnique(0); + } + } + else + { + traverse(node); + } + } +}; + +struct OSGOptimizePolicy : public OptimizeModelPolicy { + + + OSGOptimizePolicy(const string& extension) : + OptimizeModelPolicy(extension) + { + _osgOptions &= ~Optimizer::TRISTRIP_GEOMETRY; + } + Node* optimize(Node* node, const string& fileName, + const Options* opt) + { + ref_ptr optimized = node; + + const SGReaderWriterOptions* sgopt + = dynamic_cast(opt); + + if (fileName.find("vpb/WS_") != string::npos) { + // Currently the only way we have to identify WS3.0 / VirtualPlanetBuilder files is by the filename + + // Clean out any existing osgTerrain techniques + CleanTechniqueVisitor ctv; + optimized->accept(ctv); + + osg::ref_ptr terrain = findTopMostNodeOfType(optimized.get()); + + if (terrain != NULL) { + // Top level + terrain->setSampleRatio(1.0); + terrain->setVerticalScale(1.0); + terrain->setBlendingPolicy(osgTerrain::TerrainTile::INHERIT); + terrain->setTerrainTechniquePrototype(new VPBTechnique(sgopt)); + } else { + // no Terrain node present insert one above the loaded model. + terrain = new osgTerrain::Terrain; + //SG_LOG(SG_TERRAIN, SG_ALERT, "Creating Terrain Node for " << fileName); + + // if CoordinateSystemNode is present copy it's contents into the Terrain, and discard it. + osg::CoordinateSystemNode* csn = findTopMostNodeOfType(optimized.get()); + if (csn) + { + terrain->set(*csn); + for(unsigned int i=0; igetNumChildren();++i) + { + terrain->addChild(csn->getChild(i)); + } + } + else + { + terrain->addChild(optimized.get()); + } + } + } + + optimized = OptimizeModelPolicy::optimize(optimized, fileName, opt); + Group* group = dynamic_cast(optimized.get()); + MatrixTransform* transform + = dynamic_cast(optimized.get()); + if (((transform && transform->getMatrix().isIdentity()) || group) + && group->getName().empty() + && group->getNumChildren() == 1) { + optimized = static_cast(group->getChild(0)); + group = dynamic_cast(optimized.get()); + if (group && group->getName().empty() + && group->getNumChildren() == 1) + optimized = static_cast(group->getChild(0)); + } + + if (sgopt && sgopt->getInstantiateMaterialEffects()) { + optimized = instantiateMaterialEffects(optimized.get(), sgopt); + } + else if (sgopt && sgopt->getInstantiateEffects()) { + optimized = instantiateEffects(optimized.get(), sgopt); + } + + return optimized.release(); + } +}; + + struct IVEProcessPolicy { IVEProcessPolicy(const string& extension) {} Node* process(Node* node, const string& filename, @@ -897,12 +1040,17 @@ typedef ModelRegistryCallback IVECallback; +typedef ModelRegistryCallback + OSGCallback; + namespace { ModelRegistryCallbackProxy g_acRegister("ac"); ModelRegistryCallbackProxy g_objRegister("obj"); ModelRegistryCallbackProxy g_iveRegister("ive"); -ModelRegistryCallbackProxy g_osgtRegister("osgt"); -ModelRegistryCallbackProxy g_osgbRegister("osgb"); +ModelRegistryCallbackProxy g_osgtRegister("osgt"); +ModelRegistryCallbackProxy g_osgbRegister("osgb"); } diff --git a/simgear/scene/tgdb/CMakeLists.txt b/simgear/scene/tgdb/CMakeLists.txt index bbf14e92..279c5336 100644 --- a/simgear/scene/tgdb/CMakeLists.txt +++ b/simgear/scene/tgdb/CMakeLists.txt @@ -19,6 +19,7 @@ set(HEADERS SGVertexArrayBin.hxx ShaderGeometry.hxx TreeBin.hxx + VPBTechnique.hxx apt_signs.hxx obj.hxx pt_lights.hxx @@ -35,6 +36,7 @@ set(SOURCES SGVasiDrawable.cxx ShaderGeometry.cxx TreeBin.cxx + VPBTechnique.cxx apt_signs.cxx obj.cxx pt_lights.cxx