2016-07-30 12:26:45 +00:00
|
|
|
// 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$
|
|
|
|
|
|
|
|
|
2017-03-07 20:20:50 +00:00
|
|
|
#include <config.h>
|
|
|
|
#include <simgear/simgear_config.h>
|
2016-07-30 12:26:45 +00:00
|
|
|
|
|
|
|
#ifdef ENABLE_GDAL
|
|
|
|
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
|
|
|
|
#include <simgear/scene/material/mat.hxx>
|
|
|
|
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
|
|
|
|
|
|
|
#include <Main/globals.hxx>
|
|
|
|
#include <Main/fg_props.hxx>
|
|
|
|
#include <Viewer/splash.hxx>
|
|
|
|
|
|
|
|
#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<simgear::SGReaderWriterOptions> 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());
|
|
|
|
|
2018-10-30 19:10:30 +00:00
|
|
|
options->setPluginStringData("SimGear::BARE_LOD_RANGE", fgGetString("/sim/rendering/static-lod/bare-delta", boost::lexical_cast<string>(SG_OBJECT_RANGE_BARE)));
|
|
|
|
options->setPluginStringData("SimGear::ROUGH_LOD_RANGE", fgGetString("/sim/rendering/static-lod/rough-delta", boost::lexical_cast<string>(SG_OBJECT_RANGE_ROUGH)));
|
2016-07-30 12:26:45 +00:00
|
|
|
options->setPluginStringData("SimGear::ROUGH_LOD_DETAILED", fgGetString("/sim/rendering/static-lod/detailed", boost::lexical_cast<string>(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" );
|
2019-01-26 17:03:17 +00:00
|
|
|
#if OSG_VERSION_LESS_THAN(3,4,0)
|
|
|
|
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile("w180s90-360x180.pgt", options.get());
|
|
|
|
#else
|
2019-01-20 22:26:37 +00:00
|
|
|
osg::ref_ptr<osg::Node> loadedModel = osgDB::readRefNodeFile("w180s90-360x180.pgt", options.get());
|
2019-01-26 17:03:17 +00:00
|
|
|
#endif
|
2016-07-30 12:26:45 +00:00
|
|
|
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
|