Alternative terrain engine based on pagedLOD
- remove TileMgr from sub systems - add to btg terrain engine
This commit is contained in:
parent
6e9d4e8ae4
commit
ec4b9f8542
26 changed files with 1432 additions and 163 deletions
|
@ -167,6 +167,8 @@ option(ENABLE_YASIM "Set to ON to build FlightGear with YASIM FDM (default)
|
|||
option(ENABLE_JSBSIM "Set to ON to build FlightGear with JSBSim FDM (default)" ON)
|
||||
option(EVENT_INPUT "Set to ON to build FlightGear with event-based Input support" ${EVENT_INPUT_DEFAULT})
|
||||
option(ENABLE_RTI "Set to ON to build FlightGear with RTI support" OFF)
|
||||
option(ENABLE_GDAL "Set to ON to build FlightGear with GDAL support" OFF)
|
||||
option(ENABLE_OPENMP "Set to ON to build FlightGear with OpenMP compiler support" OFF)
|
||||
option(ENABLE_PROFILE "Set to ON to build FlightGear with gperftools profiling support" OFF)
|
||||
option(SYSTEM_SQLITE "Set to ON to build FlightGear with the system's SQLite3 library" OFF)
|
||||
option(ENABLE_IAX "Set to ON to build FlightGear with IAXClient/fgcom built-in (default)" ON)
|
||||
|
@ -194,6 +196,7 @@ option(ENABLE_FLITE "Set to ON to build the Flite text-to-speech module" ON
|
|||
option(ENABLE_QT "Set to ON to build the internal Qt launcher" ON)
|
||||
option(ENABLE_TRAFFIC "Set to ON to build the external traffic generator modules" ON)
|
||||
option(ENABLE_FGQCANVAS "Set to ON to build the Qt-based remote canvas application" OFF)
|
||||
option(ENABLE_DEMCONVERT "Set to ON to build the dem conversion tool (default)" ON)
|
||||
|
||||
include (DetectArch)
|
||||
|
||||
|
@ -357,6 +360,24 @@ else()
|
|||
message(STATUS "RTI: DISABLED")
|
||||
endif(ENABLE_RTI)
|
||||
|
||||
if(ENABLE_GDAL)
|
||||
find_package(GDAL 2.0.0 REQUIRED)
|
||||
endif(ENABLE_GDAL)
|
||||
include_directories(${GDAL_INCLUDE_DIR})
|
||||
|
||||
if (ENABLE_OPENMP)
|
||||
find_package(OpenMP)
|
||||
if(OPENMP_FOUND)
|
||||
message(STATUS "OpenMP: ENABLED")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
||||
else()
|
||||
message(STATUS "OpenMP: NOT FOUND")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "OpenMP: DISABLED")
|
||||
endif()
|
||||
|
||||
if (ENABLE_SIMD)
|
||||
message(STATUS "SSE/SSE2 support: ENABLED")
|
||||
else()
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <Main/fg_props.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
#include <Airports/airport.hxx>
|
||||
#include <Main/util.hxx>
|
||||
|
@ -551,7 +550,7 @@ void FGAIAircraft::getGroundElev(double dt) {
|
|||
}
|
||||
|
||||
double range = 500.0;
|
||||
if (globals->get_tile_mgr()->schedule_scenery(pos, range, 5.0))
|
||||
if (globals->get_scenery()->schedule_scenery(pos, range, 5.0))
|
||||
{
|
||||
double alt;
|
||||
if (getGroundElevationM(SGGeod::fromGeodM(pos, 20000), alt, 0))
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
|
||||
#include "flight.hxx"
|
||||
|
||||
|
@ -330,7 +329,7 @@ FGGroundCache::prepare_ground_cache(double startSimTime, double endSimTime,
|
|||
SGGeod geodPt = SGGeod::fromCart(pt);
|
||||
// Don't blow away the cache ground_radius and stuff if there's no
|
||||
// scenery
|
||||
if (!globals->get_tile_mgr()->schedule_scenery(geodPt, rad, 1.0)) {
|
||||
if (!globals->get_scenery()->schedule_scenery(geodPt, rad, 1.0)) {
|
||||
SG_LOG(SG_FLIGHT, SG_BULK, "prepare_ground_cache(): scenery_available "
|
||||
"returns false at " << geodPt << " " << pt << " " << rad);
|
||||
return false;
|
||||
|
|
|
@ -110,6 +110,12 @@ else()
|
|||
set(HLA_LIBRARIES "")
|
||||
endif()
|
||||
|
||||
if(GDAL_FOUND)
|
||||
set(GDAL_LIBRARIES ${GDAL_LIBRARY})
|
||||
else()
|
||||
set(GDAL_LIBRARIES "")
|
||||
endif()
|
||||
|
||||
if(ENABLE_JSBSIM)
|
||||
# FIXME - remove once JSBSim doesn't expose private headers
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src/FDM/JSBSim)
|
||||
|
@ -141,6 +147,7 @@ target_link_libraries(fgfs
|
|||
${OPENGL_LIBRARIES}
|
||||
${PLIB_LIBRARIES}
|
||||
${HLA_LIBRARIES}
|
||||
${GDAL_LIBRARIES}
|
||||
${EVENT_INPUT_LIBRARIES}
|
||||
${PLATFORM_LIBS}
|
||||
)
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <GUI/dialog.hxx>
|
||||
#include <Aircraft/replay.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
#include <Scripting/NasalSys.hxx>
|
||||
#include <Sound/sample_queue.hxx>
|
||||
#include <Airports/xmlloader.hxx>
|
||||
|
@ -547,8 +546,8 @@ do_materials_reload (const SGPropertyNode * arg)
|
|||
}
|
||||
|
||||
globals->set_matlib(new_matlib);
|
||||
FGTileMgr* tileManager = static_cast<FGTileMgr*>(globals->get_subsystem("tile-manager"));
|
||||
tileManager->materialLibChanged();
|
||||
FGScenery* scenery = static_cast<FGScenery*>(globals->get_scenery());
|
||||
scenery->materialLibChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -111,7 +111,6 @@
|
|||
#include <Navaids/navlist.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/SceneryPager.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
#include <Scripting/NasalSys.hxx>
|
||||
#include <Sound/voice.hxx>
|
||||
#include <Sound/soundmanager.hxx>
|
||||
|
@ -1029,7 +1028,7 @@ void fgStartNewReset()
|
|||
string_list::const_iterator it;
|
||||
for (it = names.begin(); it != names.end(); ++it) {
|
||||
if ((*it == "time") || (*it == "terrasync") || (*it == "events")
|
||||
|| (*it == "lighting") || (*it == FGTileMgr::subsystemName()) || (*it == FGScenery::subsystemName()))
|
||||
|| (*it == "lighting") || (*it == FGScenery::subsystemName()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -1052,7 +1051,6 @@ void fgStartNewReset()
|
|||
|
||||
// order is important here since tile-manager shutdown needs to
|
||||
// access the scenery object
|
||||
subsystemManger->remove(FGTileMgr::subsystemName());
|
||||
subsystemManger->remove(FGScenery::subsystemName());
|
||||
|
||||
FGScenery::getPagerSingleton()->clearRequests();
|
||||
|
|
|
@ -210,7 +210,6 @@ FGGlobals::~FGGlobals()
|
|||
subsystem_mgr->shutdown();
|
||||
subsystem_mgr->unbind();
|
||||
|
||||
subsystem_mgr->remove(FGTileMgr::subsystemName());
|
||||
// don't cancel the pager until after shutdown, since AIModels (and
|
||||
// potentially others) can queue delete requests on the pager.
|
||||
if (vw && vw->getDatabasePager()) {
|
||||
|
@ -756,11 +755,6 @@ FGScenery* FGGlobals::get_scenery () const
|
|||
return get_subsystem<FGScenery>();
|
||||
}
|
||||
|
||||
FGTileMgr* FGGlobals::get_tile_mgr () const
|
||||
{
|
||||
return get_subsystem<FGTileMgr>();
|
||||
}
|
||||
|
||||
FGViewMgr *FGGlobals::get_viewmgr() const
|
||||
{
|
||||
return get_subsystem<FGViewMgr>();
|
||||
|
|
|
@ -59,7 +59,6 @@ class FGTACANList;
|
|||
class FGLocale;
|
||||
class FGRouteMgr;
|
||||
class FGScenery;
|
||||
class FGTileMgr;
|
||||
class FGViewMgr;
|
||||
class FGRenderer;
|
||||
|
||||
|
@ -364,8 +363,6 @@ public:
|
|||
FGControls *get_controls() const;
|
||||
|
||||
FGScenery * get_scenery () const;
|
||||
|
||||
FGTileMgr * get_tile_mgr () const;
|
||||
|
||||
inline FGTACANList *get_channellist() const { return channellist; }
|
||||
inline void set_channellist( FGTACANList *c ) { channellist = c; }
|
||||
|
|
|
@ -58,7 +58,6 @@ extern bool global_crashRptEnabled;
|
|||
|
||||
#include <Model/panelnode.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
#include <Sound/soundmanager.hxx>
|
||||
#include <Time/TimeManager.hxx>
|
||||
#include <GUI/gui.h>
|
||||
|
@ -313,8 +312,7 @@ static void fgIdleFunction ( void ) {
|
|||
globals->add_new_subsystem<FGScenery>(SGSubsystemMgr::DISPLAY);
|
||||
globals->get_scenery()->init();
|
||||
globals->get_scenery()->bind();
|
||||
globals->add_new_subsystem<FGTileMgr>(SGSubsystemMgr::DISPLAY);
|
||||
|
||||
|
||||
fgSplashProgress("creating-subsystems");
|
||||
} else if (( idle_state == 7 ) || (idle_state == 2007)) {
|
||||
bool isReset = (idle_state == 2007);
|
||||
|
|
|
@ -120,17 +120,17 @@ static int fgSetupProxy( const char *arg );
|
|||
void fgSetDefaults ()
|
||||
{
|
||||
|
||||
// Position (deliberately out of range)
|
||||
// Position (deliberately out of range)
|
||||
fgSetDouble("/position/longitude-deg", 9999.0);
|
||||
fgSetDouble("/position/latitude-deg", 9999.0);
|
||||
fgSetDouble("/position/altitude-ft", -9999.0);
|
||||
|
||||
// Orientation
|
||||
// Orientation
|
||||
fgSetDouble("/orientation/heading-deg", 9999.0);
|
||||
fgSetDouble("/orientation/roll-deg", 0.0);
|
||||
fgSetDouble("/orientation/pitch-deg", 0.424);
|
||||
|
||||
// Velocities
|
||||
// Velocities
|
||||
fgSetDouble("/velocities/uBody-fps", 0.0);
|
||||
fgSetDouble("/velocities/vBody-fps", 0.0);
|
||||
fgSetDouble("/velocities/wBody-fps", 0.0);
|
||||
|
@ -140,7 +140,7 @@ void fgSetDefaults ()
|
|||
fgSetDouble("/velocities/airspeed-kt", 0.0);
|
||||
fgSetDouble("/velocities/mach", 0.0);
|
||||
|
||||
// Presets
|
||||
// Presets
|
||||
fgSetDouble("/sim/presets/longitude-deg", 9999.0);
|
||||
fgSetDouble("/sim/presets/latitude-deg", 9999.0);
|
||||
fgSetDouble("/sim/presets/altitude-ft", -9999.0);
|
||||
|
@ -162,7 +162,7 @@ void fgSetDefaults ()
|
|||
fgSetBool("/sim/presets/onground", true);
|
||||
fgSetBool("/sim/presets/trim", false);
|
||||
|
||||
// Miscellaneous
|
||||
// Miscellaneous
|
||||
fgSetBool("/sim/startup/splash-screen", true);
|
||||
// we want mouse-pointer to have an undefined value if nothing is
|
||||
// specified so we can do the right thing for voodoo-1/2 cards.
|
||||
|
@ -170,7 +170,7 @@ void fgSetDefaults ()
|
|||
fgSetBool("/controls/flight/auto-coordination", false);
|
||||
fgSetString("/sim/logging/priority", "alert");
|
||||
|
||||
// Features
|
||||
// Features
|
||||
fgSetBool("/sim/hud/color/antialiased", false);
|
||||
fgSetBool("/sim/hud/enable3d[1]", true);
|
||||
fgSetBool("/sim/hud/visibility[1]", false);
|
||||
|
@ -179,13 +179,21 @@ void fgSetDefaults ()
|
|||
fgSetBool("/sim/sound/working", true);
|
||||
fgSetBool("/sim/fgcom/enabled", false);
|
||||
|
||||
// Flight Model options
|
||||
// Flight Model options
|
||||
fgSetString("/sim/flight-model", "jsb");
|
||||
fgSetString("/sim/aero", "c172");
|
||||
fgSetInt("/sim/model-hz", NEW_DEFAULT_MODEL_HZ);
|
||||
fgSetDouble("/sim/speed-up", 1.0);
|
||||
|
||||
// Rendering options
|
||||
// Scenery
|
||||
fgSetString("/sim/scenery/engine", "tilecache");
|
||||
|
||||
// ( scenery = pagedLOD )
|
||||
fgSetString("/sim/scenery/lod-levels", "1 3 5 7 9");
|
||||
fgSetString("/sim/scenery/lod-res", "1");
|
||||
fgSetString("/sim/scenery/lod-texturing", "bluemarble");
|
||||
|
||||
// Rendering options
|
||||
fgSetString("/sim/rendering/fog", "nicest");
|
||||
fgSetBool("/environment/clouds/status", true);
|
||||
fgSetBool("/sim/startup/fullscreen", false);
|
||||
|
@ -204,16 +212,16 @@ void fgSetDefaults ()
|
|||
fgSetString("/sim/view-mode", "pilot");
|
||||
fgSetDouble("/sim/current-view/heading-offset-deg", 0);
|
||||
|
||||
// HUD options
|
||||
// HUD options
|
||||
fgSetString("/sim/startup/units", "feet");
|
||||
fgSetString("/sim/hud/frame-stat-type", "tris");
|
||||
|
||||
// Time options
|
||||
// Time options
|
||||
fgSetInt("/sim/startup/time-offset", 0);
|
||||
fgSetString("/sim/startup/time-offset-type", "system-offset");
|
||||
fgSetLong("/sim/time/cur-time-override", 0);
|
||||
|
||||
// Freeze options
|
||||
// Freeze options
|
||||
fgSetBool("/sim/freeze/master", false);
|
||||
fgSetBool("/sim/freeze/position", false);
|
||||
fgSetBool("/sim/freeze/clock", false);
|
||||
|
@ -1609,6 +1617,11 @@ struct OptionDesc {
|
|||
{"roc", true, OPTION_FUNC, "", false, "", fgOptRoc },
|
||||
{"fg-root", true, OPTION_IGNORE, "", false, "", 0 },
|
||||
{"fg-scenery", true, OPTION_FUNC | OPTION_MULTI, "", false, "", fgOptFgScenery },
|
||||
{"terrain-engine", true, OPTION_STRING, "/sim/scenery/engine", false, "tilecache", 0 },
|
||||
{"lod-levels", true, OPTION_STRING, "/sim/scenery/lod-levels", false, "1 3 5 7", 0 },
|
||||
{"lod-res", true, OPTION_STRING, "/sim/scenery/lod-res", false, "1", 0 },
|
||||
{"lod-texturing", true, OPTION_STRING, "/sim/scenery/lod-texturing", false, "bluemarble", 0 },
|
||||
{"lod-range-mult", true, OPTION_STRING, "/sim/scenery/lod-range-mult", false, "2", 0 },
|
||||
{"fg-aircraft", true, OPTION_IGNORE | OPTION_MULTI, "", false, "", 0 },
|
||||
{"fdm", true, OPTION_STRING, "/sim/flight-model", false, "", 0 },
|
||||
{"aero", true, OPTION_STRING, "/sim/aero", false, "", 0 },
|
||||
|
|
|
@ -4,6 +4,8 @@ set(SOURCES
|
|||
SceneryPager.cxx
|
||||
redout.cxx
|
||||
scenery.cxx
|
||||
terrain_stg.cxx
|
||||
terrain_pgt.cxx
|
||||
tilecache.cxx
|
||||
tileentry.cxx
|
||||
tilemgr.cxx
|
||||
|
@ -13,6 +15,9 @@ set(HEADERS
|
|||
SceneryPager.hxx
|
||||
redout.hxx
|
||||
scenery.hxx
|
||||
terrain.hxx
|
||||
terrain_stg.hxx
|
||||
terrain_pgt.hxx
|
||||
tilecache.hxx
|
||||
tileentry.hxx
|
||||
tilemgr.hxx
|
||||
|
|
|
@ -57,8 +57,12 @@
|
|||
#include <Main/fg_props.hxx>
|
||||
#include <GUI/MouseCursor.hxx>
|
||||
|
||||
#include "tilemgr.hxx"
|
||||
#include "scenery.hxx"
|
||||
#include "terrain_stg.hxx"
|
||||
|
||||
#ifdef ENABLE_GDAL
|
||||
#include "terrain_pgt.hxx"
|
||||
#endif
|
||||
|
||||
using namespace flightgear;
|
||||
using namespace simgear;
|
||||
|
@ -298,7 +302,7 @@ FGScenery::~FGScenery()
|
|||
|
||||
|
||||
// Initialize the Scenery Management system
|
||||
void FGScenery::init() {
|
||||
void FGScenery::init() {
|
||||
// Already set up.
|
||||
if (_inited)
|
||||
return;
|
||||
|
@ -345,14 +349,36 @@ void FGScenery::init() {
|
|||
precipitation_branch->setName("Precipitation");
|
||||
scene_graph->addChild(precipitation_branch.get());
|
||||
|
||||
// initialize the terrian based on selected engine
|
||||
std::string engine = fgGetString("/sim/scenery/engine", "tilecache" );
|
||||
SG_LOG( SG_TERRAIN, SG_INFO, "Selected scenery is " << engine );
|
||||
|
||||
if ( engine == "pagedLOD" ) {
|
||||
#ifdef ENABLE_GDAL
|
||||
_terrain = new FGPgtTerrain();
|
||||
#else
|
||||
_terrain = new FGStgTerrain();
|
||||
#endif
|
||||
} else {
|
||||
_terrain = new FGStgTerrain();
|
||||
}
|
||||
_terrain->init( terrain_branch.get() );
|
||||
|
||||
_listener = new ScenerySwitchListener(this);
|
||||
|
||||
// Toggle the setup flag.
|
||||
_inited = true;
|
||||
}
|
||||
|
||||
void FGScenery::reinit()
|
||||
{
|
||||
_terrain->reinit();
|
||||
}
|
||||
|
||||
void FGScenery::shutdown()
|
||||
{
|
||||
_terrain->shutdown();
|
||||
|
||||
scene_graph = NULL;
|
||||
terrain_branch = NULL;
|
||||
models_branch = NULL;
|
||||
|
@ -366,17 +392,13 @@ void FGScenery::shutdown()
|
|||
|
||||
|
||||
void FGScenery::update(double dt)
|
||||
{
|
||||
SG_UNUSED(dt);
|
||||
// nothing here, don't call again
|
||||
suspend();
|
||||
{
|
||||
_terrain->update(dt);
|
||||
}
|
||||
|
||||
|
||||
void FGScenery::bind() {
|
||||
}
|
||||
|
||||
|
||||
void FGScenery::unbind() {
|
||||
}
|
||||
|
||||
|
@ -386,9 +408,8 @@ FGScenery::get_cart_elevation_m(const SGVec3d& pos, double max_altoff,
|
|||
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);
|
||||
return _terrain->get_cart_elevation_m(pos, max_altoff, alt,
|
||||
material, butNotFrom);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -396,25 +417,8 @@ FGScenery::get_elevation_m(const SGGeod& geod, double& alt,
|
|||
const simgear::BVHMaterial** material,
|
||||
const osg::Node* butNotFrom)
|
||||
{
|
||||
SGVec3d start = SGVec3d::fromGeod(geod);
|
||||
|
||||
SGGeod geodEnd = geod;
|
||||
geodEnd.setElevationM(SGMiscd::min(geod.getElevationM() - 10, -10000));
|
||||
SGVec3d end = SGVec3d::fromGeod(geodEnd);
|
||||
|
||||
FGSceneryIntersect intersectVisitor(SGLineSegmentd(start, end), butNotFrom);
|
||||
intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
|
||||
get_scene_graph()->accept(intersectVisitor);
|
||||
|
||||
if (!intersectVisitor.getHaveHit())
|
||||
return false;
|
||||
|
||||
geodEnd = SGGeod::fromCart(intersectVisitor.getLineSegment().getEnd());
|
||||
alt = geodEnd.getElevationM();
|
||||
if (material)
|
||||
*material = intersectVisitor.getMaterial();
|
||||
|
||||
return true;
|
||||
return _terrain->get_elevation_m( geod, alt, material,
|
||||
butNotFrom );
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -422,50 +426,22 @@ FGScenery::get_cart_ground_intersection(const SGVec3d& pos, const SGVec3d& dir,
|
|||
SGVec3d& nearestHit,
|
||||
const osg::Node* butNotFrom)
|
||||
{
|
||||
// We assume that starting positions in the center of the earth are invalid
|
||||
if ( norm1(pos) < 1 )
|
||||
return false;
|
||||
|
||||
// Make really sure the direction is normalized, is really cheap compared to
|
||||
// computation of ground intersection.
|
||||
SGVec3d start = pos;
|
||||
SGVec3d end = start + 1e5*normalize(dir); // FIXME visibility ???
|
||||
|
||||
FGSceneryIntersect intersectVisitor(SGLineSegmentd(start, end), butNotFrom);
|
||||
intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
|
||||
get_scene_graph()->accept(intersectVisitor);
|
||||
|
||||
if (!intersectVisitor.getHaveHit())
|
||||
return false;
|
||||
|
||||
nearestHit = intersectVisitor.getLineSegment().getEnd();
|
||||
return true;
|
||||
return _terrain->get_cart_ground_intersection( pos, dir, nearestHit, butNotFrom );
|
||||
}
|
||||
|
||||
bool FGScenery::scenery_available(const SGGeod& position, double range_m)
|
||||
{
|
||||
if(globals->get_tile_mgr()->schedule_scenery(position, range_m, 0.0))
|
||||
{
|
||||
double elev;
|
||||
if (!get_elevation_m(SGGeod::fromGeodM(position, SG_MAX_ELEVATION_M), elev, 0, 0))
|
||||
return false;
|
||||
SGVec3f p = SGVec3f::fromGeod(SGGeod::fromGeodM(position, elev));
|
||||
osg::FrameStamp* framestamp
|
||||
= globals->get_renderer()->getViewer()->getFrameStamp();
|
||||
simgear::CheckSceneryVisitor csnv(_pager, toOsg(p), range_m, framestamp);
|
||||
// currently the PagedLODs will not be loaded by the DatabasePager
|
||||
// while the splashscreen is there, so CheckSceneryVisitor force-loads
|
||||
// missing objects in the main thread
|
||||
get_scene_graph()->accept(csnv);
|
||||
if(!csnv.isLoaded()) {
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "FGScenery::scenery_available: waiting on CheckSceneryVisitor");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "FGScenery::scenery_available: waiting on tile manager");
|
||||
}
|
||||
return false;
|
||||
return _terrain->scenery_available( position, range_m );
|
||||
}
|
||||
|
||||
bool FGScenery::schedule_scenery(const SGGeod& position, double range_m, double duration)
|
||||
{
|
||||
return _terrain->schedule_scenery( position, range_m, duration );
|
||||
}
|
||||
|
||||
void FGScenery::materialLibChanged()
|
||||
{
|
||||
_terrain->materialLibChanged();
|
||||
}
|
||||
|
||||
static osg::ref_ptr<SceneryPager> pager;
|
||||
|
@ -481,4 +457,3 @@ void FGScenery::resetPagerSingleton()
|
|||
{
|
||||
pager = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,18 +38,21 @@
|
|||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
|
||||
#include "SceneryPager.hxx"
|
||||
#include "terrain.hxx"
|
||||
|
||||
namespace simgear {
|
||||
class BVHMaterial;
|
||||
}
|
||||
|
||||
class FGTerrain;
|
||||
|
||||
// Define a structure containing global scenery parameters
|
||||
class FGScenery : public SGSubsystem
|
||||
{
|
||||
class ScenerySwitchListener;
|
||||
friend class ScenerySwitchListener;
|
||||
|
||||
|
||||
|
||||
// scene graph
|
||||
osg::ref_ptr<osg::Switch> scene_graph;
|
||||
osg::ref_ptr<osg::Group> terrain_branch;
|
||||
|
@ -61,13 +64,14 @@ class FGScenery : public SGSubsystem
|
|||
|
||||
osg::ref_ptr<flightgear::SceneryPager> _pager;
|
||||
ScenerySwitchListener* _listener;
|
||||
public:
|
||||
|
||||
public:
|
||||
FGScenery();
|
||||
~FGScenery();
|
||||
|
||||
// Implementation of SGSubsystem.
|
||||
void init ();
|
||||
void reinit();
|
||||
void shutdown ();
|
||||
void bind ();
|
||||
void unbind ();
|
||||
|
@ -129,17 +133,21 @@ public:
|
|||
// the scenery is initialized.
|
||||
static flightgear::SceneryPager* getPagerSingleton();
|
||||
static void resetPagerSingleton();
|
||||
|
||||
flightgear::SceneryPager* getPager() { return _pager.get(); }
|
||||
|
||||
flightgear::SceneryPager* getPager() { return _pager.get(); }
|
||||
|
||||
// tile mgr api
|
||||
bool schedule_scenery(const SGGeod& position, double range_m, double duration=0.0);
|
||||
void materialLibChanged();
|
||||
|
||||
static const char* subsystemName() { return "scenery"; }
|
||||
|
||||
private:
|
||||
// The state of the scene graph.
|
||||
// the terrain engine
|
||||
FGTerrain* _terrain;
|
||||
|
||||
// The state of the scene graph.
|
||||
bool _inited;
|
||||
};
|
||||
|
||||
|
||||
#endif // _SCENERY_HXX
|
||||
|
||||
|
||||
|
|
112
src/Scenery/terrain.hxx
Normal file
112
src/Scenery/terrain.hxx
Normal file
|
@ -0,0 +1,112 @@
|
|||
// scenery.hxx -- 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$
|
||||
|
||||
|
||||
#ifndef _TERRAIN_HXX
|
||||
#define _TERRAIN_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Switch>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/scene/model/particles.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
|
||||
#include "scenery.hxx"
|
||||
#include "SceneryPager.hxx"
|
||||
#include "tilemgr.hxx"
|
||||
|
||||
namespace simgear {
|
||||
class BVHMaterial;
|
||||
}
|
||||
|
||||
// Define a structure containing global scenery parameters
|
||||
class FGTerrain
|
||||
{
|
||||
public:
|
||||
FGTerrain() {};
|
||||
~FGTerrain() {};
|
||||
|
||||
// Implementation of SGSubsystem. - called from Scenery
|
||||
virtual void init ( osg::Group* terrain ) = 0;
|
||||
virtual void reinit() = 0;
|
||||
virtual void shutdown () = 0;
|
||||
virtual void bind () = 0;
|
||||
virtual void unbind () = 0;
|
||||
virtual void update (double dt) = 0;
|
||||
|
||||
/// Compute the elevation of the scenery at geodetic latitude lat,
|
||||
/// geodetic longitude lon and not higher than max_alt.
|
||||
/// If the exact flag is set to true, the scenery center is moved to
|
||||
/// gain a higher accuracy of that query. The center is restored past
|
||||
/// that to the original value.
|
||||
/// The altitude hit is returned in the alt argument.
|
||||
/// The method returns true if the scenery is available for the given
|
||||
/// lat/lon pair. If there is no scenery for that point, the altitude
|
||||
/// value is undefined.
|
||||
/// All values are meant to be in meters or degrees.
|
||||
virtual bool get_elevation_m(const SGGeod& geod, double& alt,
|
||||
const simgear::BVHMaterial** material,
|
||||
const osg::Node* butNotFrom = 0) = 0;
|
||||
|
||||
/// Compute the elevation of the scenery below the cartesian point pos.
|
||||
/// you the returned scenery altitude is not higher than the position
|
||||
/// pos plus an offset given with max_altoff.
|
||||
/// If the exact flag is set to true, the scenery center is moved to
|
||||
/// gain a higher accuracy of that query. The center is restored past
|
||||
/// that to the original value.
|
||||
/// The altitude hit is returned in the alt argument.
|
||||
/// The method returns true if the scenery is available for the given
|
||||
/// lat/lon pair. If there is no scenery for that point, the altitude
|
||||
/// value is undefined.
|
||||
/// All values are meant to be in meters.
|
||||
virtual bool get_cart_elevation_m(const SGVec3d& pos, double max_altoff,
|
||||
double& elevation,
|
||||
const simgear::BVHMaterial** material,
|
||||
const osg::Node* butNotFrom = 0) = 0;
|
||||
|
||||
/// Compute the nearest intersection point of the line starting from
|
||||
/// start going in direction dir with the terrain.
|
||||
/// The input and output values should be in cartesian coordinates in the
|
||||
/// usual earth centered wgs84 coordinate system. Units are meters.
|
||||
/// On success, true is returned.
|
||||
virtual bool get_cart_ground_intersection(const SGVec3d& start, const SGVec3d& dir,
|
||||
SGVec3d& nearestHit,
|
||||
const osg::Node* butNotFrom = 0) = 0;
|
||||
|
||||
/// Returns true if scenery is available for the given lat, lon position
|
||||
/// within a range of range_m.
|
||||
/// lat and lon are expected to be in degrees.
|
||||
virtual bool scenery_available(const SGGeod& position, double range_m) = 0;
|
||||
|
||||
// tile mgr api
|
||||
virtual bool schedule_scenery(const SGGeod& position, double range_m, double duration=0.0) = 0;
|
||||
virtual void materialLibChanged() = 0;
|
||||
};
|
||||
|
||||
#endif // _TERRAIN_HXX
|
252
src/Scenery/terrain_pgt.cxx
Normal file
252
src/Scenery/terrain_pgt.cxx
Normal file
|
@ -0,0 +1,252 @@
|
|||
// 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$
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#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());
|
||||
|
||||
options->setPluginStringData("SimGear::BARE_LOD_RANGE", fgGetString("/sim/rendering/static-lod/bare", boost::lexical_cast<string>(SG_OBJECT_RANGE_BARE)));
|
||||
options->setPluginStringData("SimGear::ROUGH_LOD_RANGE", fgGetString("/sim/rendering/static-lod/rough", boost::lexical_cast<string>(SG_OBJECT_RANGE_ROUGH)));
|
||||
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" );
|
||||
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile("w180s90-360x180.pgt", options.get());
|
||||
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
|
127
src/Scenery/terrain_pgt.hxx
Normal file
127
src/Scenery/terrain_pgt.hxx
Normal file
|
@ -0,0 +1,127 @@
|
|||
// terrain_pgt.hxx -- 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$
|
||||
|
||||
|
||||
#ifndef _TERRAIN_PGT_HXX
|
||||
#define _TERRAIN_PGT_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Switch>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/scene/model/particles.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/scene/dem/SGDem.hxx>
|
||||
|
||||
#include "terrain.hxx"
|
||||
//#include "SceneryPager.hxx"
|
||||
//#include "tilemgr.hxx"
|
||||
|
||||
namespace simgear {
|
||||
class BVHMaterial;
|
||||
}
|
||||
|
||||
// Define a structure containing global scenery parameters
|
||||
class FGPgtTerrain : public FGTerrain
|
||||
{
|
||||
public:
|
||||
|
||||
FGPgtTerrain();
|
||||
~FGPgtTerrain();
|
||||
|
||||
// Implementation of SGSubsystem.
|
||||
void init ( osg::Group* terrain );
|
||||
void reinit();
|
||||
void shutdown ();
|
||||
void bind ();
|
||||
void unbind ();
|
||||
void update (double dt);
|
||||
|
||||
/// Compute the elevation of the scenery at geodetic latitude lat,
|
||||
/// geodetic longitude lon and not higher than max_alt.
|
||||
/// If the exact flag is set to true, the scenery center is moved to
|
||||
/// gain a higher accuracy of that query. The center is restored past
|
||||
/// that to the original value.
|
||||
/// The altitude hit is returned in the alt argument.
|
||||
/// The method returns true if the scenery is available for the given
|
||||
/// lat/lon pair. If there is no scenery for that point, the altitude
|
||||
/// value is undefined.
|
||||
/// All values are meant to be in meters or degrees.
|
||||
bool get_elevation_m(const SGGeod& geod, double& alt,
|
||||
const simgear::BVHMaterial** material,
|
||||
const osg::Node* butNotFrom = 0);
|
||||
|
||||
/// Compute the elevation of the scenery below the cartesian point pos.
|
||||
/// you the returned scenery altitude is not higher than the position
|
||||
/// pos plus an offset given with max_altoff.
|
||||
/// If the exact flag is set to true, the scenery center is moved to
|
||||
/// gain a higher accuracy of that query. The center is restored past
|
||||
/// that to the original value.
|
||||
/// The altitude hit is returned in the alt argument.
|
||||
/// The method returns true if the scenery is available for the given
|
||||
/// lat/lon pair. If there is no scenery for that point, the altitude
|
||||
/// value is undefined.
|
||||
/// All values are meant to be in meters.
|
||||
bool get_cart_elevation_m(const SGVec3d& pos, double max_altoff,
|
||||
double& elevation,
|
||||
const simgear::BVHMaterial** material,
|
||||
const osg::Node* butNotFrom = 0);
|
||||
|
||||
/// Compute the nearest intersection point of the line starting from
|
||||
/// start going in direction dir with the terrain.
|
||||
/// The input and output values should be in cartesian coordinates in the
|
||||
/// usual earth centered wgs84 coordinate system. Units are meters.
|
||||
/// On success, true is returned.
|
||||
bool get_cart_ground_intersection(const SGVec3d& start, const SGVec3d& dir,
|
||||
SGVec3d& nearestHit,
|
||||
const osg::Node* butNotFrom = 0);
|
||||
|
||||
/// Returns true if scenery is available for the given lat, lon position
|
||||
/// within a range of range_m.
|
||||
/// lat and lon are expected to be in degrees.
|
||||
bool scenery_available(const SGGeod& position, double range_m);
|
||||
|
||||
// tile mgr api
|
||||
bool schedule_scenery(const SGGeod& position, double range_m, double duration=0.0);
|
||||
void materialLibChanged();
|
||||
|
||||
static const char* subsystemName() { return "scenery"; }
|
||||
|
||||
private:
|
||||
// terrain branch of scene graph
|
||||
osg::ref_ptr<osg::Group> terrain_branch;
|
||||
|
||||
SGPropertyNode_ptr _scenery_loaded, _scenery_override;
|
||||
|
||||
bool _inited;
|
||||
|
||||
SGDemPtr _dem;
|
||||
};
|
||||
|
||||
#endif // _TERRAIN_PGT_HXX
|
409
src/Scenery/terrain_stg.cxx
Normal file
409
src/Scenery/terrain_stg.cxx
Normal file
|
@ -0,0 +1,409 @@
|
|||
// scenery.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$
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <osg/Camera>
|
||||
#include <osg/Transform>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osg/CameraView>
|
||||
#include <osg/LOD>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/scene/tgdb/userdata.hxx>
|
||||
#include <simgear/scene/material/matlib.hxx>
|
||||
#include <simgear/scene/material/mat.hxx>
|
||||
#include <simgear/scene/util/SGNodeMasks.hxx>
|
||||
#include <simgear/scene/util/OsgMath.hxx>
|
||||
#include <simgear/scene/util/SGSceneUserData.hxx>
|
||||
#include <simgear/scene/model/CheckSceneryVisitor.hxx>
|
||||
#include <simgear/scene/sky/sky.hxx>
|
||||
|
||||
#include <simgear/bvh/BVHNode.hxx>
|
||||
#include <simgear/bvh/BVHLineSegmentVisitor.hxx>
|
||||
#include <simgear/structure/commands.hxx>
|
||||
|
||||
#include <Viewer/renderer.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <GUI/MouseCursor.hxx>
|
||||
|
||||
#include "terrain_stg.hxx"
|
||||
|
||||
using namespace flightgear;
|
||||
using namespace simgear;
|
||||
|
||||
class FGGroundPickCallback : public SGPickCallback {
|
||||
public:
|
||||
FGGroundPickCallback() : SGPickCallback(PriorityScenery)
|
||||
{ }
|
||||
|
||||
virtual bool buttonPressed( int button,
|
||||
const osgGA::GUIEventAdapter&,
|
||||
const Info& info )
|
||||
{
|
||||
// only on left mouse button
|
||||
if (button != 0)
|
||||
return false;
|
||||
|
||||
SGGeod geod = SGGeod::fromCart(info.wgs84);
|
||||
SG_LOG( SG_TERRAIN, SG_INFO, "Got ground pick at " << geod );
|
||||
|
||||
SGPropertyNode *c = fgGetNode("/sim/input/click", true);
|
||||
c->setDoubleValue("longitude-deg", geod.getLongitudeDeg());
|
||||
c->setDoubleValue("latitude-deg", geod.getLatitudeDeg());
|
||||
c->setDoubleValue("elevation-m", geod.getElevationM());
|
||||
c->setDoubleValue("elevation-ft", geod.getElevationFt());
|
||||
fgSetBool("/sim/signals/click", 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class FGSceneryIntersect : public osg::NodeVisitor {
|
||||
public:
|
||||
FGSceneryIntersect(const SGLineSegmentd& lineSegment,
|
||||
const osg::Node* skipNode) :
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
|
||||
_lineSegment(lineSegment),
|
||||
_skipNode(skipNode),
|
||||
_material(0),
|
||||
_haveHit(false)
|
||||
{ }
|
||||
|
||||
bool getHaveHit() const
|
||||
{ return _haveHit; }
|
||||
const SGLineSegmentd& getLineSegment() const
|
||||
{ return _lineSegment; }
|
||||
const simgear::BVHMaterial* getMaterial() const
|
||||
{ return _material; }
|
||||
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
if (&node == _skipNode)
|
||||
return;
|
||||
if (!testBoundingSphere(node.getBound()))
|
||||
return;
|
||||
|
||||
addBoundingVolume(node);
|
||||
}
|
||||
|
||||
virtual void apply(osg::Group& group)
|
||||
{
|
||||
if (&group == _skipNode)
|
||||
return;
|
||||
if (!testBoundingSphere(group.getBound()))
|
||||
return;
|
||||
|
||||
traverse(group);
|
||||
addBoundingVolume(group);
|
||||
}
|
||||
|
||||
virtual void apply(osg::Transform& transform)
|
||||
{ handleTransform(transform); }
|
||||
virtual void apply(osg::Camera& camera)
|
||||
{
|
||||
if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
|
||||
return;
|
||||
handleTransform(camera);
|
||||
}
|
||||
virtual void apply(osg::CameraView& transform)
|
||||
{ handleTransform(transform); }
|
||||
virtual void apply(osg::MatrixTransform& transform)
|
||||
{ handleTransform(transform); }
|
||||
virtual void apply(osg::PositionAttitudeTransform& transform)
|
||||
{ handleTransform(transform); }
|
||||
|
||||
private:
|
||||
void handleTransform(osg::Transform& transform)
|
||||
{
|
||||
if (&transform == _skipNode)
|
||||
return;
|
||||
// Hmm, may be this needs to be refined somehow ...
|
||||
if (transform.getReferenceFrame() != osg::Transform::RELATIVE_RF)
|
||||
return;
|
||||
|
||||
if (!testBoundingSphere(transform.getBound()))
|
||||
return;
|
||||
|
||||
osg::Matrix inverseMatrix;
|
||||
if (!transform.computeWorldToLocalMatrix(inverseMatrix, this))
|
||||
return;
|
||||
osg::Matrix matrix;
|
||||
if (!transform.computeLocalToWorldMatrix(matrix, this))
|
||||
return;
|
||||
|
||||
SGLineSegmentd lineSegment = _lineSegment;
|
||||
bool haveHit = _haveHit;
|
||||
const simgear::BVHMaterial* material = _material;
|
||||
|
||||
_haveHit = false;
|
||||
_lineSegment = lineSegment.transform(SGMatrixd(inverseMatrix.ptr()));
|
||||
|
||||
addBoundingVolume(transform);
|
||||
traverse(transform);
|
||||
|
||||
if (_haveHit) {
|
||||
_lineSegment = _lineSegment.transform(SGMatrixd(matrix.ptr()));
|
||||
} else {
|
||||
_lineSegment = lineSegment;
|
||||
_material = material;
|
||||
_haveHit = haveHit;
|
||||
}
|
||||
}
|
||||
|
||||
simgear::BVHNode* getNodeBoundingVolume(osg::Node& node)
|
||||
{
|
||||
SGSceneUserData* userData = SGSceneUserData::getSceneUserData(&node);
|
||||
if (!userData)
|
||||
return 0;
|
||||
return userData->getBVHNode();
|
||||
}
|
||||
void addBoundingVolume(osg::Node& node)
|
||||
{
|
||||
simgear::BVHNode* bvNode = getNodeBoundingVolume(node);
|
||||
if (!bvNode)
|
||||
return;
|
||||
|
||||
// Find ground intersection on the bvh nodes
|
||||
simgear::BVHLineSegmentVisitor lineSegmentVisitor(_lineSegment,
|
||||
0/*startTime*/);
|
||||
bvNode->accept(lineSegmentVisitor);
|
||||
if (!lineSegmentVisitor.empty()) {
|
||||
_lineSegment = lineSegmentVisitor.getLineSegment();
|
||||
_material = lineSegmentVisitor.getMaterial();
|
||||
_haveHit = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool testBoundingSphere(const osg::BoundingSphere& bound) const
|
||||
{
|
||||
if (!bound.valid())
|
||||
return false;
|
||||
|
||||
SGSphered sphere(toVec3d(toSG(bound._center)), bound._radius);
|
||||
return intersects(_lineSegment, sphere);
|
||||
}
|
||||
|
||||
SGLineSegmentd _lineSegment;
|
||||
const osg::Node* _skipNode;
|
||||
|
||||
const simgear::BVHMaterial* _material;
|
||||
bool _haveHit;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Terrain Management system
|
||||
FGStgTerrain::FGStgTerrain() :
|
||||
_tilemgr()
|
||||
{
|
||||
_inited = false;
|
||||
}
|
||||
|
||||
FGStgTerrain::~FGStgTerrain()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Initialize the Scenery Management system
|
||||
void FGStgTerrain::init( osg::Group* terrain ) {
|
||||
// Already set up.
|
||||
if (_inited)
|
||||
return;
|
||||
|
||||
SG_LOG(SG_TERRAIN, SG_INFO, "FGStgTerrain::init - init tilemgr");
|
||||
|
||||
// remember the scene terrain branch on scenegraph
|
||||
terrain_branch = terrain;
|
||||
|
||||
// initialize the tile manager
|
||||
_tilemgr.init();
|
||||
|
||||
// Toggle the setup flag.
|
||||
_inited = true;
|
||||
}
|
||||
|
||||
void FGStgTerrain::reinit()
|
||||
{
|
||||
SG_LOG(SG_TERRAIN, SG_INFO, "FGStgTerrain::reinit - reinit tilemgr");
|
||||
|
||||
_tilemgr.reinit();
|
||||
}
|
||||
|
||||
void FGStgTerrain::shutdown()
|
||||
{
|
||||
SG_LOG(SG_TERRAIN, SG_INFO, "FGStgTerrain::shutdown - shutdown tilemgr");
|
||||
|
||||
_tilemgr.shutdown();
|
||||
|
||||
terrain_branch = NULL;
|
||||
|
||||
// Toggle the setup flag.
|
||||
_inited = false;
|
||||
}
|
||||
|
||||
|
||||
void FGStgTerrain::update(double dt)
|
||||
{
|
||||
_tilemgr.update(dt);
|
||||
}
|
||||
|
||||
void FGStgTerrain::bind()
|
||||
{
|
||||
SG_LOG(SG_TERRAIN, SG_INFO, "FGStgTerrain::bind - noop");
|
||||
}
|
||||
|
||||
void FGStgTerrain::unbind()
|
||||
{
|
||||
SG_LOG(SG_TERRAIN, SG_INFO, "FGStgTerrain::unbind - noop");
|
||||
}
|
||||
|
||||
bool
|
||||
FGStgTerrain::get_cart_elevation_m(const SGVec3d& pos, double max_altoff,
|
||||
double& alt,
|
||||
const simgear::BVHMaterial** material,
|
||||
const osg::Node* butNotFrom)
|
||||
{
|
||||
bool ok;
|
||||
|
||||
SGGeod geod = SGGeod::fromCart(pos);
|
||||
geod.setElevationM(geod.getElevationM() + max_altoff);
|
||||
|
||||
ok = get_elevation_m(geod, alt, material, butNotFrom);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool
|
||||
FGStgTerrain::get_elevation_m(const SGGeod& geod, double& alt,
|
||||
const simgear::BVHMaterial** material,
|
||||
const osg::Node* butNotFrom)
|
||||
{
|
||||
SGVec3d start = SGVec3d::fromGeod(geod);
|
||||
|
||||
SGGeod geodEnd = geod;
|
||||
geodEnd.setElevationM(SGMiscd::min(geod.getElevationM() - 10, -10000));
|
||||
SGVec3d end = SGVec3d::fromGeod(geodEnd);
|
||||
|
||||
FGSceneryIntersect intersectVisitor(SGLineSegmentd(start, end), butNotFrom);
|
||||
intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
|
||||
terrain_branch->accept(intersectVisitor);
|
||||
|
||||
if (!intersectVisitor.getHaveHit())
|
||||
return false;
|
||||
|
||||
geodEnd = SGGeod::fromCart(intersectVisitor.getLineSegment().getEnd());
|
||||
alt = geodEnd.getElevationM();
|
||||
if (material) {
|
||||
*material = intersectVisitor.getMaterial();
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "FGStgTerrain::get_elevation_m: alt " << alt << " material " << *material );
|
||||
} else {
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "FGStgTerrain::get_elevation_m: alt " << alt << " no material " );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FGStgTerrain::get_cart_ground_intersection(const SGVec3d& pos, const SGVec3d& dir,
|
||||
SGVec3d& nearestHit,
|
||||
const osg::Node* butNotFrom)
|
||||
{
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "FGStgTerrain::get_cart_ground_intersection");
|
||||
|
||||
// We assume that starting positions in the center of the earth are invalid
|
||||
if ( norm1(pos) < 1 )
|
||||
return false;
|
||||
|
||||
// Make really sure the direction is normalized, is really cheap compared to
|
||||
// computation of ground intersection.
|
||||
SGVec3d start = pos;
|
||||
SGVec3d end = start + 1e5*normalize(dir); // FIXME visibility ???
|
||||
|
||||
FGSceneryIntersect intersectVisitor(SGLineSegmentd(start, end), butNotFrom);
|
||||
intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
|
||||
terrain_branch->accept(intersectVisitor);
|
||||
|
||||
if (!intersectVisitor.getHaveHit())
|
||||
return false;
|
||||
|
||||
nearestHit = intersectVisitor.getLineSegment().getEnd();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FGStgTerrain::scenery_available(const SGGeod& position, double range_m)
|
||||
{
|
||||
if( schedule_scenery(position, range_m, 0.0) )
|
||||
{
|
||||
double elev;
|
||||
if (!get_elevation_m(SGGeod::fromGeodM(position, SG_MAX_ELEVATION_M), elev, 0, 0))
|
||||
{
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "FGStgTerrain::scenery_available - false" );
|
||||
return false;
|
||||
}
|
||||
|
||||
SGVec3f p = SGVec3f::fromGeod(SGGeod::fromGeodM(position, elev));
|
||||
osg::FrameStamp* framestamp
|
||||
= globals->get_renderer()->getViewer()->getFrameStamp();
|
||||
|
||||
FGScenery* pSceneryManager = globals->get_scenery();
|
||||
simgear::CheckSceneryVisitor csnv(pSceneryManager->getPager(), toOsg(p), range_m, framestamp);
|
||||
// currently the PagedLODs will not be loaded by the DatabasePager
|
||||
// while the splashscreen is there, so CheckSceneryVisitor force-loads
|
||||
// missing objects in the main thread
|
||||
terrain_branch->accept(csnv);
|
||||
if(!csnv.isLoaded()) {
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "FGScenery::scenery_available: waiting on CheckSceneryVisitor");
|
||||
return false;
|
||||
}
|
||||
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "FGStgTerrain::scenery_available - true" );
|
||||
return true;
|
||||
} else {
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "FGScenery::scenery_available: waiting on tile manager");
|
||||
}
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "FGStgTerrain::scenery_available - false" );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FGStgTerrain::schedule_scenery(const SGGeod& position, double range_m, double duration)
|
||||
{
|
||||
SG_LOG(SG_TERRAIN, SG_BULK, "FGStgTerrain::schedule_scenery");
|
||||
|
||||
return _tilemgr.schedule_scenery( position, range_m, duration );
|
||||
}
|
||||
|
||||
void FGStgTerrain::materialLibChanged()
|
||||
{
|
||||
_tilemgr.materialLibChanged();
|
||||
}
|
126
src/Scenery/terrain_stg.hxx
Normal file
126
src/Scenery/terrain_stg.hxx
Normal file
|
@ -0,0 +1,126 @@
|
|||
// scenery.hxx -- 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$
|
||||
|
||||
|
||||
#ifndef _TERRAIN_STG_HXX
|
||||
#define _TERRAIN_STG_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Switch>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/scene/model/particles.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
|
||||
#include "terrain.hxx"
|
||||
#include "SceneryPager.hxx"
|
||||
#include "tilemgr.hxx"
|
||||
|
||||
namespace simgear {
|
||||
class BVHMaterial;
|
||||
}
|
||||
|
||||
// Define a structure containing global scenery parameters
|
||||
class FGStgTerrain : public FGTerrain
|
||||
{
|
||||
public:
|
||||
|
||||
FGStgTerrain();
|
||||
~FGStgTerrain();
|
||||
|
||||
// Implementation of SGSubsystem.
|
||||
void init ( osg::Group* terrain );
|
||||
void reinit();
|
||||
void shutdown ();
|
||||
void bind ();
|
||||
void unbind ();
|
||||
void update (double dt);
|
||||
|
||||
/// Compute the elevation of the scenery at geodetic latitude lat,
|
||||
/// geodetic longitude lon and not higher than max_alt.
|
||||
/// If the exact flag is set to true, the scenery center is moved to
|
||||
/// gain a higher accuracy of that query. The center is restored past
|
||||
/// that to the original value.
|
||||
/// The altitude hit is returned in the alt argument.
|
||||
/// The method returns true if the scenery is available for the given
|
||||
/// lat/lon pair. If there is no scenery for that point, the altitude
|
||||
/// value is undefined.
|
||||
/// All values are meant to be in meters or degrees.
|
||||
bool get_elevation_m(const SGGeod& geod, double& alt,
|
||||
const simgear::BVHMaterial** material,
|
||||
const osg::Node* butNotFrom = 0);
|
||||
|
||||
/// Compute the elevation of the scenery below the cartesian point pos.
|
||||
/// you the returned scenery altitude is not higher than the position
|
||||
/// pos plus an offset given with max_altoff.
|
||||
/// If the exact flag is set to true, the scenery center is moved to
|
||||
/// gain a higher accuracy of that query. The center is restored past
|
||||
/// that to the original value.
|
||||
/// The altitude hit is returned in the alt argument.
|
||||
/// The method returns true if the scenery is available for the given
|
||||
/// lat/lon pair. If there is no scenery for that point, the altitude
|
||||
/// value is undefined.
|
||||
/// All values are meant to be in meters.
|
||||
bool get_cart_elevation_m(const SGVec3d& pos, double max_altoff,
|
||||
double& elevation,
|
||||
const simgear::BVHMaterial** material,
|
||||
const osg::Node* butNotFrom = 0);
|
||||
|
||||
/// Compute the nearest intersection point of the line starting from
|
||||
/// start going in direction dir with the terrain.
|
||||
/// The input and output values should be in cartesian coordinates in the
|
||||
/// usual earth centered wgs84 coordinate system. Units are meters.
|
||||
/// On success, true is returned.
|
||||
bool get_cart_ground_intersection(const SGVec3d& start, const SGVec3d& dir,
|
||||
SGVec3d& nearestHit,
|
||||
const osg::Node* butNotFrom = 0);
|
||||
|
||||
/// Returns true if scenery is available for the given lat, lon position
|
||||
/// within a range of range_m.
|
||||
/// lat and lon are expected to be in degrees.
|
||||
bool scenery_available(const SGGeod& position, double range_m);
|
||||
|
||||
// tile mgr api
|
||||
bool schedule_scenery(const SGGeod& position, double range_m, double duration=0.0);
|
||||
void materialLibChanged();
|
||||
|
||||
static const char* subsystemName() { return "scenery"; }
|
||||
|
||||
private:
|
||||
// tile manager
|
||||
FGTileMgr _tilemgr;
|
||||
|
||||
// terrain branch of scene graph
|
||||
osg::ref_ptr<osg::Group> terrain_branch;
|
||||
|
||||
bool _inited;
|
||||
};
|
||||
|
||||
#endif // _TERRAIN_STG_HXX
|
||||
|
||||
|
|
@ -65,12 +65,12 @@ public:
|
|||
_pagedLODMaximumProp(fgGetNode("/sim/rendering/max-paged-lod", true))
|
||||
{
|
||||
_useVBOsProp->addChangeListener(this, true);
|
||||
|
||||
|
||||
_enableCacheProp->addChangeListener(this, true);
|
||||
if (_enableCacheProp->getType() == simgear::props::NONE) {
|
||||
_enableCacheProp->setBoolValue(true);
|
||||
}
|
||||
|
||||
|
||||
if (_pagedLODMaximumProp->getType() == simgear::props::NONE) {
|
||||
// not set, use OSG default / environment value variable
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer(globals->get_renderer()->getViewer());
|
||||
|
@ -79,14 +79,14 @@ public:
|
|||
}
|
||||
_pagedLODMaximumProp->addChangeListener(this, true);
|
||||
}
|
||||
|
||||
|
||||
~TileManagerListener()
|
||||
{
|
||||
_useVBOsProp->removeChangeListener(this);
|
||||
_enableCacheProp->removeChangeListener(this);
|
||||
_pagedLODMaximumProp->removeChangeListener(this);
|
||||
}
|
||||
|
||||
|
||||
virtual void valueChanged(SGPropertyNode* prop)
|
||||
{
|
||||
if (prop == _useVBOsProp) {
|
||||
|
@ -101,7 +101,7 @@ public:
|
|||
viewer->getDatabasePager()->setTargetMaximumNumberOfPageLOD(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
FGTileMgr* _manager;
|
||||
SGPropertyNode_ptr _useVBOsProp,
|
||||
|
@ -128,8 +128,7 @@ FGTileMgr::FGTileMgr():
|
|||
|
||||
FGTileMgr::~FGTileMgr()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Initialize the Tile Manager subsystem
|
||||
void FGTileMgr::init()
|
||||
|
@ -160,10 +159,10 @@ void FGTileMgr::reinit()
|
|||
// drops the previous options reference
|
||||
_options = new simgear::SGReaderWriterOptions;
|
||||
_listener = new TileManagerListener(this);
|
||||
|
||||
|
||||
materialLibChanged();
|
||||
_options->setPropertyNode(globals->get_props());
|
||||
|
||||
|
||||
osgDB::FilePathList &fp = _options->getDatabasePathList();
|
||||
const PathList &sc = globals->get_fg_scenery();
|
||||
fp.clear();
|
||||
|
@ -172,11 +171,11 @@ void FGTileMgr::reinit()
|
|||
fp.push_back(it->local8BitStr());
|
||||
}
|
||||
_options->setPluginStringData("SimGear::FG_ROOT", globals->get_fg_root().local8BitStr());
|
||||
|
||||
|
||||
if (_terra_sync) {
|
||||
_options->setPluginStringData("SimGear::TERRASYNC_ROOT", globals->get_terrasync_dir().local8BitStr());
|
||||
}
|
||||
|
||||
|
||||
if (!_disableNasalHooks->getBoolValue())
|
||||
_options->setModelData(new FGNasalModelDataProxy);
|
||||
|
||||
|
@ -197,7 +196,7 @@ void FGTileMgr::reinit()
|
|||
}
|
||||
|
||||
_options->setSceneryPathSuffixes(scenerySuffixes);
|
||||
|
||||
|
||||
if (state != Start)
|
||||
{
|
||||
// protect against multiple scenery reloads and properly reset flags,
|
||||
|
@ -207,25 +206,25 @@ void FGTileMgr::reinit()
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_scenery_loaded->setBoolValue(false);
|
||||
fgSetDouble("/sim/startup/splash-alpha", 1.0);
|
||||
|
||||
|
||||
materialLibChanged();
|
||||
|
||||
// remove all old scenery nodes from scenegraph and clear cache
|
||||
osg::Group* group = globals->get_scenery()->get_terrain_branch();
|
||||
group->removeChildren(0, group->getNumChildren());
|
||||
tile_cache.init();
|
||||
|
||||
|
||||
// clear OSG cache, except on initial start-up
|
||||
if (state != Start)
|
||||
{
|
||||
osgDB::Registry::instance()->clearObjectCache();
|
||||
}
|
||||
|
||||
|
||||
state = Inited;
|
||||
|
||||
|
||||
previous_bucket.make_bad();
|
||||
current_bucket.make_bad();
|
||||
scheduled_visibility = 100.0;
|
||||
|
@ -293,7 +292,7 @@ void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis)
|
|||
"scheduling needed tiles for " << curr_bucket
|
||||
<< ", tile-width-m:" << tile_width << ", tile-height-m:" << tile_height);
|
||||
|
||||
|
||||
|
||||
// cout << "tile width = " << tile_width << " tile_height = "
|
||||
// << tile_height << endl;
|
||||
|
||||
|
@ -310,7 +309,7 @@ void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis)
|
|||
// cout << "max cache size = " << tile_cache.get_max_cache_size()
|
||||
// << " current cache size = " << tile_cache.get_size() << endl;
|
||||
|
||||
// clear flags of all tiles belonging to the previous view set
|
||||
// clear flags of all tiles belonging to the previous view set
|
||||
tile_cache.clear_current_view();
|
||||
|
||||
// update timestamps, so all tiles scheduled now are *newer* than any tile previously loaded
|
||||
|
@ -332,10 +331,10 @@ void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis)
|
|||
if (!b.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
float priority = (-1.0) * (x*x+y*y);
|
||||
sched_tile( b, priority, true, 0.0 );
|
||||
|
||||
|
||||
if (_terra_sync) {
|
||||
_terra_sync->scheduleTile(b);
|
||||
}
|
||||
|
@ -356,7 +355,7 @@ void FGTileMgr::update_queues(bool& isDownloadingScenery)
|
|||
TileEntry *e;
|
||||
int loading=0;
|
||||
int sz=0;
|
||||
|
||||
|
||||
tile_cache.set_current_time( current_time );
|
||||
tile_cache.reset_traversal();
|
||||
|
||||
|
@ -369,7 +368,7 @@ void FGTileMgr::update_queues(bool& isDownloadingScenery)
|
|||
// Set the ssg transform and update it's range selector
|
||||
// based on current visibilty
|
||||
e->prep_ssg_node(vis);
|
||||
|
||||
|
||||
if (!e->is_loaded()) {
|
||||
bool nonExpiredOrCurrent = !e->is_expired(current_time) || e->is_current_view();
|
||||
bool downloading = isTileDirSyncing(e->tileFileName);
|
||||
|
@ -400,7 +399,7 @@ void FGTileMgr::update_queues(bool& isDownloadingScenery)
|
|||
dropTiles = true;
|
||||
drop_count = sz; // no limit on tiles to drop
|
||||
}
|
||||
|
||||
|
||||
if (dropTiles)
|
||||
{
|
||||
long drop_index = _enableCache ? tile_cache.get_drop_tile() :
|
||||
|
@ -412,14 +411,14 @@ void FGTileMgr::update_queues(bool& isDownloadingScenery)
|
|||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Dropping:" << old->get_tile_bucket());
|
||||
|
||||
tile_cache.clear_entry(drop_index);
|
||||
|
||||
|
||||
osg::ref_ptr<osg::Object> subgraph = old->getNode();
|
||||
old->removeFromSceneGraph();
|
||||
delete old;
|
||||
// zeros out subgraph ref_ptr, so subgraph is owned by
|
||||
// the pager and will be deleted in the pager thread.
|
||||
_pager->queueDeleteRequest(subgraph);
|
||||
|
||||
|
||||
if (!_enableCache)
|
||||
drop_index = tile_cache.get_first_expired_tile();
|
||||
// limit tiles dropped to drop_count
|
||||
|
@ -448,8 +447,8 @@ void FGTileMgr::update(double)
|
|||
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 || (isSceneryLoaded() && fdmInited)))
|
||||
|
@ -466,7 +465,7 @@ void FGTileMgr::update(double)
|
|||
} else {
|
||||
fgSplashProgress("loading-scenery");
|
||||
}
|
||||
|
||||
|
||||
// be nice to loader threads while waiting for initial scenery, reduce to 20fps
|
||||
SGTimeStamp::sleepForMSec(50);
|
||||
}
|
||||
|
@ -506,7 +505,7 @@ void FGTileMgr::schedule_tiles_at(const SGGeod& location, double range_m)
|
|||
scheduled_visibility = range_m;
|
||||
schedule_needed(current_bucket, range_m);
|
||||
}
|
||||
|
||||
|
||||
// save bucket
|
||||
previous_bucket = current_bucket;
|
||||
} else if ( state == Start || state == Inited ) {
|
||||
|
@ -533,7 +532,7 @@ bool FGTileMgr::schedule_scenery(const SGGeod& position, double range_m, double
|
|||
|
||||
SGBucket bucket(position);
|
||||
available = sched_tile( bucket, priority, false, duration );
|
||||
|
||||
|
||||
if ((!available)&&(duration==0.0)) {
|
||||
SG_LOG( SG_TERRAIN, SG_DEBUG, "schedule_scenery: Scheduling tile at bucket:" << bucket << " return false" );
|
||||
return false;
|
||||
|
@ -547,7 +546,7 @@ bool FGTileMgr::schedule_scenery(const SGGeod& position, double range_m, double
|
|||
double tile_r = 0.5*sqrt(tile_width*tile_width + tile_height*tile_height);
|
||||
double max_dist = tile_r + range_m;
|
||||
double max_dist2 = max_dist*max_dist;
|
||||
|
||||
|
||||
int xrange = (int)fabs(range_m / tile_width) + 1;
|
||||
int yrange = (int)fabs(range_m / tile_height) + 1;
|
||||
|
||||
|
@ -562,7 +561,7 @@ bool FGTileMgr::schedule_scenery(const SGGeod& position, double range_m, double
|
|||
if (!b.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
double distance2 = distSqr(cartPos, SGVec3d::fromGeod(b.get_center()));
|
||||
// Do not ask if it is just the next tile but way out of range.
|
||||
if (distance2 <= max_dist2)
|
||||
|
@ -593,10 +592,11 @@ bool FGTileMgr::isTileDirSyncing(const std::string& tileFileName) const
|
|||
if (!_terra_sync) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::string nameWithoutExtension = tileFileName.substr(0, tileFileName.size() - 4);
|
||||
long int bucketIndex = simgear::strutils::to_int(nameWithoutExtension);
|
||||
SGBucket bucket(bucketIndex);
|
||||
|
||||
|
||||
return _terra_sync->isTileDirPending(bucket.gen_base_path());
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/bucket/newbucket.hxx>
|
||||
#include "SceneryPager.hxx"
|
||||
#include "tilecache.hxx"
|
||||
|
@ -42,7 +41,7 @@ class SGTerraSync;
|
|||
class SGReaderWriterOptions;
|
||||
}
|
||||
|
||||
class FGTileMgr : public SGSubsystem {
|
||||
class FGTileMgr {
|
||||
|
||||
private:
|
||||
|
||||
|
@ -93,17 +92,16 @@ private:
|
|||
osg::ref_ptr<flightgear::SceneryPager> _pager;
|
||||
|
||||
/// is caching of expired tiles enabled or not?
|
||||
bool _enableCache;
|
||||
bool _enableCache;
|
||||
public:
|
||||
FGTileMgr();
|
||||
~FGTileMgr();
|
||||
|
||||
// Initialize the Tile Manager
|
||||
virtual void init();
|
||||
virtual void reinit();
|
||||
virtual void shutdown();
|
||||
|
||||
virtual void update(double dt);
|
||||
void init();
|
||||
void reinit();
|
||||
void shutdown();
|
||||
void update(double dt);
|
||||
|
||||
const SGBucket& get_current_bucket () const { return current_bucket; }
|
||||
|
||||
|
@ -118,9 +116,6 @@ public:
|
|||
// notify the tile manahger the material library was reloaded,
|
||||
// so it can pass this through to its options object
|
||||
void materialLibChanged();
|
||||
|
||||
static const char* subsystemName() { return "tile-manager"; }
|
||||
};
|
||||
|
||||
|
||||
#endif // _TILEMGR_HXX
|
||||
|
|
|
@ -200,10 +200,6 @@ fgviewerMain(int argc, char** argv)
|
|||
throw sg_io_exception("Error loading materials file", mpath);
|
||||
}
|
||||
|
||||
FGScenery* scenery = globals->add_new_subsystem<FGScenery>();
|
||||
scenery->init();
|
||||
scenery->bind();
|
||||
|
||||
// The file path list must be set in the registry.
|
||||
osgDB::Registry::instance()->getDataFilePathList() = filePathList;
|
||||
|
||||
|
@ -212,7 +208,11 @@ fgviewerMain(int argc, char** argv)
|
|||
options->setMaterialLib(globals->get_matlib());
|
||||
options->setPropertyNode(globals->get_props());
|
||||
options->setPluginStringData("SimGear::PREVIEW", "ON");
|
||||
|
||||
|
||||
FGScenery* scenery = globals->add_new_subsystem<FGScenery>();
|
||||
scenery->init();
|
||||
scenery->bind();
|
||||
|
||||
// read the scene from the list of file specified command line args.
|
||||
osg::ref_ptr<osg::Node> loadedModel;
|
||||
loadedModel = osgDB::readNodeFiles(dataFiles, options);
|
||||
|
|
|
@ -38,3 +38,9 @@ endif()
|
|||
if (ENABLE_FGQCANVAS)
|
||||
add_subdirectory(fgqcanvas)
|
||||
endif()
|
||||
|
||||
if(ENABLE_DEMCONVERT)
|
||||
if(GDALFOUND)
|
||||
add_subdirectory(demconvert)
|
||||
endif()
|
||||
endif()
|
||||
|
|
8
utils/demconvert/CMakeLists.txt
Normal file
8
utils/demconvert/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
add_executable(demconvert demconvert.cxx )
|
||||
|
||||
target_link_libraries(demconvert
|
||||
SimGearScene SimGearCore
|
||||
${GDAL_LIBRARY}
|
||||
)
|
||||
|
||||
install(TARGETS demconvert RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
219
utils/demconvert/demconvert.cxx
Normal file
219
utils/demconvert/demconvert.cxx
Normal file
|
@ -0,0 +1,219 @@
|
|||
// demconvert.cxx -- convert dem into lower resolutions
|
||||
//
|
||||
// Copyright (C) 2016 Peter Sadrozinski
|
||||
//
|
||||
// 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.
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
|
||||
#include <osg/ArgumentParser>
|
||||
|
||||
#include <simgear/misc/stdint.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include <simgear/scene/dem/SGDem.hxx>
|
||||
#include <simgear/scene/dem/SGDemSession.hxx>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string demroot;
|
||||
std::string inputvfp;
|
||||
int tileWidth;
|
||||
int tileHeight;
|
||||
int resx, resy;
|
||||
int overlap = 0;
|
||||
SGDem dem;
|
||||
|
||||
osg::ApplicationUsage* usage = new osg::ApplicationUsage();
|
||||
usage->setApplicationName("demconvert");
|
||||
usage->setCommandLineUsage(
|
||||
"Convert high resolution DEM to low res suitable for terrasync dl.");
|
||||
usage->addCommandLineOption("--inputvfp <dir>", "input VFP root directory");
|
||||
usage->addCommandLineOption("--demroot <dir>", "input/ouput DEM root directory");
|
||||
usage->addCommandLineOption("--width <N>", "width (in degrees) of created tiles");
|
||||
usage->addCommandLineOption("--height <N>", "height (in degrees) of created tiles");
|
||||
usage->addCommandLineOption("--resx <N>", "resolution of created tiles (w/o overlap)");
|
||||
usage->addCommandLineOption("--resy <N>", "resolution of created tiles (w/o overlap)");
|
||||
usage->addCommandLineOption("--overlap <N>", "number of pixels of overlap");
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc, argv);
|
||||
arguments.setApplicationUsage(usage);
|
||||
|
||||
sglog().setLogLevels( SG_TERRAIN, SG_INFO );
|
||||
|
||||
arguments.read("--inputvfp", inputvfp);
|
||||
printf( "--inputvfp is %s\n", inputvfp.c_str() );
|
||||
|
||||
arguments.read("--demroot", demroot);
|
||||
if ( inputvfp.empty() && demroot.empty() ) {
|
||||
arguments.reportError("--inputvfp or --demroot argument required.");
|
||||
} else if ( !demroot.empty() ) {
|
||||
SGPath s(demroot);
|
||||
if (!s.isDir()) {
|
||||
arguments.reportError(
|
||||
"--demroot directory does not exist or is not directory.");
|
||||
} else if (!s.canRead()) {
|
||||
arguments.reportError(
|
||||
"--demroot directory cannot be read. Check permissions.");
|
||||
} else if (!s.canWrite()) {
|
||||
arguments.reportError(
|
||||
"--demroot directory cannot be written. Check permissions.");
|
||||
} else if ( !dem.addRoot(s) ) {
|
||||
// see if we specified input as raw directory
|
||||
if ( inputvfp.empty() ) {
|
||||
arguments.reportError(
|
||||
"--demroot directory is not a DEM heiarchy");
|
||||
} else {
|
||||
// create a new dem heiarchy
|
||||
printf("Creating new dem heiarchy at %s\n", s.c_str() );
|
||||
dem.createRoot(s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SGPath s(inputvfp);
|
||||
if (!s.isDir()) {
|
||||
arguments.reportError(
|
||||
"--inputvfp directory does not exist or is not directory.");
|
||||
} else if (!s.canRead()) {
|
||||
arguments.reportError(
|
||||
"--inputvfp directory cannot be read. Check permissions.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!arguments.read("--width", tileWidth)) {
|
||||
arguments.reportError("--width argument required.");
|
||||
} else {
|
||||
if ( tileWidth < 1 || tileWidth > 60 )
|
||||
arguments.reportError(
|
||||
"--width must be between 1 and 60");
|
||||
}
|
||||
|
||||
if (!arguments.read("--height", tileHeight)) {
|
||||
arguments.reportError("--height argument required.");
|
||||
} else {
|
||||
if ( tileHeight < 1 || tileHeight > 60 )
|
||||
arguments.reportError(
|
||||
"--height must be between 1 and 60");
|
||||
}
|
||||
|
||||
if (!arguments.read("--resx", resx)) {
|
||||
arguments.reportError("--resx argument required.");
|
||||
} else {
|
||||
if ( resx < 2 )
|
||||
arguments.reportError(
|
||||
"--resx must be between greater than 2");
|
||||
}
|
||||
|
||||
if (!arguments.read("--resy", resy)) {
|
||||
arguments.reportError("--resy argument required.");
|
||||
} else {
|
||||
if ( resy < 2 )
|
||||
arguments.reportError(
|
||||
"--resy must be between greater than 2");
|
||||
}
|
||||
|
||||
if (arguments.read("--overlap", overlap)) {
|
||||
if ( overlap > (resx/2) || overlap > (resy/2) )
|
||||
arguments.reportError(
|
||||
"--overlap is greater than half tile");
|
||||
}
|
||||
|
||||
if (arguments.errors()) {
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
arguments.getApplicationUsage()->write(std::cout,
|
||||
osg::ApplicationUsage::COMMAND_LINE_OPTION |
|
||||
osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE, 80, true);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
double lat_dec = (double)tileHeight / (double)resy;
|
||||
double lon_inc = (double)tileWidth / (double)resx;
|
||||
|
||||
SG_LOG( SG_TERRAIN, SG_INFO, "tileWidth: " << tileWidth);
|
||||
SG_LOG( SG_TERRAIN, SG_INFO, "tileHeight: " << tileHeight);
|
||||
SG_LOG( SG_TERRAIN, SG_INFO, "lon_inc: " << lon_inc);
|
||||
SG_LOG( SG_TERRAIN, SG_INFO, "lat_dec: " << lat_dec);
|
||||
|
||||
#define MIN_X -180
|
||||
#define MIN_Y -90
|
||||
#define MAX_X 180
|
||||
#define MAX_Y 90
|
||||
|
||||
// create a new dem level in demRoot
|
||||
SGDemRoot* root = dem.getRoot(0);
|
||||
if ( root ) {
|
||||
int outLvl = root->createLevel( tileWidth, tileHeight, resx, resy, overlap, ".tiff" );
|
||||
if ( outLvl >= 0 ) {
|
||||
printf("SGDem::createLevel success\n");
|
||||
|
||||
// traverse the new tiles, 1 at a time
|
||||
for ( int tilex = MIN_X; tilex < MAX_X; tilex += tileWidth ) {
|
||||
for ( int tiley = MAX_Y; tiley > MIN_Y; tiley -= tileHeight ) {
|
||||
// traverse rows from north to south, then columns west to east
|
||||
double lonmin = (double)tilex;
|
||||
double lonmax = lonmin + (double)tileWidth;
|
||||
double latmax = (double)tiley;
|
||||
double latmin = latmax - (double)tileHeight;
|
||||
|
||||
unsigned wo = SGDem::longitudeDegToOffset(lonmin);
|
||||
unsigned eo = SGDem::longitudeDegToOffset(lonmax);
|
||||
unsigned so = SGDem::latitudeDegToOffset(latmin);
|
||||
unsigned no = SGDem::latitudeDegToOffset(latmax);
|
||||
|
||||
if ( !inputvfp.empty() ) {
|
||||
// read from vfp files
|
||||
printf("open session from raw directory\n");
|
||||
SGDemSession s = dem.openSession( SGGeod::fromDeg(lonmin, latmin), SGGeod::fromDeg(lonmax, latmax), SGPath(inputvfp) );
|
||||
printf("opened session from raw directory\n");
|
||||
|
||||
// create a new dem tile for the new level
|
||||
SGDemTileRef tile = root->createTile( outLvl, (int)lonmin, (int)latmin, overlap, s );
|
||||
|
||||
s.close();
|
||||
} else {
|
||||
// read session from DEM root - don't cache - include adjacent tiles
|
||||
fprintf( stderr, "open session from DEM level %d\n", outLvl-1);
|
||||
SGDemSession s = dem.openSession( wo, so, eo, no, outLvl-1, false );
|
||||
fprintf( stderr, "session has %d tiles\n", s.size() );
|
||||
|
||||
// create a new dem tile for the new level
|
||||
SGDemTileRef tile = root->createTile( outLvl, (int)lonmin, (int)latmin, overlap, s );
|
||||
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("SGDem::close Level \n");
|
||||
|
||||
root->closeLevel( outLvl );
|
||||
} else {
|
||||
printf("SGDem::createLevel failed\n");
|
||||
}
|
||||
} else {
|
||||
printf("SGDem::getRoot failed\n");
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -2,6 +2,7 @@ add_executable(fgelev fgelev.cxx)
|
|||
|
||||
target_link_libraries(fgelev
|
||||
SimGearScene SimGearCore
|
||||
${GDAL_LIBRARY}
|
||||
)
|
||||
|
||||
install(TARGETS fgelev RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
|
|
@ -49,5 +49,6 @@ endif()
|
|||
target_link_libraries(fgviewer
|
||||
SimGearScene SimGearCore
|
||||
${FGVIEWER_RTI_LIBRARIES}
|
||||
${GDAL_LIBRARY}
|
||||
)
|
||||
install(TARGETS fgviewer RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
|
Loading…
Add table
Reference in a new issue