#include <simgear/math/vector.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/scene/model/modellib.hxx>
+#include <simgear/scene/model/shadowvolume.hxx>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
bool FGTileMgr::tile_filter = true;
+extern SGShadowVolume *shadows;
+
// Constructor
FGTileMgr::FGTileMgr():
state( Start ),
long index = tile_cache.get_oldest_tile();
if ( index >= 0 ) {
FGTileEntry *old = tile_cache.get_tile( index );
+ shadows->deleteOccluderFromTile( (ssgBranch *) old->get_terra_transform() );
old->disconnect_ssg_nodes();
delete_queue.push( old );
tile_cache.clear_entry( index );
// schedule a needed buckets for loading
-void FGTileMgr::schedule_needed( double vis, SGBucket curr_bucket) {
+void FGTileMgr::schedule_needed( double vis, const SGBucket& curr_bucket) {
// sanity check (unfortunately needed!)
if ( longitude < -180.0 || longitude > 180.0
|| latitude < -90.0 || latitude > 90.0 )
globals->get_sim_time_sec() );
if ( obj_model != NULL ) {
dm->get_obj_trans()->addKid( obj_model );
+ shadows->addOccluder( (ssgBranch *) obj_model->getParent(0),
+ SGShadowVolume::occluderTypeTileObject,
+ (ssgBranch *) dm->get_tile()->get_terra_transform());
}
} catch (const sg_exception& exc) {
SG_LOG( SG_ALL, SG_ALERT, exc.getMessage() );
}
}
- // cout << "current elevation (ssg) == " << scenery.get_cur_elev() << endl;
-
// Notify the tile loader that it can load another tile
loader.update();
// get real serious and agressively free up some tiles so
// we don't explode our memory usage.
- SG_LOG( SG_TERRAIN, SG_ALERT,
- "Alert: catching up on tile delete queue" );
+ SG_LOG( SG_TERRAIN, SG_WARN,
+ "Warning: catching up on tile delete queue" );
}
FGTileEntry* e = delete_queue.front();
int FGTileMgr::update( double visibility_meters )
{
SGLocation *location = globals->get_current_view()->getSGLocation();
- sgdVec3 abs_pos_vector;
- sgdCopyVec3( abs_pos_vector,
- globals->get_current_view()->get_absolute_view_pos() );
- return update( location, visibility_meters, abs_pos_vector );
+ return update( location, visibility_meters );
}
-int FGTileMgr::update( SGLocation *location, double visibility_meters,
- sgdVec3 abs_pos_vector )
+int FGTileMgr::update( SGLocation *location, double visibility_meters )
{
SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update()" );
// << current_bucket );
fgSetInt( "/environment/current-tile-id", current_bucket.gen_index() );
- // set global scenery center from current tile center
- current_tile = tile_cache.get_tile( current_bucket );
- if ( current_tile != NULL ) {
- globals->get_scenery()->set_next_center( current_tile->center );
- } else {
- SG_LOG( SG_TERRAIN, SG_WARN, "Tile not found (Ok if initializing)" );
- globals->get_scenery()->set_next_center( Point3D(0.0) );
- }
-
// do tile load scheduling.
// Note that we need keep track of both viewer buckets and fdm buckets.
if ( state == Running ) {
// save bucket...
previous_bucket = current_bucket;
- updateCurrentElevAtPos( abs_pos_vector, altitude_m,
- location->get_tile_center() );
-
return 1;
}
}
}
-
-int FGTileMgr::updateCurrentElevAtPos( sgdVec3 abs_pos_vector,
- double max_alt_m,
- Point3D center)
-{
- sgdVec3 sc;
-
- sgdSetVec3( sc, center[0], center[1], center[2]);
-
- // overridden with actual values if a terrain intersection is
- // found
- double hit_elev = -9999.0;
- double hit_radius = 0.0;
- sgdVec3 hit_normal = { 0.0, 0.0, 0.0 };
-
- bool hit = false;
- if ( fabs(sc[0]) > 1.0 || fabs(sc[1]) > 1.0 || fabs(sc[2]) > 1.0 ) {
- // scenery center has been properly defined so any hit should
- // be valid (and not just luck)
- hit = fgCurrentElev(abs_pos_vector,
- max_alt_m,
- sc,
- // uncomment next paramater to fly under
- // bridges and a slightly faster algorithm
- // but you won't be able to land on aircraft carriers
- // current_tile->get_terra_transform(),
- &hit_list,
- &hit_elev,
- &hit_radius,
- hit_normal);
- }
-
- if ( hit ) {
- // cout << "elev = " << hit_elev << " " << hit_radius << endl;
- globals->get_scenery()->set_cur_elev( hit_elev );
- globals->get_scenery()->set_cur_radius( hit_radius );
- globals->get_scenery()->set_cur_normal( hit_normal );
- } else {
- globals->get_scenery()->set_cur_elev( -9999.0 );
- globals->get_scenery()->set_cur_radius( 0.0 );
- globals->get_scenery()->set_cur_normal( hit_normal );
- }
- return hit;
-}
-
-
void FGTileMgr::prep_ssg_nodes( SGLocation *location, float vis ) {
// traverse the potentially viewable tile list and update range
// selector and transform
- Point3D center = location->get_tile_center();
float *up = location->get_world_up();
FGTileEntry *e;
tile_cache.reset_traversal();
+ const double *vp = location->get_absolute_view_pos();
+ Point3D viewpos(vp[0], vp[1], vp[2]);
while ( ! tile_cache.at_end() ) {
// cout << "processing a tile" << endl;
if ( (e = tile_cache.get_current()) ) {
- e->prep_ssg_node( center, up, vis);
+ e->prep_ssg_node( viewpos, up, vis);
} else {
SG_LOG(SG_INPUT, SG_ALERT, "warning ... empty tile in cache");
}
{
return tile_filter ? 1 : 0;
}
+
+bool FGTileMgr::scenery_available(double lat, double lon, double range_m)
+{
+ // sanity check (unfortunately needed!)
+ if ( lon < -180.0 || lon > 180.0 || lat < -90.0 || lat > 90.0 )
+ return false;
+
+ SGBucket bucket(lon, lat);
+ FGTileEntry *te = tile_cache.get_tile(bucket);
+ if (!te || !te->is_loaded())
+ return false;
+
+ // Traverse all tiles required to be there for the given visibility.
+ // This uses exactly the same algorithm like the tile scheduler.
+ double tile_width = bucket.get_width_m();
+ double tile_height = bucket.get_height_m();
+
+ int xrange = (int)fabs(range_m / tile_width) + 1;
+ int yrange = (int)fabs(range_m / tile_height) + 1;
+
+ for ( int x = -xrange; x <= xrange; ++x ) {
+ for ( int y = -yrange; y <= yrange; ++y ) {
+ // We have already checked for the center tile.
+ if ( x != 0 || y != 0 ) {
+ SGBucket b = sgBucketOffset( lon, lat, x, y );
+ FGTileEntry *te = tile_cache.get_tile(b);
+ if (!te || !te->is_loaded())
+ return false;
+ }
+ }
+ }
+
+ // Survived all tests.
+ return true;
+}