]> git.mxchange.org Git - flightgear.git/blobdiff - src/Scenery/tileentry.cxx
A long, long time ago, a bug was inadvertently introduced into the threaded
[flightgear.git] / src / Scenery / tileentry.cxx
index a160ecac311d58ea7cdfe7fdf8f6839751c1f411..a457c76c35b584416dd1c409754467be755502b0 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Written by Curtis Olson, started May 1998.
 //
-// Copyright (C) 1998 - 2001  Curtis L. Olson  - curt@flightgear.org
+// Copyright (C) 1998 - 2001  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
@@ -26,7 +26,7 @@
 #endif
 
 #include <simgear/compiler.h>
-
+#include <plib/ul.h>
 #include <Main/main.hxx>
 
 
@@ -43,6 +43,7 @@
 #include <simgear/scene/tgdb/apt_signs.hxx>
 #include <simgear/scene/tgdb/obj.hxx>
 #include <simgear/scene/tgdb/vasi.hxx>
+#include <simgear/scene/model/placementtrans.hxx>
 
 #include <Aircraft/aircraft.hxx>
 #include <Include/general.hxx>
@@ -62,16 +63,17 @@ SG_USING_STD(string);
 FGTileEntry::FGTileEntry ( const SGBucket& b )
     : center( Point3D( 0.0 ) ),
       tile_bucket( b ),
-      terra_transform( new ssgTransform ),
-      vasi_lights_transform( new ssgTransform ),
-      rwy_lights_transform( new ssgTransform ),
-      taxi_lights_transform( new ssgTransform ),
+      terra_transform( new ssgPlacementTransform ),
+      vasi_lights_transform( new ssgPlacementTransform ),
+      rwy_lights_transform( new ssgPlacementTransform ),
+      taxi_lights_transform( new ssgPlacementTransform ),
       terra_range( new ssgRangeSelector ),
       vasi_lights_selector( new ssgSelector ),
       rwy_lights_selector( new ssgSelector ),
       taxi_lights_selector( new ssgSelector ),
       loaded(false),
       pending_models(0),
