// terrain_pgt.cxx -- data structures and routines for managing scenery. // // Written by Curtis Olson, started May 1997. // // Copyright (C) 1997 Curtis L. Olson - http://www.flightgear.org/~curt // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ #include #include #ifdef ENABLE_GDAL #include #include #include #include
#include
#include #include "terrain_pgt.hxx" #include "scenery.hxx" using namespace flightgear; using namespace simgear; using flightgear::SceneryPager; // Terrain Management system FGPgtTerrain::FGPgtTerrain() : _scenery_loaded(fgGetNode("/sim/sceneryloaded", true)), _scenery_override(fgGetNode("/sim/sceneryloaded-override", true)) { _inited = false; } FGPgtTerrain::~FGPgtTerrain() { } // Initialize the Scenery Management system void FGPgtTerrain::init( osg::Group* terrain ) { // Already set up. if (_inited) return; SG_LOG(SG_TERRAIN, SG_INFO, "FGPgtTerrain::init"); // remember the scene terrain branch on scenegraph terrain_branch = terrain; // load the whole planet tile - database pager handles // the quad tree / loading the highres tiles osg::ref_ptr options; // drops the previous options reference options = new simgear::SGReaderWriterOptions; options->setPropertyNode(globals->get_props()); osgDB::FilePathList &fp = options->getDatabasePathList(); const PathList &sc = globals->get_fg_scenery(); fp.clear(); PathList::const_iterator it; for (it = sc.begin(); it != sc.end(); ++it) { fp.push_back(it->local8BitStr()); } options->setPluginStringData("SimGear::FG_ROOT", globals->get_fg_root().local8BitStr()); options->setPluginStringData("SimGear::BARE_LOD_RANGE", fgGetString("/sim/rendering/static-lod/bare-delta", boost::lexical_cast(SG_OBJECT_RANGE_BARE))); options->setPluginStringData("SimGear::ROUGH_LOD_RANGE", fgGetString("/sim/rendering/static-lod/rough-delta", boost::lexical_cast(SG_OBJECT_RANGE_ROUGH))); options->setPluginStringData("SimGear::ROUGH_LOD_DETAILED", fgGetString("/sim/rendering/static-lod/detailed", boost::lexical_cast(SG_OBJECT_RANGE_DETAILED))); options->setPluginStringData("SimGear::RENDER_BUILDING_MESH", fgGetBool("/sim/rendering/building-mesh", false) ? "true" : "false"); options->setPluginStringData("SimGear::FG_EARTH", "ON"); // tunables options->setPluginStringData("SimGear::SPT_PAGE_LEVELS", fgGetString("/sim/scenery/lod-levels", "1 3 5 7 9" )); options->setPluginStringData("SimGear::SPT_RANGE_MULTIPLIER", fgGetString("/sim/scenery/lod-range-mult", "2" )); options->setPluginStringData("SimGear::SPT_MESH_RESOLUTION", fgGetString("/sim/scenery/lod-res", "1" )); options->setPluginStringData("SimGear::SPT_LOD_TEXTURING", fgGetString("/sim/scenery/lod-texturing", "bluemarble" )); options->setMaterialLib(globals->get_matlib()); // a DEM can contain multiple levels from multiple locations // priority is based on first found... _dem = new SGDem; if ( _dem ) { for (osgDB::FilePathList::const_iterator i = fp.begin(); i != fp.end(); ++i) { SGPath demPath(*i); demPath.append("DEM"); int numLevels = _dem->addRoot(demPath); if ( numLevels ) { SG_LOG(SG_TERRAIN, SG_INFO, "Terrain init - dem path " << demPath << " has " << numLevels << " LOD Levels " ); } else { SG_LOG(SG_TERRAIN, SG_INFO, "Terrain init - dem path " << demPath << " has NO LOD Levels " ); } } options->setDem(_dem); SG_LOG(SG_TERRAIN, SG_INFO, "Terrain init - Load w180s90-360x180.pgt" ); #if OSG_VERSION_LESS_THAN(3,4,0) osg::ref_ptr loadedModel = osgDB::readNodeFile("w180s90-360x180.pgt", options.get()); #else osg::ref_ptr loadedModel = osgDB::readRefNodeFile("w180s90-360x180.pgt", options.get()); #endif if ( loadedModel ) { terrain_branch->addChild( loadedModel.get() ); // Toggle the setup flag. _inited = true; } } } void FGPgtTerrain::reinit() { } void FGPgtTerrain::shutdown() { terrain_branch = NULL; // Toggle the setup flag. _inited = false; } void FGPgtTerrain::update(double dt) { // scenery loading check, triggers after each sim (tile manager) reinit if (!_scenery_loaded->getBoolValue()) { bool fdmInited = fgGetBool("sim/fdm-initialized"); bool positionFinalized = fgGetBool("sim/position-finalized"); bool sceneryOverride = _scenery_override->getBoolValue(); // we are done if final position is set and the scenery & FDM are done. // scenery-override can ignore the last two, but not position finalization. if (positionFinalized && (sceneryOverride || fdmInited)) { _scenery_loaded->setBoolValue(true); fgSplashProgress(""); } else { if (!positionFinalized) { fgSplashProgress("finalize-position"); } else { fgSplashProgress("loading-scenery"); } // be nice to loader threads while waiting for initial scenery, reduce to 20fps SGTimeStamp::sleepForMSec(50); } } } void FGPgtTerrain::bind() { } void FGPgtTerrain::unbind() { } bool FGPgtTerrain::get_cart_elevation_m(const SGVec3d& pos, double max_altoff, double& alt, const simgear::BVHMaterial** material, const osg::Node* butNotFrom) { SGGeod geod = SGGeod::fromCart(pos); geod.setElevationM(geod.getElevationM() + max_altoff); return get_elevation_m(geod, alt, material, butNotFrom); } static simgear::BVHMaterial def_mat; bool FGPgtTerrain::get_elevation_m(const SGGeod& geod, double& alt, const simgear::BVHMaterial** material, const osg::Node* butNotFrom) { alt = 100.0; if (material) { *material = &def_mat; } else { // SG_LOG(SG_TERRAIN, SG_INFO, "FGStgTerrain::get_elevation_m: alt " << alt << " no material " ); } return true; } bool FGPgtTerrain::get_cart_ground_intersection(const SGVec3d& pos, const SGVec3d& dir, SGVec3d& nearestHit, const osg::Node* butNotFrom) { return true; } bool FGPgtTerrain::scenery_available(const SGGeod& position, double range_m) { if( schedule_scenery(position, range_m, 0.0) ) { return true; } else { return false; } } bool FGPgtTerrain::schedule_scenery(const SGGeod& position, double range_m, double duration) { // sanity check (unfortunately needed!) if (!position.isValid()) { SG_LOG(SG_TERRAIN, SG_INFO, "FGSptTerrain::schedule_scenery - position invalid"); return false; } return true; } void FGPgtTerrain::materialLibChanged() { // PSADRO: TODO - passing down new regional textures won't work. these need to be set in the // lod tree at init time, as OSGDBPager generates the load request, not the tile cache. // _options->setMaterialLib(globals->get_matlib()); } #endif