]> git.mxchange.org Git - flightgear.git/commitdiff
(Hopefully) fixed bug which caused corrupt entries to be loaded into the
authorcurt <curt>
Sun, 4 Jul 1999 07:37:30 +0000 (07:37 +0000)
committercurt <curt>
Sun, 4 Jul 1999 07:37:30 +0000 (07:37 +0000)
  scene graph when a tile shift occured while the tile load queue was not
  empty.

src/Scenery/tilecache.cxx
src/Scenery/tileentry.cxx
src/Scenery/tileentry.hxx
src/Scenery/tilemgr.cxx
src/Scenery/tilemgr.hxx

index c996087f295f5cc43c7da6fa2786cebbf446a79a..1e0411d22acd837bae6533eafb13dc6c29efc8a2 100644 (file)
@@ -129,34 +129,39 @@ FGTileCache::exists( const FGBucket& p )
 void
 FGTileCache::fill_in( int index, const FGBucket& p )
 {
+    // cout << "FILL IN CACHE ENTRY = " << index << endl;
+
     // Load the appropriate data file and build tile fragment list
     FGPath tile_path( current_options.get_fg_root() );
     tile_path.append( "Scenery" );
     tile_path.append( p.gen_base_path() );
     tile_path.append( p.gen_index_str() );
 
-    tile_cache[index].mark_loaded();
     tile_cache[index].tile_bucket = p;
-    tile_cache[index].branch_ptr = new ssgTransform;
+
+    tile_cache[index].select_ptr = new ssgSelector;
+    tile_cache[index].transform_ptr = new ssgTransform;
     tile_cache[index].range_ptr = new ssgRangeSelector;
+
     ssgBranch *new_tile = fgObjLoad( tile_path.str(), &tile_cache[index] );
     if ( new_tile != NULL ) {
        tile_cache[index].range_ptr->addKid( new_tile );
     }
-    tile_cache[index].branch_ptr->addKid( tile_cache[index].range_ptr );
-    terrain->addKid( tile_cache[index].branch_ptr );
-
-    // cout << " ncount before = " << tile_cache[index].ncount << "\n";
-    // cout << " fragments before = " << tile_cache[index].fragment_list.size()
-    //      << "\n";
-
-    string apt_path = tile_path.str();
-    apt_path += ".apt";
-    fgAptGenerate( apt_path, &tile_cache[index] );
-
-    // cout << " ncount after = " << tile_cache[index].ncount << "\n";
-    // cout << " fragments after = " << tile_cache[index].fragment_list.size()
-    //      << "\n";
+    tile_cache[index].transform_ptr->addKid( tile_cache[index].range_ptr );
+    tile_cache[index].select_ptr->addKid( tile_cache[index].transform_ptr );
+    terrain->addKid( tile_cache[index].select_ptr );
+
+    if ( tile_cache[index].is_scheduled_for_cache() ) {
+       // cout << "FOUND ONE SCHEDULED FOR CACHE" << endl;
+       // load, but not needed now so disable
+       tile_cache[index].mark_loaded();
+       tile_cache[index].ssg_disable();
+       tile_cache[index].select_ptr->select(0);
+    } else {
+       // cout << "FOUND ONE READY TO LOAD" << endl;
+       tile_cache[index].mark_loaded();
+       tile_cache[index].select_ptr->select(1);
+    }
 }
 
 
index 1af8fb4c7ac67be1233c38af7156be43501b5573..bd246f1e9ac990a477e07ec57400aa172ae094a0 100644 (file)
@@ -89,17 +89,17 @@ FGTileEntry::free_tile()
     // delete the ssg branch
 
     // make sure we have a sane number of parents