+      is_inner_ring(false),
       free_tracker(0)
 {
     // update the contents
@@ -315,8 +317,6 @@ bool FGTileEntry::free_tile() {
 void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
     if ( !loaded ) return;
 
-    SetOffset( p );
-
     // visibility can change from frame to frame so we update the
     // range selector cutoff's each time.
     terra_range->setRange( 0, SG_ZERO );
@@ -327,9 +327,8 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
         gnd_lights_range->setRange( 1, vis * 1.5 + bounding_radius );
     }
 
-    sgVec3 sgTrans;
-    sgSetVec3( sgTrans, offset.x(), offset.y(), offset.z() );
-    terra_transform->setTransform( sgTrans );
+    sgdVec3 sgdTrans;
+    sgdSetVec3( sgdTrans, center.x(), center.y(), center.z() );
 
     FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
     if ( gnd_lights_transform ) {
@@ -344,15 +343,11 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
         sgCopyVec3( lift_vec, up );
 
         double agl;
-        agl = globals->get_current_view()->getAltitudeASL_ft()
-            * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev();
+        agl = globals->get_current_view()->getAltitudeASL_ft()*SG_FEET_TO_METER
+          - globals->get_current_view()->getSGLocation()->get_cur_elev_m();
 
-        // sgTrans just happens to be the
-        // vector from scenery center to the center of this tile which
-        // is what we want to calculate the distance of
-        sgVec3 to;
-        sgCopyVec3( to, sgTrans );
-        double dist = sgLengthVec3( to );
+        // Compute the distance of the scenery center from the view position.
+        double dist = center.distance3D(p);
 
         if ( general.get_glDepthBits() > 16 ) {
             sgScaleVec3( lift_vec, 10.0 + agl / 100.0 + dist / 10000 );
@@ -360,11 +355,12 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
             sgScaleVec3( lift_vec, 10.0 + agl / 20.0 + dist / 5000 );
         }
 
-        sgVec3 lt_trans;
-        sgCopyVec3( lt_trans, sgTrans );
-
-        sgAddVec3( lt_trans, lift_vec );
-        gnd_lights_transform->setTransform( lt_trans );
+        sgdVec3 dlt_trans;
+        sgdCopyVec3( dlt_trans, sgdTrans );
+        sgdVec3 dlift_vec;
+        sgdSetVec3( dlift_vec, lift_vec );
+        sgdAddVec3( dlt_trans, dlift_vec );
+        gnd_lights_transform->setTransform( dlt_trans );
 
         // select which set of lights based on sun angle
         float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES;
@@ -390,9 +386,9 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
         // we fudge agl by 30 meters so that the lifting function
         // doesn't phase in until we are > 30m agl.
         double agl;
-        agl = globals->get_current_view()->getAltitudeASL_ft()
-            * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev()
-            - 30.0;
+        agl = globals->get_current_view()->getAltitudeASL_ft()*SG_FEET_TO_METER
+          - globals->get_current_view()->getSGLocation()->get_cur_elev_m()
+          - 30.0;
         if ( agl < 0.0 ) {
             agl = 0.0;
         }
@@ -403,11 +399,12 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
             sgScaleVec3( lift_vec, 0.25 + agl / 150.0 );
         }
 
-        sgVec3 lt_trans;
-        sgCopyVec3( lt_trans, sgTrans );
-
-        sgAddVec3( lt_trans, lift_vec );
-        vasi_lights_transform->setTransform( lt_trans );
+        sgdVec3 dlt_trans;
+        sgdCopyVec3( dlt_trans, sgdTrans );
+        sgdVec3 dlift_vec;
+        sgdSetVec3( dlift_vec, lift_vec );
+        sgdAddVec3( dlt_trans, dlift_vec );
+        vasi_lights_transform->setTransform( dlt_trans );
 
         // generally, vasi lights are always on
         vasi_lights_selector->select(0x01);
@@ -424,9 +421,9 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
         // we fudge agl by 30 meters so that the lifting function
         // doesn't phase in until we are > 30m agl.
         double agl;
-        agl = globals->get_current_view()->getAltitudeASL_ft()
-            * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev()
-            - 30.0;
+        agl = globals->get_current_view()->getAltitudeASL_ft()*SG_FEET_TO_METER
+          - globals->get_current_view()->getSGLocation()->get_cur_elev_m()
+          - 30.0;
         if ( agl < 0.0 ) {
             agl = 0.0;
         }
@@ -437,11 +434,12 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
             sgScaleVec3( lift_vec, 0.25 + agl / 150.0 );
         }
 
-        sgVec3 lt_trans;
-        sgCopyVec3( lt_trans, sgTrans );
-
-        sgAddVec3( lt_trans, lift_vec );
-        rwy_lights_transform->setTransform( lt_trans );
+        sgdVec3 dlt_trans;
+        sgdCopyVec3( dlt_trans, sgdTrans );
+        sgdVec3 dlift_vec;
+        sgdSetVec3( dlift_vec, lift_vec );
+        sgdAddVec3( dlt_trans, dlift_vec );
+        rwy_lights_transform->setTransform( dlt_trans );
 
         // turn runway lights on/off based on sun angle and visibility
         float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES;
@@ -464,9 +462,9 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
         // we fudge agl by 30 meters so that the lifting function
         // doesn't phase in until we are > 30m agl.
         double agl;
-        agl = globals->get_current_view()->getAltitudeASL_ft()
-            * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev()
-            - 30.0;
+        agl = globals->get_current_view()->getAltitudeASL_ft()*SG_FEET_TO_METER
+          - globals->get_current_view()->getSGLocation()->get_cur_elev_m()
+          - 30.0;
         if ( agl < 0.0 ) {
             agl = 0.0;
         }
@@ -477,11 +475,12 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
             sgScaleVec3( lift_vec, 0.25 + agl / 150.0 );
         }
 
