1998-05-20 20:53:53 +00:00
|
|
|
// tilemgr.cxx -- routines to handle dynamic management of scenery tiles
|
|
|
|
//
|
|
|
|
// Written by Curtis Olson, started January 1998.
|
|
|
|
//
|
|
|
|
// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
|
|
|
|
//
|
|
|
|
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
//
|
|
|
|
// $Id$
|
1998-01-07 23:50:01 +00:00
|
|
|
|
|
|
|
|
1998-04-24 00:51:07 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
1998-04-03 22:09:02 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_WINDOWS_H
|
1998-01-07 23:50:01 +00:00
|
|
|
# include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <GL/glut.h>
|
2000-12-04 05:24:38 +00:00
|
|
|
|
|
|
|
#include <plib/ssg.h>
|
1998-01-07 23:50:01 +00:00
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
#include <simgear/constants.h>
|
2000-02-16 23:01:03 +00:00
|
|
|
#include <simgear/debug/logstream.hxx>
|
|
|
|
#include <simgear/math/point3d.hxx>
|
|
|
|
#include <simgear/math/polar3d.hxx>
|
2000-09-27 20:16:22 +00:00
|
|
|
#include <simgear/math/sg_geodesy.hxx>
|
2000-02-16 23:01:03 +00:00
|
|
|
#include <simgear/math/vector.hxx>
|
1998-05-23 14:09:20 +00:00
|
|
|
|
The following changes were made to flightgear-0.7.5 code to implement the follow
ing features:
a) ADA Flight model - ADA.cxx, ADA.hxx, flight.hxx
b) Fighter a/c HUD - flight.hxx, hud.hxx, hud.cxx, cockpit.cxx, hud_ladr.c
xx, hud_card.cxx
c) 3-window display - options.hxx, options.cxx, viewer.cxx
d) Moving objects (ship) - main.cxx
e) Patches - main.cxx
ADA.cxx, ADA.hxx
--------------------------
Interface to the external ADA flight dynamics package.
flight.hxx
----------
Included prototypes for accepting additional data fron the External flight
model for fighter aircraft HUD
Hud.hxx
-------
Included prototypes for accepting additional data for fighter HUD from Exernal F
light model.
Defined FIGHTER_HUD pre-processor directive to enable compilation of fighter hud
code.
hud.cxx, cockpit.cxx, hud_ladr.cxx, hud_card.cxx
---------------------------------------
Included code to initialise additional reticles/text for fighter HUD which is co
nditionally
compiled if FIGHTER_HUD is defined.
options.hxx
-----------
Added window_offset, and function to retrieve its value for 3 windows
options.cxx
-----------
Changed few options to suit ADA/CEF projection system/screens and checks for win
dow offset.
views.cxx
---------
Added code to retrieve view offset for window.
Main.cxx
--------
Added code to load and move an aircraft carrier.
Patch to enable clouds from command line until Curtis fixes it. By default cloud
s are disabled.
2000-10-19 19:46:13 +00:00
|
|
|
#include <Main/globals.hxx>
|
2002-02-22 22:51:34 +00:00
|
|
|
#include <Main/fg_props.hxx>
|
2001-07-22 19:51:16 +00:00
|
|
|
#include <Main/viewer.hxx>
|
1998-08-25 16:52:38 +00:00
|
|
|
#include <Objects/obj.hxx>
|
1999-08-12 17:13:44 +00:00
|
|
|
|
2000-12-03 20:15:46 +00:00
|
|
|
#include "newcache.hxx"
|
1998-06-05 22:39:53 +00:00
|
|
|
#include "scenery.hxx"
|
1998-12-03 01:18:16 +00:00
|
|
|
#include "tilemgr.hxx"
|
1998-06-05 22:39:53 +00:00
|
|
|
|
2000-06-15 22:32:26 +00:00
|
|
|
#define TEST_LAST_HIT_CACHE
|
1998-09-08 15:05:10 +00:00
|
|
|
|
1999-07-04 07:37:30 +00:00
|
|
|
extern ssgRoot *scene;
|
2002-03-03 23:20:55 +00:00
|
|
|
extern ssgBranch *terrain_branch; // branch that holds world geometry
|
|
|
|
extern ssgBranch *gnd_lights_branch; // branch that holds ground lighting
|
|
|
|
extern ssgBranch *rwy_lights_branch; // branch that holds runway lighting
|
1999-07-04 07:37:30 +00:00
|
|
|
|
1999-06-13 05:58:02 +00:00
|
|
|
// the tile manager
|
|
|
|
FGTileMgr global_tile_mgr;
|
1998-01-24 00:03:27 +00:00
|
|
|
|
1999-05-06 21:14:06 +00:00
|
|
|
|
2001-04-16 20:03:52 +00:00
|
|
|
#ifdef ENABLE_THREADS
|
2001-05-19 16:59:43 +00:00
|
|
|
SGLockedQueue<FGTileEntry *> FGTileMgr::attach_queue;
|
|
|
|
SGLockedQueue<FGDeferredModel *> FGTileMgr::model_queue;
|
2001-05-18 20:31:23 +00:00
|
|
|
#else
|
2001-05-19 16:59:43 +00:00
|
|
|
queue<FGTileEntry *> FGTileMgr::attach_queue;
|
2001-05-21 20:44:59 +00:00
|
|
|
queue<FGDeferredModel *> FGTileMgr::model_queue;
|
2001-04-16 20:03:52 +00:00
|
|
|
#endif // ENABLE_THREADS
|
2000-06-15 22:32:26 +00:00
|
|
|
|
2001-05-19 16:59:43 +00:00
|
|
|
|
1999-06-13 05:58:02 +00:00
|
|
|
// Constructor
|
2000-12-03 20:15:46 +00:00
|
|
|
FGTileMgr::FGTileMgr():
|
2000-12-04 05:24:38 +00:00
|
|
|
state( Start ),
|
2002-02-22 20:20:23 +00:00
|
|
|
current_tile( NULL ),
|
2001-04-16 20:03:52 +00:00
|
|
|
vis( 16000 ),
|
|
|
|
counter_hack(0)
|
1999-06-13 05:58:02 +00:00
|
|
|
{
|
|
|
|
}
|
1999-05-06 21:14:06 +00:00
|
|
|
|
1998-01-24 00:03:27 +00:00
|
|
|
|
1999-06-13 05:58:02 +00:00
|
|
|
// Destructor
|
2000-12-03 20:15:46 +00:00
|
|
|
FGTileMgr::~FGTileMgr() {
|
1999-06-13 05:58:02 +00:00
|
|
|
}
|
1999-05-06 21:14:06 +00:00
|
|
|
|
1998-01-07 23:50:01 +00:00
|
|
|
|
1998-05-20 20:53:53 +00:00
|
|
|
// Initialize the Tile Manager subsystem
|
2000-12-03 20:15:46 +00:00
|
|
|
int FGTileMgr::init() {
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_INFO, "Initializing Tile Manager subsystem." );
|
1998-06-05 22:39:53 +00:00
|
|
|
|
2001-05-21 20:44:59 +00:00
|
|
|
tile_cache.init();
|
2001-05-30 18:21:03 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
|
|
// instead it's just a lot easier to let any pending work flush
|
|
|
|
// through, rather than trying to arrest the queue and nuke all
|
|
|
|
// the various work at all the various stages and get everything
|
|
|
|
// cleaned up properly.
|
2001-05-21 20:44:59 +00:00
|
|
|
|
|
|
|
while ( ! attach_queue.empty() ) {
|
|
|
|
attach_queue.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( ! model_queue.empty() ) {
|
|
|
|
#ifdef ENABLE_THREADS
|
|
|
|
FGDeferredModel* dm = model_queue.pop();
|
|
|
|
#else
|
|
|
|
FGDeferredModel* dm = model_queue.front();
|
|
|
|
model_queue.pop();
|
|
|
|
#endif
|
|
|
|
delete dm;
|
|
|
|
}
|
|
|
|
loader.reinit();
|
|
|
|
#endif
|
2000-07-06 22:13:24 +00:00
|
|
|
|
2000-06-20 04:48:12 +00:00
|
|
|
hit_list.clear();
|
1999-08-15 15:35:07 +00:00
|
|
|
|
1999-06-13 05:58:02 +00:00
|
|
|
state = Inited;
|
1999-05-06 21:14:06 +00:00
|
|
|
|
2000-06-15 22:32:26 +00:00
|
|
|
previous_bucket.make_bad();
|
|
|
|
current_bucket.make_bad();
|
|
|
|
|
|
|
|
longitude = latitude = -1000.0;
|
|
|
|
last_longitude = last_latitude = -1000.0;
|
|
|
|
|
1998-02-12 21:58:27 +00:00
|
|
|
return 1;
|
1998-01-07 23:50:01 +00:00
|
|
|
}
|
|
|
|
|
1999-07-04 07:37:30 +00:00
|
|
|
|
|
|
|
// schedule a tile for loading
|
2000-12-13 20:36:04 +00:00
|
|
|
void FGTileMgr::sched_tile( const SGBucket& b ) {
|
1999-06-13 05:58:02 +00:00
|
|
|
// see if tile already exists in the cache
|
2001-04-11 02:47:15 +00:00
|
|
|
FGTileEntry *t = tile_cache.get_tile( b );
|
1999-07-04 07:37:30 +00:00
|
|
|
|
2000-12-04 05:24:38 +00:00
|
|
|
if ( t == NULL ) {
|
2001-04-14 03:11:39 +00:00
|
|
|
// create a new entry
|
|
|
|
FGTileEntry *e = new FGTileEntry( b );
|
|
|
|
|
|
|
|
// insert the tile into the cache
|
2001-07-20 22:25:12 +00:00
|
|
|
if ( tile_cache.insert_tile( e ) ) {
|
|
|
|
// Schedule tile for loading
|
|
|
|
loader.add( e );
|
|
|
|
} else {
|
|
|
|
// insert failed (cache full with no available entries to
|
|
|
|
// delete.) Try again later
|
|
|
|
delete e;
|
|
|
|
}
|
1999-06-13 05:58:02 +00:00
|
|
|
}
|
|
|
|
}
|
1998-05-20 20:53:53 +00:00
|
|
|
|
|
|
|
|
2000-12-03 20:15:46 +00:00
|
|
|
// schedule a needed buckets for loading
|
|
|
|
void FGTileMgr::schedule_needed() {
|
2001-11-12 22:05:47 +00:00
|
|
|
// sanity check (unfortunately needed!)
|
|
|
|
if ( longitude < -180.0 || longitude > 180.0
|
|
|
|
|| latitude < -90.0 || latitude > 90.0 )
|
|
|
|
{
|
|
|
|
SG_LOG( SG_TERRAIN, SG_ALERT,
|
|
|
|
"Attempting to schedule tiles for bogus latitude and" );
|
|
|
|
SG_LOG( SG_TERRAIN, SG_ALERT,
|
|
|
|
"longitude. This is a FATAL error. Exiting!" );
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
SG_LOG( SG_TERRAIN, SG_INFO,
|
|
|
|
"scheduling needed tiles for " << longitude << " " << latitude );
|
|
|
|
|
2002-02-22 22:51:34 +00:00
|
|
|
vis = fgGetDouble("/environment/visibility-m");
|
1999-11-03 21:01:59 +00:00
|
|
|
|
2000-12-04 05:24:38 +00:00
|
|
|
double tile_width = current_bucket.get_width_m();
|
|
|
|
double tile_height = current_bucket.get_height_m();
|
2001-04-11 02:47:15 +00:00
|
|
|
// cout << "tile width = " << tile_width << " tile_height = "
|
|
|
|
// << tile_height !<< endl;
|
2000-12-03 20:15:46 +00:00
|
|
|
|
|
|
|
xrange = (int)(vis / tile_width) + 1;
|
|
|
|
yrange = (int)(vis / tile_height) + 1;
|
|
|
|
if ( xrange < 1 ) { xrange = 1; }
|
|
|
|
if ( yrange < 1 ) { yrange = 1; }
|
2001-04-11 02:47:15 +00:00
|
|
|
// cout << "xrange = " << xrange << " yrange = " << yrange << endl;
|
2000-12-03 20:15:46 +00:00
|
|
|
|
2001-04-11 02:47:15 +00:00
|
|
|
tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) );
|
2000-12-03 20:15:46 +00:00
|
|
|
|
2001-01-17 23:30:35 +00:00
|
|
|
SGBucket b;
|
|
|
|
|
|
|
|
// schedule center tile first so it can be loaded first
|
|
|
|
b = sgBucketOffset( longitude, latitude, 0, 0 );
|
|
|
|
sched_tile( b );
|
|
|
|
|
2001-03-21 23:10:15 +00:00
|
|
|
int x, y;
|
|
|
|
|
2001-01-17 23:30:35 +00:00
|
|
|
// schedule next ring of 8 tiles
|
2001-03-21 23:10:15 +00:00
|
|
|
for ( x = -1; x <= 1; ++x ) {
|
|
|
|
for ( y = -1; y <= 1; ++y ) {
|
2001-01-17 23:30:35 +00:00
|
|
|
if ( x != 0 || y != 0 ) {
|
|
|
|
b = sgBucketOffset( longitude, latitude, x, y );
|
2001-04-11 02:47:15 +00:00
|
|
|
sched_tile( b );
|
2001-01-17 23:30:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// schedule remaining tiles
|
2001-03-21 23:10:15 +00:00
|
|
|
for ( x = -xrange; x <= xrange; ++x ) {
|
|
|
|
for ( y = -yrange; y <= yrange; ++y ) {
|
2001-01-17 23:30:35 +00:00
|
|
|
if ( x < -1 || x > 1 || y < -1 || y > 1 ) {
|
|
|
|
SGBucket b = sgBucketOffset( longitude, latitude, x, y );
|
2001-04-11 02:47:15 +00:00
|
|
|
sched_tile( b );
|
2000-12-03 20:15:46 +00:00
|
|
|
}
|
1999-11-03 21:01:59 +00:00
|
|
|
}
|
2000-06-15 22:32:26 +00:00
|
|
|
}
|
|
|
|
}
|
1999-11-03 21:01:59 +00:00
|
|
|
|
|
|
|
|
2000-07-23 21:32:59 +00:00
|
|
|
void FGTileMgr::initialize_queue()
|
2000-06-15 22:32:26 +00:00
|
|
|
{
|
|
|
|
// First time through or we have teleported, initialize the
|
|
|
|
// system and load all relavant tiles
|
1999-11-03 21:01:59 +00:00
|
|
|
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_INFO, "Updating Tile list for " << current_bucket );
|
2001-04-11 02:47:15 +00:00
|
|
|
// cout << "tile cache size = " << tile_cache.get_size() << endl;
|
1999-11-03 21:01:59 +00:00
|
|
|
|
2000-06-15 22:32:26 +00:00
|
|
|
// wipe/initialize tile cache
|
2001-04-11 02:47:15 +00:00
|
|
|
// tile_cache.init();
|
2000-06-15 22:32:26 +00:00
|
|
|
previous_bucket.make_bad();
|
1999-11-03 21:01:59 +00:00
|
|
|
|
2000-06-15 22:32:26 +00:00
|
|
|
// build the local area list and schedule tiles for loading
|
1999-11-03 21:01:59 +00:00
|
|
|
|
2000-06-15 22:32:26 +00:00
|
|
|
// start with the center tile and work out in concentric
|
|
|
|
// "rings"
|
1999-11-03 21:01:59 +00:00
|
|
|
|
2000-12-03 20:15:46 +00:00
|
|
|
schedule_needed();
|
1999-11-04 00:41:23 +00:00
|
|
|
|
2001-04-11 02:47:15 +00:00
|
|
|
// do we really want to lose this? CLO
|
|
|
|
#if 0
|
2000-06-15 22:32:26 +00:00
|
|
|
// Now force a load of the center tile and inner ring so we
|
|
|
|
// have something to see in our first frame.
|
2001-04-14 03:11:39 +00:00
|
|
|
int i;
|
2000-06-15 22:32:26 +00:00
|
|
|
for ( i = 0; i < 9; ++i ) {
|
|
|
|
if ( load_queue.size() ) {
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_DEBUG,
|
2000-06-15 22:32:26 +00:00
|
|
|
"Load queue not empty, loading a tile" );
|
|
|
|
|
2000-12-13 20:36:04 +00:00
|
|
|
SGBucket pending = load_queue.front();
|
2000-06-15 22:32:26 +00:00
|
|
|
load_queue.pop_front();
|
2000-12-03 20:15:46 +00:00
|
|
|
load_tile( pending );
|
2000-06-15 22:32:26 +00:00
|
|
|
}
|
1999-11-04 00:41:23 +00:00
|
|
|
}
|
2001-04-11 02:47:15 +00:00
|
|
|
#endif
|
2000-08-09 21:35:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-23 21:32:59 +00:00
|
|
|
// given the current lon/lat (in degrees), fill in the array of local
|
|
|
|
// chunks. If the chunk isn't already in the cache, then read it from
|
|
|
|
// disk.
|
|
|
|
int FGTileMgr::update( double lon, double lat ) {
|
2001-11-20 22:03:58 +00:00
|
|
|
// SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update() for "
|
|
|
|
// << lon << " " << lat );
|
1998-01-07 23:50:01 +00:00
|
|
|
|
2000-07-23 21:32:59 +00:00
|
|
|
longitude = lon;
|
|
|
|
latitude = lat;
|
2001-03-24 06:03:11 +00:00
|
|
|
// SG_LOG( SG_TERRAIN, SG_DEBUG, "lon "<< lonlat[LON] <<
|
2000-06-15 22:32:26 +00:00
|
|
|
// " lat " << lonlat[LAT] );
|
1998-01-07 23:50:01 +00:00
|
|
|
|
2000-06-15 22:32:26 +00:00
|
|
|
current_bucket.set_bucket( longitude, latitude );
|
2001-03-24 06:03:11 +00:00
|
|
|
// SG_LOG( SG_TERRAIN, SG_DEBUG, "Updating Tile list for " << current_bucket );
|
1999-11-04 22:55:00 +00:00
|
|
|
|
2001-04-11 02:47:15 +00:00
|
|
|
if ( tile_cache.exists( current_bucket ) ) {
|
|
|
|
current_tile = tile_cache.get_tile( current_bucket );
|
2001-10-28 16:16:30 +00:00
|
|
|
scenery.set_next_center( current_tile->center );
|
1999-11-04 22:55:00 +00:00
|
|
|
} else {
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_WARN, "Tile not found (Ok if initializing)" );
|
2002-02-22 20:20:23 +00:00
|
|
|
scenery.set_next_center( Point3D(0.0) );
|
1999-11-04 22:55:00 +00:00
|
|
|
}
|
|
|
|
|
2000-06-15 22:32:26 +00:00
|
|
|
if ( state == Running ) {
|
2001-10-28 16:16:30 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_DEBUG, "State == Running" );
|
2000-12-13 23:02:02 +00:00
|
|
|
if ( !(current_bucket == previous_bucket) ) {
|
2000-12-03 20:15:46 +00:00
|
|
|
// We've moved to a new bucket, we need to schedule any
|
|
|
|
// needed tiles for loading.
|
|
|
|
schedule_needed();
|
1998-01-26 15:55:24 +00:00
|
|
|
}
|
2000-07-23 21:32:59 +00:00
|
|
|
} else if ( state == Start || state == Inited ) {
|
2001-10-28 16:16:30 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_INFO, "State == Start || Inited" );
|
2000-06-15 22:32:26 +00:00
|
|
|
initialize_queue();
|
|
|
|
state = Running;
|
1998-12-03 01:18:16 +00:00
|
|
|
|
2001-10-28 16:16:30 +00:00
|
|
|
// load the next tile in the load queue (or authorize the next
|
|
|
|
// load in the case of the threaded tile pager)
|
|
|
|
loader.update();
|
|
|
|
}
|
1999-06-13 05:58:02 +00:00
|
|
|
|
2001-05-19 16:59:43 +00:00
|
|
|
// load the next model in the load queue. Currently this must
|
|
|
|
// happen in the render thread because model loading can trigger
|
|
|
|
// texture loading which involves use of the opengl api.
|
|
|
|
if ( !model_queue.empty() ) {
|
2002-03-17 00:38:24 +00:00
|
|
|
// cout << "loading next model ..." << endl;
|
|
|
|
// load the next tile in the queue
|
2001-05-19 16:59:43 +00:00
|
|
|
#ifdef ENABLE_THREADS
|
|
|
|
FGDeferredModel* dm = model_queue.pop();
|
|
|
|
#else
|
|
|
|
FGDeferredModel* dm = model_queue.front();
|
|
|
|
model_queue.pop();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ssgTexturePath( (char *)(dm->get_texture_path().c_str()) );
|
|
|
|
ssgEntity *obj_model
|
|
|
|
= ssgLoad( (char *)(dm->get_model_path().c_str()) );
|
2001-06-01 18:04:10 +00:00
|
|
|
if ( obj_model != NULL ) {
|
|
|
|
dm->get_obj_trans()->addKid( obj_model );
|
|
|
|
}
|
|
|
|
dm->get_tile()->dec_pending_models();
|
2001-05-19 16:59:43 +00:00
|
|
|
|
|
|
|
delete dm;
|
|
|
|
}
|
|
|
|
|
2002-03-17 00:38:24 +00:00
|
|
|
// cout << "current elevation (ssg) == " << scenery.get_cur_elev() << endl;
|
|
|
|
|
2001-06-20 22:22:26 +00:00
|
|
|
previous_bucket = current_bucket;
|
|
|
|
last_longitude = longitude;
|
|
|
|
last_latitude = latitude;
|
|
|
|
|
|
|
|
// activate loader thread one out of every 5 frames
|
|
|
|
if ( counter_hack == 0 ) {
|
|
|
|
// Notify the tile loader that it can load another tile
|
2002-02-11 23:33:20 +00:00
|
|
|
|
2001-10-28 16:16:30 +00:00
|
|
|
loader.update();
|
2001-06-20 22:22:26 +00:00
|
|
|
|
2001-10-28 16:16:30 +00:00
|
|
|
}
|
|
|
|
counter_hack = (counter_hack + 1) % 5;
|
|
|
|
|
|
|
|
if ( !attach_queue.empty() ) {
|
2001-06-20 22:22:26 +00:00
|
|
|
#ifdef ENABLE_THREADS
|
2001-10-28 16:16:30 +00:00
|
|
|
FGTileEntry* e = attach_queue.pop();
|
2001-06-20 22:22:26 +00:00
|
|
|
#else
|
2001-10-28 16:16:30 +00:00
|
|
|
FGTileEntry* e = attach_queue.front();
|
|
|
|
attach_queue.pop();
|
2001-06-20 22:22:26 +00:00
|
|
|
#endif
|
2002-03-03 23:20:55 +00:00
|
|
|
e->add_ssg_nodes( terrain_branch,
|
|
|
|
gnd_lights_branch,
|
|
|
|
rwy_lights_branch );
|
2002-03-17 00:38:24 +00:00
|
|
|
// cout << "Adding ssg nodes for "
|
2001-06-20 22:22:26 +00:00
|
|
|
}
|
2001-10-28 16:16:30 +00:00
|
|
|
|
2001-07-11 15:51:21 +00:00
|
|
|
sgdVec3 sc;
|
2001-10-28 16:16:30 +00:00
|
|
|
sgdSetVec3( sc,
|
2002-02-22 20:20:23 +00:00
|
|
|
scenery.get_center()[0],
|
|
|
|
scenery.get_center()[1],
|
|
|
|
scenery.get_center()[2] );
|
2001-06-20 22:22:26 +00:00
|
|
|
|
2001-10-28 16:16:30 +00:00
|
|
|
#if 0
|
2000-07-23 21:32:59 +00:00
|
|
|
if ( scenery.center == Point3D(0.0) ) {
|
|
|
|
// initializing
|
2002-03-17 00:38:24 +00:00
|
|
|
cout << "initializing scenery current elevation ... " << endl;
|
2000-10-25 19:27:13 +00:00
|
|
|
sgdVec3 tmp_abs_view_pos;
|
|
|
|
|
2001-03-24 04:48:44 +00:00
|
|
|
Point3D geod_pos = Point3D( longitude * SGD_DEGREES_TO_RADIANS,
|
|
|
|
latitude * SGD_DEGREES_TO_RADIANS,
|
2000-07-23 21:32:59 +00:00
|
|
|
0.0);
|
2000-10-25 19:27:13 +00:00
|
|
|
Point3D tmp = sgGeodToCart( geod_pos );
|
|
|
|
scenery.center = tmp;
|
|
|
|
sgdSetVec3( tmp_abs_view_pos, tmp.x(), tmp.y(), tmp.z() );
|
|
|
|
|
2002-03-17 00:38:24 +00:00
|
|
|
// cout << "abs_view_pos = " << tmp_abs_view_pos << endl;
|
2000-07-23 21:32:59 +00:00
|
|
|
prep_ssg_nodes();
|
2001-07-12 15:03:49 +00:00
|
|
|
|
2000-11-02 00:59:39 +00:00
|
|
|
double tmp_elev;
|
2001-07-11 15:51:21 +00:00
|
|
|
if ( fgCurrentElev(tmp_abs_view_pos, sc, &hit_list,
|
|
|
|
&tmp_elev, &scenery.cur_radius, scenery.cur_normal) )
|
|
|
|
{
|
2001-10-28 16:16:30 +00:00
|
|
|
scenery.set_cur_elev( tmp_elev );
|
2000-11-02 00:59:39 +00:00
|
|
|
} else {
|
2001-10-28 16:16:30 +00:00
|
|
|
scenery.set_cur_elev( 0.0 );
|
2000-11-02 00:59:39 +00:00
|
|
|
}
|
2002-03-17 00:38:24 +00:00
|
|
|
// cout << "result = " << scenery.get_cur_elev() << endl;
|
2000-07-23 21:32:59 +00:00
|
|
|
} else {
|
2001-10-28 16:16:30 +00:00
|
|
|
#endif
|
2002-03-17 00:38:24 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
cout << "abs view pos = "
|
|
|
|
<< globals->get_current_view()->get_abs_view_pos()[0] << ","
|
|
|
|
<< globals->get_current_view()->get_abs_view_pos()[1] << ","
|
|
|
|
<< globals->get_current_view()->get_abs_view_pos()[2]
|
|
|
|
<< " view pos = "
|
|
|
|
<< globals->get_current_view()->get_view_pos()[0] << ","
|
|
|
|
<< globals->get_current_view()->get_view_pos()[1] << ","
|
|
|
|
<< globals->get_current_view()->get_view_pos()[2]
|
|
|
|
<< endl;
|
|
|
|
cout << "current_tile = " << current_tile << endl;
|
|
|
|
cout << "Scenery center = " << sc[0] << "," << sc[1] << "," << sc[2]
|
|
|
|
<< endl;
|
|
|
|
*/
|
|
|
|
|
2002-02-22 20:20:23 +00:00
|
|
|
// 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)
|
2002-03-17 00:38:24 +00:00
|
|
|
sgdSetVec3( sc,
|
|
|
|
scenery.get_center()[0],
|
|
|
|
scenery.get_center()[1],
|
|
|
|
scenery.get_center()[2] );
|
Major viewer-code overhaul from Jim Wilson:
Description:
This update includes the new viewer interface as proposed by David M. and
a first pass at cleaning up the viewer/view manager code by Jim W.
Note that I have dropped Main/viewer_lookat.?xx and Main/viewer_rph.?xx and
modified the Makefile.am accordingly.
Detail of work:
Overall:
The code reads a little easier. There are still some unnecessary bits in
there and I'd like to supplement the comments in the viewer.hxx with a tiny
bit on each interface group and what the groupings mean (similar but briefer
than what you emailed me the other day). I tried not to mess up the style,
but there is an occasional inconsistency. In general I wouldn't call it done
(especially since there's no tower yet! :)), but I'd like to get this out
there so others can comment, and test.
In Viewer:
The interface as you suggested has been implemented. Basically everything
seems to work as it did visually. There is no difference that I can see in
performance, although some things might be a tiny bit faster.
I've merged the lookat and rph (pilot view) code into the recalc for the
viewer. There is still some redundancy between the two, but a lot has been
removed. In some cases I've taken some code that we'd likely want to inline
anyway and left it in there in duplicate. You'll see that the code for both
looks a little cleaner. I need to take a closer look at the rotations in
particular. I've cleaned up a little there, but I suspect more can be done
to streamline this.
The external declaration to the Quat_mat in mouse.cxx has been removed. IMHO
the quat doesn't serve any intrinsic purpose in mouse.cxx, but I'm not about
to rip it out. It would seem that there more conventional ways to get
spherical data that are just as fast. In any case all the viewer was pulling
from the quat matrix was the pitch value so I modified mouse.cxx to output to
our pitchOffset input and that works fine.
I've changed the native values to degrees from radians where appropriate.
This required a conversion from degrees to radians in a couple modules that
access the interface. Perhaps we should add interface calls that do the
conversion, e.g. a getHeadingOffset_rad() to go along with the
getHeadingOffset_deg().
On the view_offset (now headingOffset) thing there are two entry points
because of the ability to instantly switch views or to scroll to a new view
angle (by hitting the numeric keys for example). This leaves an anomaly in
the interface which should be resolved by adding "goal" settings to the
interface, e.g. a setGoalHeadingOffset_deg(), setGoalPitchOffset_deg(), etc.
Other than these two issues, the next step here will be to look at some
further optimizations, and to write support code for a tower view. That
should be fairly simple at this point. I was considering creating a
"simulated tower view" or "pedestrian view" that defaulted to a position off
to the right of whereever the plane is at the moment you switch to the tower
view. This could be a fall back when we don't have an actual tower location
at hand (as would be the case with rural airports).
ViewManager:
Basically all I did here was neaten things up by ripping out excess crap and
made it compatible as is with the new interface.
The result is that viewmanager is now ready to be developed. The two
preexisting views are still hardcoded into the view manager. The next step
would be to design configuration xml (eg /sim/view[x]/config/blahblah) that
could be used to set up as many views as we want. If we want to take the easy
way out, we might want to insist that view[0] be a pilot-view and have
viewmanager check for that.
2002-03-20 17:43:28 +00:00
|
|
|
hit = fgCurrentElev(globals->get_current_view()->get_absolute_view_pos(),
|
2002-03-17 00:38:24 +00:00
|
|
|
sc,
|
|
|
|
current_tile->get_terra_transform(),
|
|
|
|
&hit_list,
|
|
|
|
&hit_elev,
|
|
|
|
&hit_radius,
|
|
|
|
hit_normal);
|
2002-02-22 20:20:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( hit ) {
|
|
|
|
scenery.set_cur_elev( hit_elev );
|
|
|
|
scenery.set_cur_radius( hit_radius );
|
|
|
|
scenery.set_cur_normal( hit_normal );
|
|
|
|
} else {
|
|
|
|
scenery.set_cur_elev( -9999.0 );
|
|
|
|
scenery.set_cur_radius( 0.0 );
|
|
|
|
scenery.set_cur_normal( hit_normal );
|
|
|
|
}
|
2002-03-17 00:38:24 +00:00
|
|
|
// cout << "Current elevation = " << scenery.get_cur_elev() << endl;
|
|
|
|
|
2001-10-28 16:16:30 +00:00
|
|
|
#if 0
|
2000-07-23 21:32:59 +00:00
|
|
|
}
|
2001-10-28 16:16:30 +00:00
|
|
|
#endif
|
1998-09-08 15:05:10 +00:00
|
|
|
|
2000-06-15 22:32:26 +00:00
|
|
|
return 1;
|
1998-09-08 15:05:10 +00:00
|
|
|
}
|
|
|
|
|
2000-06-15 22:32:26 +00:00
|
|
|
|
2000-12-03 20:15:46 +00:00
|
|
|
void FGTileMgr::prep_ssg_nodes() {
|
|
|
|
float vis = 0.0;
|
2000-07-23 21:32:59 +00:00
|
|
|
|
2002-02-22 22:51:34 +00:00
|
|
|
vis = fgGetDouble("/environment/visibility-m");
|
1999-06-30 00:28:20 +00:00
|
|
|
|
|
|
|
// traverse the potentially viewable tile list and update range
|
|
|
|
// selector and transform
|
2000-06-15 22:32:26 +00:00
|
|
|
|
2000-12-03 20:15:46 +00:00
|
|
|
FGTileEntry *e;
|
2001-04-11 02:47:15 +00:00
|
|
|
tile_cache.reset_traversal();
|
2000-06-15 22:32:26 +00:00
|
|
|
|
2001-04-11 02:47:15 +00:00
|
|
|
while ( ! tile_cache.at_end() ) {
|
2002-03-17 00:38:24 +00:00
|
|
|
// cout << "processing a tile" << endl;
|
|
|
|
if ( (e = tile_cache.get_current()) ) {
|
2001-10-28 16:16:30 +00:00
|
|
|
e->prep_ssg_node( scenery.get_center(), vis);
|
2000-12-03 20:15:46 +00:00
|
|
|
} else {
|
2002-03-16 00:18:38 +00:00
|
|
|
SG_LOG(SG_INPUT, SG_ALERT, "warning ... empty tile in cache");
|
2000-06-15 22:32:26 +00:00
|
|
|
}
|
2001-04-11 02:47:15 +00:00
|
|
|
tile_cache.next();
|
2000-12-03 20:15:46 +00:00
|
|
|
}
|
1999-06-30 00:28:20 +00:00
|
|
|
}
|
Major viewer-code overhaul from Jim Wilson:
Description:
This update includes the new viewer interface as proposed by David M. and
a first pass at cleaning up the viewer/view manager code by Jim W.
Note that I have dropped Main/viewer_lookat.?xx and Main/viewer_rph.?xx and
modified the Makefile.am accordingly.
Detail of work:
Overall:
The code reads a little easier. There are still some unnecessary bits in
there and I'd like to supplement the comments in the viewer.hxx with a tiny
bit on each interface group and what the groupings mean (similar but briefer
than what you emailed me the other day). I tried not to mess up the style,
but there is an occasional inconsistency. In general I wouldn't call it done
(especially since there's no tower yet! :)), but I'd like to get this out
there so others can comment, and test.
In Viewer:
The interface as you suggested has been implemented. Basically everything
seems to work as it did visually. There is no difference that I can see in
performance, although some things might be a tiny bit faster.
I've merged the lookat and rph (pilot view) code into the recalc for the
viewer. There is still some redundancy between the two, but a lot has been
removed. In some cases I've taken some code that we'd likely want to inline
anyway and left it in there in duplicate. You'll see that the code for both
looks a little cleaner. I need to take a closer look at the rotations in
particular. I've cleaned up a little there, but I suspect more can be done
to streamline this.
The external declaration to the Quat_mat in mouse.cxx has been removed. IMHO
the quat doesn't serve any intrinsic purpose in mouse.cxx, but I'm not about
to rip it out. It would seem that there more conventional ways to get
spherical data that are just as fast. In any case all the viewer was pulling
from the quat matrix was the pitch value so I modified mouse.cxx to output to
our pitchOffset input and that works fine.
I've changed the native values to degrees from radians where appropriate.
This required a conversion from degrees to radians in a couple modules that
access the interface. Perhaps we should add interface calls that do the
conversion, e.g. a getHeadingOffset_rad() to go along with the
getHeadingOffset_deg().
On the view_offset (now headingOffset) thing there are two entry points
because of the ability to instantly switch views or to scroll to a new view
angle (by hitting the numeric keys for example). This leaves an anomaly in
the interface which should be resolved by adding "goal" settings to the
interface, e.g. a setGoalHeadingOffset_deg(), setGoalPitchOffset_deg(), etc.
Other than these two issues, the next step here will be to look at some
further optimizations, and to write support code for a tower view. That
should be fairly simple at this point. I was considering creating a
"simulated tower view" or "pedestrian view" that defaulted to a position off
to the right of whereever the plane is at the moment you switch to the tower
view. This could be a fall back when we don't have an actual tower location
at hand (as would be the case with rural airports).
ViewManager:
Basically all I did here was neaten things up by ripping out excess crap and
made it compatible as is with the new interface.
The result is that viewmanager is now ready to be developed. The two
preexisting views are still hardcoded into the view manager. The next step
would be to design configuration xml (eg /sim/view[x]/config/blahblah) that
could be used to set up as many views as we want. If we want to take the easy
way out, we might want to insist that view[0] be a pilot-view and have
viewmanager check for that.
2002-03-20 17:43:28 +00:00
|
|
|
|