-    int pcount = branch_ptr->getNumParents();
+    int pcount = select_ptr->getNumParents();
     if ( pcount > 0 ) {
        // find the first parent (should only be one)
-       ssgBranch *parent = branch_ptr->getParent( 0 ) ;
+       ssgBranch *parent = select_ptr->getParent( 0 ) ;
        // find the number of kids this parent has
        int kcount = parent->getNumKids();
-       // find the kid that matches our original branch_ptr
+       // find the kid that matches our original select_ptr
        bool found_kid = false;
        for ( int i = 0; i < kcount; ++i ) {
            ssgEntity *kid = parent->getKid( i );
-           if ( kid == branch_ptr ) {
+           if ( kid == select_ptr ) {
                FG_LOG( FG_TERRAIN, FG_INFO,
                        "Found a kid to delete " << kid);
                found_kid = true;
@@ -118,3 +118,37 @@ FGTileEntry::free_tile()
 }
 
 
+// when a tile is still in the cache, but not in the immediate draw l
+// ist, it can still remain in the scene graph, but we use a range
+// selector to disable it from ever being drawn.
+void 
+FGTileEntry::ssg_disable() {
+    // cout << "TILE STATE = " << state << endl;
+    if ( state == Scheduled_for_use ) {
+       state = Scheduled_for_cache;
+    } else if ( (state == Loaded) || (state == Cached) ) {
+       state = Cached;
+       // cout << "DISABLING SSG NODE" << endl;
+       select_ptr->select(0);
+
+#if 0
+       // set a really tiny range
+       // cout << "SETTING TINY RANGE" << endl;
+       float ranges[2];
+       ranges[0] = 0.0f;
+       ranges[1] = 0.00001f;
+       range_ptr->setRanges( ranges, 2 );
+
+       // transform to a long way away
+       // cout << "MOVING FAR AWAY" << endl;
+       sgCoord sgcoord;
+       sgSetCoord( &sgcoord, 999999.0, 999999.0, 999999.0, 0.0, 0.0, 0.0 );
+       transform_ptr->setTransform( &sgcoord );
+#endif 
+    } else {
+       FG_LOG( FG_TERRAIN, FG_ALERT,
+               "Trying to disable an unused tile!  Dying" );
+       exit(-1);
+    }  
+    // cout << "TILE STATE = " << state << endl;
+}
index 81f67b639e8e382930813da636719eaa62a11c6c..8a5ec4c0a1df60a6d238cac29b559f487c64e285 100644 (file)
@@ -73,8 +73,10 @@ private:
     // Tile state
     enum tile_state {
        Unused = 0,
-       Scheduled = 1,
-       Loaded = 2
+       Scheduled_for_use = 1,
+       Scheduled_for_cache = 2,
+       Loaded = 3,
+       Cached = 4
     };
 
 public:
@@ -112,6 +114,7 @@ public:
     // ssg tree structure for this tile is as follows:
     // ssgRoot(scene)
     //     - ssgBranch(terrain)
+    //      - ssgSelector(tile)
     //        - ssgTransform(tile)
     //           - ssgRangeSelector(tile)
     //              - ssgEntity(tile)
@@ -120,11 +123,14 @@ public:
     //                   ...
     //                 - kidn(fan)
 
-    // pointer to ssg range selector for this tile
-    ssgRangeSelector *range_ptr;
+    // selector (turn tile on/off)
+    ssgSelector *select_ptr;
 
     // pointer to ssg transform for this tile
-    ssgTransform *branch_ptr;
+    ssgTransform *transform_ptr;
+
+    // pointer to ssg range selector for this tile
+    ssgRangeSelector *range_ptr;
 
 public:
 
@@ -189,11 +195,24 @@ public:
     }
 
     inline bool is_unused() const { return state == Unused; }
+    inline bool is_scheduled_for_use() const { 
+       return state == Scheduled_for_use;
+    }
+    inline bool is_scheduled_for_cache() const {
+       return state == Scheduled_for_cache;
+    }
     inline bool is_loaded() const { return state == Loaded; }
 
     inline void mark_unused() { state = Unused; }
-    inline void mark_scheduled() { state = Scheduled; }
+    inline void mark_scheduled_for_use() { state = Scheduled_for_use; }
+    inline void mark_scheduled_for_cache() { state = Scheduled_for_use; }
     inline void mark_loaded() { state = Loaded; }
+
+
+    // when a tile is still in the cache, but not in the immediate
+    // draw l ist, it can still remain in the scene graph, but we use
+    // a range selector to disable it from ever being drawn.
+    void ssg_disable();
 };
 
 
index e296d0a28b2309bb92239dacd02286dbd36211e9..6e315a41e82ad3ee877f9238615b50e5d46926fb 100644 (file)
@@ -61,6 +61,9 @@
 #endif
 
 
+extern ssgRoot *scene;
+
+
 // the tile manager
 FGTileMgr global_tile_mgr;
 
@@ -93,21 +96,40 @@ int FGTileMgr::init( void ) {
 
 
 // schedule a tile for loading
-void FGTileMgr::sched_tile( const FGBucket& b, int *index ) {
+static void disable_tile( int cache_index ) {
+    // see if tile already exists in the cache
+    // cout << "DISABLING CACHE ENTRY = " << cache_index << endl;
+    FGTileEntry *t = global_tile_cache.get_tile( cache_index );
+    t->ssg_disable();
+}
+
+
+// schedule a tile for loading
+int FGTileMgr::sched_tile( const FGBucket& b ) {
     // see if tile already exists in the cache
-    *index = global_tile_cache.exists( b );
-    if ( *index < 0 ) {
-       // find the next availabel cache entry and mark it as scheduled
-       *index = global_tile_cache.next_avail();
-       FGTileEntry *t = global_tile_cache.get_tile( *index );
-       t->mark_scheduled();
+    int cache_index = global_tile_cache.exists( b );
+
+    if ( cache_index >= 0 ) {
+       // tile exists in cache, reenable it.
+       // cout << "REENABLING DISABLED TILE" << endl;
+       FGTileEntry *t = global_tile_cache.get_tile( cache_index );
+       t->select_ptr->select( 1 );
+       t->mark_loaded();
+    } else {
+       // find the next available cache entry and mark it as
+       // scheduled
+       cache_index = global_tile_cache.next_avail();
+       FGTileEntry *t = global_tile_cache.get_tile( cache_index );
+       t->mark_scheduled_for_use();
 
        // register a load request
        FGLoadRec request;
        request.b = b;
-       request.index = *index;
+       request.cache_index = cache_index;
        load_queue.push_back( request );
     }
+
+    return cache_index;
 }
 
 
@@ -340,6 +362,40 @@ FGTileMgr::current_elev( double lon, double lat, const Point3D& abs_view_pos ) {
 }
 
 
+// Determine scenery altitude via ssg.  Normally this just happens
+// when we render the scene, but we'd also like to be able to do this
+// explicitely.  lat & lon are in radians.  view_pos in current world
+// coordinate translated near (0,0,0) (in meters.)  Returns result in
+// meters.
+double
+FGTileMgr::current_elev_ssg( const Point3D& abs_view_pos, 
+                            const Point3D& view_pos )
+{
+    ssgHit *results ;
+
+    // cout << "view pos = " << view_pos << endl;
+    // cout << "abs view pos = " << abs_view_pos << endl;
+
+    sgMat4 m;
+    sgMakeTransMat4( m, view_pos.x(), view_pos.y(), view_pos.z() );
+
+    sgVec3 s;
+    sgSetVec3(s, -abs_view_pos.x(), -abs_view_pos.y(), -abs_view_pos.z() );
+
+    int num_hits = ssgLOS ( scene, s, m, &results ) ;
+
+    for ( int i = 0 ; i < num_hits ; i++ ) {
+       ssgHit *h = &(results [ i ]) ;
+       cout << "got a hit!" << endl;
+       /* Do something with 'h' */
+    }
+
+    FG_LOG( FG_TERRAIN, FG_INFO, "(ssg) no terrain intersection found" );
+
+    return 0.0;
+}
+
+
 // given the current lon/lat, fill in the array of local chunks.  If
 // the chunk isn't already in the cache, then read it from disk.
 int FGTileMgr::update( void ) {
@@ -368,7 +424,7 @@ int FGTileMgr::update( void ) {
     } else if ( (state == Start) || (state == Inited) ) {
        state = Running;
 
-       // First time through or we have teleporte, initialize the
+       // First time through or we have teleported, initialize the
        // system and load all relavant tiles
 
        FG_LOG( FG_TERRAIN, FG_INFO, "Updating Tile list for " << p1 );
@@ -389,7 +445,7 @@ int FGTileMgr::update( void ) {
        p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
                             f->get_Latitude() * RAD_TO_DEG,
                             0, 0 );
-       sched_tile( p2, &tiles[(dh*tile_diameter) + dw]);
+       tiles[(dh*tile_diameter) + dw] = sched_tile( p2 );
 
        for ( i = 3; i <= tile_diameter; i = i + 2 ) {
            int span = i / 2;
@@ -399,7 +455,7 @@ int FGTileMgr::update( void ) {
                p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
                                     f->get_Latitude() * RAD_TO_DEG,
                                     j, -span );
-               sched_tile( p2, &tiles[((dh-span)*tile_diameter) + dw+j]);
+               tiles[((dh-span)*tile_diameter) + dw+j] = sched_tile( p2 );
            }
 
            // top row
@@ -407,7 +463,7 @@ int FGTileMgr::update( void ) {
                p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
                                     f->get_Latitude() * RAD_TO_DEG,
                                     j, span );
-               sched_tile( p2, &tiles[((dh+span)*tile_diameter) + dw+j]);
+               tiles[((dh+span)*tile_diameter) + dw+j] = sched_tile( p2 );
            }
 
            // middle rows
@@ -415,11 +471,11 @@ int FGTileMgr::update( void ) {
                p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
                                     f->get_Latitude() * RAD_TO_DEG,
                                     -span, j );
-               sched_tile( p2, &tiles[((dh+j)*tile_diameter) + dw-span]);
+               tiles[((dh+j)*tile_diameter) + dw-span] = sched_tile( p2 );
                p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
                                     f->get_Latitude() * RAD_TO_DEG,
                                     span, j );
-               sched_tile( p2, &tiles[((dh+j)*tile_diameter) + dw+span]);
+               tiles[((dh+j)*tile_diameter) + dw+span] = sched_tile( p2 );
            }
 
        }
@@ -430,7 +486,7 @@ int FGTileMgr::update( void ) {
                p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
                                     f->get_Latitude() * RAD_TO_DEG,
                                     i - dw, j -dh );
-               sched_tile( p2, &tiles[(j*tile_diameter) + i]);
+               tiles[(j*tile_diameter) + i] = sched_tile( p2 );
            }
        } */
 