-        sgVec3 lt_trans;
-        sgCopyVec3( lt_trans, sgTrans );
-
-        sgAddVec3( lt_trans, lift_vec );
-        taxi_lights_transform->setTransform( lt_trans );
+        sgdVec3 dlt_trans;
+        sgdCopyVec3( dlt_trans, sgdTrans );
+        sgdVec3 dlift_vec;
+        sgdSetVec3( dlift_vec, lift_vec );
+        sgdAddVec3( dlt_trans, dlift_vec );
+        taxi_lights_transform->setTransform( dlt_trans );
 
         // turn taxi lights on/off based on sun angle and visibility
         float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES;
@@ -493,9 +492,11 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
         }
     }
 
-    if ( vasi_lights_transform ) {
+    if ( vasi_lights_transform && is_inner_ring ) {
         // now we need to traverse the list of vasi lights and update
-        // their coloring
+        // their coloring (but only for the inner ring, no point in
+        // doing this extra work for tiles that are relatively far
+        // away.)
         for ( int i = 0; i < vasi_lights_transform->getNumKids(); ++i ) {
             // cout << "vasi root = " << i << endl;
             ssgBranch *v = (ssgBranch *)vasi_lights_transform->getKid(i);
@@ -659,29 +660,24 @@ bool FGTileEntry::obj_load( const string& path,
 
 
 void
-FGTileEntry::load( const string &base_path, bool is_base )
+FGTileEntry::load( const string_list &path_list, bool is_base )
 {
-    SG_LOG( SG_TERRAIN, SG_INFO, "load() base search path = "
-            << base_path );
-
     bool found_tile_base = false;
 
-    string_list search = sgPathSplit( base_path );
-
     // obj_load() will generate ground lighting for us ...
     ssgVertexArray *light_pts = new ssgVertexArray( 100 );
 
     ssgBranch* new_tile = new ssgBranch;
 
     unsigned int i = 0;
-    while ( i < search.size() ) {
+    while ( i < path_list.size() ) {
 
         bool has_base = false;
 
         // Generate names for later use
         string index_str = tile_bucket.gen_index_str();
 
-        SGPath tile_path = search[i];
+        SGPath tile_path = path_list[i];
         tile_path.append( tile_bucket.gen_base_path() );
 
         SGPath basename = tile_path;
@@ -704,6 +700,10 @@ FGTileEntry::load( const string &base_path, bool is_base )
             while ( ! in.eof() ) {
                 in >> token;
 
+                if ( token[0] == '#' ) {
+                   in >> ::skipeol;
+                   continue;
+                }
                                 // Load only once (first found)
                 if ( token == "OBJECT_BASE" ) {
                     in >> name >> ::skipws;
@@ -722,6 +722,9 @@ FGTileEntry::load( const string &base_path, bool is_base )
                                        geometry, NULL, NULL, NULL, light_pts,
                                        true ) )
                             {
+                                geometry->getKid( 0 )->setTravCallback( 
+                                                        SSG_CALLBACK_PRETRAV,
+                                                        &FGTileMgr::tile_filter_cb );
                                 new_tile -> addKid( geometry );
                             } else {
                                 delete geometry;
@@ -749,6 +752,9 @@ FGTileEntry::load( const string &base_path, bool is_base )
                                        taxi_lights, NULL, false ) )
                             {
                                 if ( geometry -> getNumKids() > 0 ) {
+                                    geometry->getKid( 0 )->setTravCallback(
+                                                                SSG_CALLBACK_PRETRAV,
+                                                                &FGTileMgr::tile_filter_cb );
                                     new_tile -> addKid( geometry );
                                 } else {
                                     delete geometry;
@@ -814,6 +820,7 @@ FGTileEntry::load( const string &base_path, bool is_base )
                     FGDeferredModel *dm
                         = new FGDeferredModel( custom_path.str(),
                                                tile_path.str(),
+                                               tile_bucket,
                                                this, obj_trans );
                     FGTileMgr::model_ready( dm );
 
@@ -909,7 +916,7 @@ FGTileEntry::load( const string &base_path, bool is_base )
         ssgBranch *geometry = new ssgBranch;
         Point3D c;
         double br;
-        if ( sgGenTile( search[0], tile_bucket, &c, &br,
+        if ( sgGenTile( path_list[0], tile_bucket, &c, &br,
                         globals->get_matlib(), geometry ) )
         {
             center = c;
@@ -929,20 +936,16 @@ FGTileEntry::load( const string &base_path, bool is_base )
     terra_transform->addKid( terra_range );
 
     // calculate initial tile offset
-    SetOffset( globals->get_scenery()->get_center() );
-    sgCoord sgcoord;
-    sgSetCoord( &sgcoord,
-                offset.x(), offset.y(), offset.z(),
-                0.0, 0.0, 0.0 );
-    terra_transform->setTransform( &sgcoord );
-    // terrain->addKid( terra_transform );
+    sgdVec3 sgdTrans;
+    sgdSetVec3( sgdTrans, center.x(), center.y(), center.z() );
+    terra_transform->setTransform( sgdTrans );
 
     // Add ground lights to scene graph if any exist
     gnd_lights_transform = NULL;
     gnd_lights_range = NULL;
     if ( light_pts->getNum() ) {
         SG_LOG( SG_TERRAIN, SG_DEBUG, "generating lights" );
-        gnd_lights_transform = new ssgTransform;
+        gnd_lights_transform = new ssgPlacementTransform;
         gnd_lights_range = new ssgRangeSelector;
         gnd_lights_brightness = new ssgSelector;
         ssgLeaf *lights;
@@ -958,25 +961,40 @@ FGTileEntry::load( const string &base_path, bool is_base )
 
         gnd_lights_range->addKid( gnd_lights_brightness );
         gnd_lights_transform->addKid( gnd_lights_range );
-        gnd_lights_transform->setTransform( &sgcoord );
+        gnd_lights_transform->setTransform( sgdTrans );
     }
 
     // Update vasi lights transform
     if ( vasi_lights_transform->getNumKids() > 0 ) {
-        vasi_lights_transform->setTransform( &sgcoord );
+        vasi_lights_transform->setTransform( sgdTrans );
     }
 
     // Update runway lights transform
     if ( rwy_lights_transform->getNumKids() > 0 ) {
-        rwy_lights_transform->setTransform( &sgcoord );
+        rwy_lights_transform->setTransform( sgdTrans );
     }
 
      // Update taxi lights transform
     if ( taxi_lights_transform->getNumKids() > 0 ) {
-        taxi_lights_transform->setTransform( &sgcoord );
+        taxi_lights_transform->setTransform( sgdTrans );
     }
+
+    delete light_pts;
 }
 
+void
+FGTileEntry::makeDList( ssgBranch *b )
+{
+    int nb = b->getNumKids();
+    for (int i = 0; i<nb; i++) {
+        ssgEntity *e = b->getKid(i);
+        if (e->isAKindOf(ssgTypeLeaf())) {
+            ((ssgLeaf*)e)->makeDList();
+        } else if (e->isAKindOf(ssgTypeBranch())) {
+            makeDList( (ssgBranch*)e );
+        }
+    }
+}
 
 void
 FGTileEntry::add_ssg_nodes( ssgBranch *terrain_branch,
@@ -987,8 +1005,15 @@ FGTileEntry::add_ssg_nodes( ssgBranch *terrain_branch,
 {
     // bump up the ref count so we can remove this later without
     // having ssg try to free the memory.
+#if PLIB_VERSION > 183
+    if ( fgGetBool( "/sim/rendering/use-display-list", true ) ) {
+        makeDList( terra_transform );
+    }
+#endif
+
     terra_transform->ref();
     terrain_branch->addKid( terra_transform );
+    globals->get_scenery()->register_placement_transform(terra_transform);
 
     SG_LOG( SG_TERRAIN, SG_DEBUG,
             "connected a tile into scene graph.  terra_transform = "
@@ -1001,6 +1026,7 @@ FGTileEntry::add_ssg_nodes( ssgBranch *terrain_branch,
         // having ssg try to free the memory.
         gnd_lights_transform->ref();
         gnd_lights_branch->addKid( gnd_lights_transform );
+        globals->get_scenery()->register_placement_transform(gnd_lights_transform);
     }
 
     if ( vasi_lights_transform != NULL ) {
@@ -1008,6 +1034,7 @@ FGTileEntry::add_ssg_nodes( ssgBranch *terrain_branch,
         // having ssg try to free the memory.
         vasi_lights_selector->ref();
         vasi_lights_selector->addKid( vasi_lights_transform );
+        globals->get_scenery()->register_placement_transform(vasi_lights_transform);
         vasi_lights_branch->addKid( vasi_lights_selector );
     }
 
@@ -1016,6 +1043,7 @@ FGTileEntry::add_ssg_nodes( ssgBranch *terrain_branch,
         // having ssg try to free the memory.
         rwy_lights_selector->ref();
         rwy_lights_selector->addKid( rwy_lights_transform );
+        globals->get_scenery()->register_placement_transform(rwy_lights_transform);
         rwy_lights_branch->addKid( rwy_lights_selector );
     }
 
@@ -1024,6 +1052,7 @@ FGTileEntry::add_ssg_nodes( ssgBranch *terrain_branch,
         // having ssg try to free the memory.
         taxi_lights_selector->ref();
         taxi_lights_selector->addKid( taxi_lights_transform );
+        globals->get_scenery()->register_placement_transform(taxi_lights_transform);
         taxi_lights_branch->addKid( taxi_lights_selector );
     }
 
@@ -1042,6 +1071,9 @@ FGTileEntry::disconnect_ssg_nodes()
         SG_LOG( SG_TERRAIN, SG_DEBUG, "removing a fully loaded tile!  terra_transform = " << terra_transform );
     }
         
+    // Unregister that one at the scenery manager
+    globals->get_scenery()->unregister_placement_transform(terra_transform);
+
     // find the terrain branch parent
     int pcount = terra_transform->getNumParents();
     if ( pcount > 0 ) {
@@ -1064,6 +1096,8 @@ FGTileEntry::disconnect_ssg_nodes()
 
     // find the ground lighting branch
     if ( gnd_lights_transform ) {
+        // Unregister that one at the scenery manager
+        globals->get_scenery()->unregister_placement_transform(gnd_lights_transform);
         pcount = gnd_lights_transform->getNumParents();
         if ( pcount > 0 ) {
             // find the first parent (should only be one)
@@ -1086,6 +1120,8 @@ FGTileEntry::disconnect_ssg_nodes()
 
     // find the vasi lighting branch
     if ( vasi_lights_transform ) {
+        // Unregister that one at the scenery manager
+        globals->get_scenery()->unregister_placement_transform(vasi_lights_transform);
         pcount = vasi_lights_transform->getNumParents();
         if ( pcount > 0 ) {
             // find the first parent (should only be one)
@@ -1108,6 +1144,8 @@ FGTileEntry::disconnect_ssg_nodes()
 
     // find the runway lighting branch
     if ( rwy_lights_transform ) {
+        // Unregister that one at the scenery manager
+        globals->get_scenery()->unregister_placement_transform(rwy_lights_transform);
         pcount = rwy_lights_transform->getNumParents();
         if ( pcount > 0 ) {
             // find the first parent (should only be one)
@@ -1130,6 +1168,8 @@ FGTileEntry::disconnect_ssg_nodes()
 
     // find the taxi lighting branch
     if ( taxi_lights_transform ) {
+        // Unregister that one at the scenery manager
+        globals->get_scenery()->unregister_placement_transform(taxi_lights_transform);
         pcount = taxi_lights_transform->getNumParents();
         if ( pcount > 0 ) {
             // find the first parent (should only be one)