@@ -443,7 +499,7 @@ int FGTileMgr::update( void ) {
            
                FGLoadRec pending = load_queue.front();
                load_queue.pop_front();
-               load_tile( pending.b, pending.index );
+               load_tile( pending.b, pending.cache_index );
            }
        }
 
@@ -451,6 +507,18 @@ int FGTileMgr::update( void ) {
        // We've moved to a new bucket, we need to scroll our
         // structures, and load in the new tiles
 
+#if 0 
+       // make sure load queue is flushed before doing shift
+       while ( load_queue.size() ) {
+           FG_LOG( FG_TERRAIN, FG_INFO, 
+                   "Load queue not empty, flushing queue before tile shift." );
+           
+           FGLoadRec pending = load_queue.front();
+           load_queue.pop_front();
+           load_tile( pending.b, pending.index );
+       }
+#endif
+
        // CURRENTLY THIS ASSUMES WE CAN ONLY MOVE TO ADJACENT TILES.
        // AT ULTRA HIGH SPEEDS THIS ASSUMPTION MAY NOT BE VALID IF
        // THE AIRCRAFT CAN SKIP A TILE IN A SINGLE ITERATION.
@@ -460,66 +528,66 @@ int FGTileMgr::update( void ) {
        if ( (p1.get_lon() > p_last.get_lon()) ||
             ( (p1.get_lon() == p_last.get_lon()) && (p1.get_x() > p_last.get_x()) ) ) {
            FG_LOG( FG_TERRAIN, FG_INFO, 
-                   "  Loading " << tile_diameter << "tiles" );
+                   "  Loading " << tile_diameter << " tiles" );
            for ( j = 0; j < tile_diameter; j++ ) {
                // scrolling East
+               disable_tile( tiles[(j*tile_diameter) + 0] );
                for ( i = 0; i < tile_diameter - 1; i++ ) {
                    tiles[(j*tile_diameter) + i] = 
                        tiles[(j*tile_diameter) + i + 1];
                }
                // load in new column
-               // fgBucketOffset(&p_last, &p2, dw + 1, j - dh);
                p2 = fgBucketOffset( last_lon, last_lat, dw + 1, j - dh );
-               sched_tile( p2, &tiles[(j*tile_diameter) + 
-                                            tile_diameter - 1]);
+               tiles[(j*tile_diameter) + tile_diameter - 1] = sched_tile( p2 );
            }
        } else if ( (p1.get_lon() < p_last.get_lon()) ||
-                   ( (p1.get_lon() == p_last.get_lon()) && (p1.get_x() < p_last.get_x()) ) ) {
+                   ( (p1.get_lon() == p_last.get_lon()) && 
+                     (p1.get_x() < p_last.get_x()) ) ) {
            FG_LOG( FG_TERRAIN, FG_INFO, 
-                   "  Loading " << tile_diameter << "tiles" );
+                   "  Loading " << tile_diameter << " tiles" );
            for ( j = 0; j < tile_diameter; j++ ) {
                // scrolling West
+               disable_tile( tiles[(j*tile_diameter) + tile_diameter - 1] );
                for ( i = tile_diameter - 1; i > 0; i-- ) {
                    tiles[(j*tile_diameter) + i] = 
                        tiles[(j*tile_diameter) + i - 1];
                }
                // load in new column
-               // fgBucketOffset(&p_last, &p2, -dw - 1, j - dh);
                p2 = fgBucketOffset( last_lon, last_lat, -dw - 1, j - dh );
-               sched_tile( p2, &tiles[(j*tile_diameter) + 0]);
+               tiles[(j*tile_diameter) + 0] = sched_tile( p2 );
            }
        }
 
        if ( (p1.get_lat() > p_last.get_lat()) ||
             ( (p1.get_lat() == p_last.get_lat()) && (p1.get_y() > p_last.get_y()) ) ) {
            FG_LOG( FG_TERRAIN, FG_INFO, 
-                   "  Loading " << tile_diameter << "tiles" );
+                   "  Loading " << tile_diameter << " tiles" );
            for ( i = 0; i < tile_diameter; i++ ) {
                // scrolling North
+               disable_tile( tiles[0 + i] );
                for ( j = 0; j < tile_diameter - 1; j++ ) {
                    tiles[(j * tile_diameter) + i] =
                        tiles[((j+1) * tile_diameter) + i];
                }
                // load in new column
-               // fgBucketOffset(&p_last, &p2, i - dw, dh + 1);
                p2 = fgBucketOffset( last_lon, last_lat, i - dw, dh + 1);
-               sched_tile( p2, &tiles[((tile_diameter-1) * 
-                                              tile_diameter) + i]);
+               tiles[((tile_diameter-1) * tile_diameter) + i] = 
+                   sched_tile( p2 );
            }
        } else if ( (p1.get_lat() < p_last.get_lat()) ||
                    ( (p1.get_lat() == p_last.get_lat()) && (p1.get_y() < p_last.get_y()) ) ) {
            FG_LOG( FG_TERRAIN, FG_INFO, 
-                   "  Loading " << tile_diameter << "tiles" );
+                   "  Loading " << tile_diameter << " tiles" );
            for ( i = 0; i < tile_diameter; i++ ) {
                // scrolling South
+               disable_tile( tiles[((tile_diameter-1) * tile_diameter) + i] );
                for ( j = tile_diameter - 1; j > 0; j-- ) {
                    tiles[(j * tile_diameter) + i] = 
                        tiles[((j-1) * tile_diameter) + i];
                }
                // load in new column
-               // fgBucketOffset(&p_last, &p2, i - dw, -dh - 1);
                p2 = fgBucketOffset( last_lon, last_lat, i - dw, -dh - 1);
-               sched_tile( p2, &tiles[0 + i]);
+               tiles[0 + i] = sched_tile( p2 );
            }
        }
     }
@@ -529,7 +597,7 @@ int FGTileMgr::update( void ) {
 
        FGLoadRec pending = load_queue.front();
        load_queue.pop_front();
-       load_tile( pending.b, pending.index );
+       load_tile( pending.b, pending.cache_index );
     }
 
     // find our current elevation (feed in the current bucket to save work)
@@ -538,7 +606,11 @@ int FGTileMgr::update( void ) {
 
     scenery.cur_elev = 
        current_elev( f->get_Longitude(), f->get_Latitude(), tmp_abs_view_pos );
-
+    // cout << "current elevation == " << scenery.cur_elev << endl;
+    // double junk = current_elev_ssg( current_view.abs_view_pos,
+    //                                 current_view.view_pos );
+    // cout << "current elevation (ssg) == " << 
+       
     p_last = p1;
     last_lon = f->get_Longitude() * RAD_TO_DEG;
     last_lat = f->get_Latitude() * RAD_TO_DEG;
@@ -765,7 +837,7 @@ void FGTileMgr::prep_ssg_nodes( void ) {
            sgSetCoord( &sgcoord,
                        t->offset.x(), t->offset.y(), t->offset.z(),
                        0.0, 0.0, 0.0 );
-           t->branch_ptr->setTransform( &sgcoord );
+           t->transform_ptr->setTransform( &sgcoord );
        }
     }
 }
index 0f7ee3815d8b75860eabd372d6bc22d3796239b6..9a659ca58507eddf6126feccd1eed2c69276c28a 100644 (file)
@@ -55,7 +55,7 @@ class FGLoadRec {
 public:
 
     FGBucket b;
-    int index;
+    int cache_index;
 };
 
 
@@ -80,7 +80,7 @@ private:
     list < FGLoadRec > load_queue;
 
     // schedule a tile for loading
-    void sched_tile( const FGBucket& b, int *index );
+    int sched_tile( const FGBucket& b );
 
     // load a tile
     void load_tile( const FGBucket& b, int cache_index );
@@ -105,8 +105,10 @@ public:
     // render the scene, but we'd also like to be able to do this
     // explicitely.  lat & lon are in radians.  abs_view_pos in
     // meters.  Returns result in meters.
-    double current_elev_new( const FGBucket& p );
     double current_elev( double lon, double lat, const Point3D& abs_view_pos );
+    double current_elev_ssg( const Point3D& abs_view_pos, 
+                            const Point3D& view_pos );
+    double current_elev_new( const FGBucket& p );
 
     // Prepare the ssg nodes ... for each tile, set it's proper
     // transform and update it's range selector based on current