]> git.mxchange.org Git - simgear.git/commitdiff
Modified Files:
authorfrohlich <frohlich>
Tue, 8 May 2007 06:11:15 +0000 (06:11 +0000)
committerfrohlich <frohlich>
Tue, 8 May 2007 06:11:15 +0000 (06:11 +0000)
simgear/bucket/newbucket.hxx simgear/scene/material/mat.cxx
simgear/scene/material/matlib.cxx
simgear/scene/material/matlib.hxx
simgear/scene/model/location.cxx
simgear/scene/tgdb/apt_signs.cxx simgear/scene/tgdb/leaf.cxx
simgear/scene/tgdb/leaf.hxx simgear/scene/tgdb/obj.cxx
simgear/scene/tgdb/obj.hxx
simgear/scene/util/SGUpdateVisitor.hxx: Reorganize scenegraph to
simplify top level structure.

simgear/bucket/newbucket.hxx
simgear/scene/material/mat.cxx
simgear/scene/material/matlib.cxx
simgear/scene/material/matlib.hxx
simgear/scene/model/location.cxx
simgear/scene/tgdb/apt_signs.cxx
simgear/scene/tgdb/leaf.cxx
simgear/scene/tgdb/leaf.hxx
simgear/scene/tgdb/obj.cxx
simgear/scene/tgdb/obj.hxx
simgear/scene/util/SGUpdateVisitor.hxx

index 2ba7de551e669d4a0da76fa0f5c901cf5265b8b4..955ce8b1b670f8f009514bb47db3517fb5326e8c 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <simgear/compiler.h>
 #include <simgear/constants.h>
+#include <simgear/math/SGMath.hxx>
 
 #ifdef SG_HAVE_STD_INCLUDES
 #  include <cmath>
@@ -252,7 +253,24 @@ public:
      * @return the height of the tile in meters.
      */
     double get_height_m() const;
+
+    /**
+     * @return the center of the bucket in geodetic coordinates.
+     */
+    SGGeod get_center() const
+    { return SGGeod::fromDeg(get_center_lon(), get_center_lat()); }
+
+    /**
+     * @return the center of the bucket in geodetic coordinates.
+     */
+    SGGeod get_corner(unsigned num) const
+    {
+        double lonFac = ((num + 1) & 2) ? 0.5 : -0.5;
+        double latFac = ((num    ) & 2) ? 0.5 : -0.5;
+        return SGGeod::fromDeg(get_center_lon() + lonFac*get_width(),
+                               get_center_lat() + latFac*get_height());
+    }
+
     // Informational methods.
 
     /**
index 8c93886a83b83e5531d5d41e46d1d2a59e6740fc..d9f5c82f3f6bbc0bff68ef4fa4507d4c80dd489f 100644 (file)
@@ -266,6 +266,7 @@ SGMaterial::build_state( bool defer_tex_load )
     for (unsigned int i = 0; i < _status.size(); i++)
     {
         osg::StateSet *stateSet = new osg::StateSet;
+        stateSet->setUserData(new SGMaterialUserData(this));
 
         // Set up the textured state
         osg::ShadeModel* shadeModel = new osg::ShadeModel;
index 7a8ea5440609ab5e928f4845df753a9c420d1f46..bd8a7725bc80aef6413a93b18e5686c105d5bc11 100644 (file)
@@ -216,7 +216,7 @@ bool SGMaterialLib::load( const string &fg_root, const string& mpath, const char
 
     osg::ref_ptr<osg::StateSet> lightStateSet = new osg::StateSet;
     {
-      lightStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+      lightStateSet->setRenderBinDetails(9, "DepthSortedBin");
       lightStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
 //       lightStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
 
@@ -552,13 +552,13 @@ void SGMaterialLib::load_next_deferred() {
     }
 }
 
-// Return the material from that given leaf
-const SGMaterial* SGMaterialLib::findMaterial(const osg::Node* leaf) const
+const SGMaterial*
+SGMaterialLib::findMaterial(const osg::StateSet* stateSet) const
 {
-  if (!leaf)
+  if (!stateSet)
     return 0;
   
-  const osg::Referenced* base = leaf->getUserData();
+  const osg::Referenced* base = stateSet->getUserData();
   if (!base)
     return 0;
 
index 14a0a8d10bd04364729ca4cc0b33a7bd3e1d62fe..52f414e054a11f544631b65f89bc219bf43899f6 100644 (file)
@@ -86,7 +86,7 @@ public:
     material_map_iterator end() { return matlib.end(); }
     const_material_map_iterator end() const { return matlib.end(); }
 
-    const SGMaterial* findMaterial(const osg::Node* leaf) const;
+    const SGMaterial* findMaterial(const osg::StateSet* stateSet) const;
 
     // Destructor
     ~SGMaterialLib ( void );
index cf9f0192ad41cbb7dd878f42516e3dd21dd131bb..ec572c8cc7233e00ea10abe4ed9004571421ee9e 100644 (file)
@@ -33,7 +33,6 @@
 #include <simgear/math/point3d.hxx>
 #include <simgear/math/polar3d.hxx>
 #include <simgear/math/sg_geodesy.hxx>
-#include <simgear/math/vector.hxx>
 
 #include "location.hxx"
 
index 543882c734e72f142f749513fe3feaea6cfd047e..97fef252208a1628745f34c5ef15cdc18d250553 100644 (file)
@@ -33,7 +33,6 @@
 
 #include <simgear/debug/logstream.hxx>
 #include <simgear/math/sg_types.hxx>
-#include <simgear/scene/tgdb/leaf.hxx>
 #include <simgear/scene/material/mat.hxx>
 #include <simgear/scene/material/matlib.hxx>
 
@@ -355,63 +354,27 @@ SGMakeSign(SGMaterialLib *matlib, const string& path, const string& content)
     return object;
 }
 
-
-
-
-
 osg::Node*
 SGMakeRunwaySign(SGMaterialLib *matlib, const string& path, const string& name)
 {
     // for demo purposes we assume each element (letter) is 1x1 meter.
     // Sign is placed 0.25 meters above the ground
 
-    osg::Group *object = new osg::Group;
-    object->setName(name);
-
-    double width = name.length() / 3.0;
-
-    string material = name;
-
-    point_list nodes;
-    point_list normals;
-    point_list texcoords;
-    int_list vertex_index;
-    int_list normal_index;
-    int_list tex_index;
-
-    nodes.push_back( Point3D( -width, 0, 0.25 ) );
-    nodes.push_back( Point3D( width + 1, 0, 0.25 ) );
-    nodes.push_back( Point3D( -width, 0, 1.25 ) );
-    nodes.push_back( Point3D( width + 1, 0, 1.25 ) );
+    float width = name.length() / 3.0;
 
-    normals.push_back( Point3D( 0, -1, 0 ) );
+    osg::Vec3 corner(-width, 0, 0.25f);
+    osg::Vec3 widthVec(2*width + 1, 0, 0);
+    osg::Vec3 heightVec(0, 0, 1);
+    osg::Geometry* geometry;
+    geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
 
-    texcoords.push_back( Point3D( 0, 0, 0 ) );
-    texcoords.push_back( Point3D( 1, 0, 0 ) );
-    texcoords.push_back( Point3D( 0, 1, 0 ) );
-    texcoords.push_back( Point3D( 1, 1, 0 ) );
-
-    vertex_index.push_back( 0 );
-    vertex_index.push_back( 1 );
-    vertex_index.push_back( 2 );
-    vertex_index.push_back( 3 );
-
-    normal_index.push_back( 0 );
-    normal_index.push_back( 0 );
-    normal_index.push_back( 0 );
-    normal_index.push_back( 0 );
-
-    tex_index.push_back( 0 );
-    tex_index.push_back( 1 );
-    tex_index.push_back( 2 );
-    tex_index.push_back( 3 );
-
-    osg::Node* leaf = SGMakeLeaf( path, GL_TRIANGLE_STRIP, matlib, material,
-                                  nodes, normals, texcoords,
-                                  vertex_index, normal_index, tex_index,
-                                  false, NULL );
+    SGMaterial *mat = matlib->find(name);
+    if (mat)
+      geometry->setStateSet(mat->get_state());
 
-    object->addChild(leaf);
+    osg::Geode* geode = new osg::Geode;
+    geode->setName(name);
+    geode->addDrawable(geometry);
 
-    return object;
+    return geode;
 }
index 1d3e6d9477f5b66532199ffcfbdb6e24acb36a7d..8dde0fb1b1c435df218574278692d89a129b3762 100644 (file)
@@ -54,22 +54,6 @@ typedef vector < int > int_list;
 typedef int_list::iterator int_list_iterator;
 typedef int_list::const_iterator int_point_list_iterator;
 
-
-static inline
-osg::Vec3 random_pt_inside_tri(const osg::Vec3& n1, const osg::Vec3& n2,
-                               const osg::Vec3& n3 )
-{
-    double a = sg_random();
-    double b = sg_random();
-    if ( a + b > 1.0 ) {
-        a = 1.0 - a;
-        b = 1.0 - b;
-    }
-    double c = 1 - a - b;
-
-    return n1*a + n2*b + n3*c;
-}
-
 /// class to implement the TrinagleFunctor class
 struct SGRandomSurfacePointsFill {
   osg::Vec3Array* lights;
@@ -97,6 +81,20 @@ struct SGRandomSurfacePointsFill {
       }
     }
   }
+
+  osg::Vec3 random_pt_inside_tri(const osg::Vec3& n1, const osg::Vec3& n2,
+                                 const osg::Vec3& n3)
+  {
+    double a = sg_random();
+    double b = sg_random();
+    if ( a + b > 1.0 ) {
+      a = 1 - a;
+      b = 1 - b;
+    }
+    double c = 1 - a - b;
+    
+    return n1*a + n2*b + n3*c;
+  }
 };
 
 static void SGGenRandomSurfacePoints( osg::Geometry *leaf, double factor, 
@@ -109,13 +107,13 @@ static void SGGenRandomSurfacePoints( osg::Geometry *leaf, double factor,
 }
 
 
+
 ////////////////////////////////////////////////////////////////////////
 // Scenery loaders.
 ////////////////////////////////////////////////////////////////////////
 
-osg::Node* SGMakeLeaf( const string& path,
-                     const GLenum ty, 
-                     SGMaterialLib *matlib, const string& material,
+osg::Drawable* SGMakeLeaf( const string& path,
+                     const GLenum ty, SGMaterial *mat,
                      const point_list& nodes, const point_list& normals,
                      const point_list& texcoords,
                      const int_list& node_index,
@@ -127,31 +125,6 @@ osg::Node* SGMakeLeaf( const string& path,
     osg::StateSet *state = 0;
     float coverage = -1;
 
-    SGMaterial *mat = matlib->find( material );
-    if ( mat == NULL ) {
-        // see if this is an on the fly texture
-        string file = path;
-        string::size_type pos = file.rfind( "/" );
-        file = file.substr( 0, pos );
-        // cout << "current file = " << file << endl;
-        file += "/";
-        file += material;
-        // cout << "current file = " << file << endl;
-        if ( ! matlib->add_item( file ) ) {
-            SG_LOG( SG_TERRAIN, SG_ALERT, 
-                    "Ack! unknown usemtl name = " << material 
-                    << " in " << path );
-        } else {
-            // locate our newly created material
-            mat = matlib->find( material );
-            if ( mat == NULL ) {
-                SG_LOG( SG_TERRAIN, SG_ALERT, 
-                        "Ack! bad on the fly material create = "
-                        << material << " in " << path );
-            }
-        }
-    }
-
     if ( mat != NULL ) {
         // set the texture width and height values for this
         // material
@@ -159,10 +132,6 @@ osg::Node* SGMakeLeaf( const string& path,
         tex_height = mat->get_ysize();
         state = mat->get_state();
         coverage = mat->get_light_coverage();
-        // cout << "(w) = " << tex_width << " (h) = "
-        //      << tex_width << endl;
-    } else {
-        coverage = -1;
     }
 
     int i;
@@ -240,12 +209,9 @@ osg::Node* SGMakeLeaf( const string& path,
     geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
     geometry->setTexCoordArray(0, tl);
     geometry->addPrimitiveSet(new osg::DrawArrays(ty, 0, vl->size()));
-    osg::Geode* geode = new osg::Geode;
-    geode->addDrawable(geometry);
 
     // lookup the state record
-    geode->setStateSet(state);
-    geode->setUserData( new SGMaterialUserData(mat) );
+    geometry->setStateSet(state);
 
     if ( calc_lights ) {
         if ( coverage > 0.0 ) {
@@ -254,9 +220,10 @@ osg::Node* SGMakeLeaf( const string& path,
                        << coverage << ", pushing up to 10000");
                 coverage = 10000;
             }
-            SGGenRandomSurfacePoints(geometry, coverage, lights );
+            SGGenRandomSurfacePoints(geometry, coverage, lights);
         }
     }
 
-    return geode;
+    return geometry;
 }
+
index eb4e663dd26fad6f229363fb83e75861ddb381a1..61506ec9c225ac91270ae6dc6a7a77e3d5a9097d 100644 (file)
@@ -46,9 +46,8 @@ class SGMaterialLib;            // forward declaration.
 
 
 // Create a ssg leaf
-osg::Node* SGMakeLeaf( const string& path,
-                     const GLenum ty,
-                     SGMaterialLib *matlib, const string& material,
+osg::Drawable* SGMakeLeaf( const string& path,
+                     const GLenum ty, SGMaterial *mat,
                      const point_list& nodes, const point_list& normals,
                      const point_list& texcoords,
                      const int_list& node_index,
index 8e900a80d7121f7a0265a581c606ce6ec0f9001d..5251a263419546283d0f01983b44c611532adb43 100644 (file)
@@ -33,6 +33,7 @@
 #include STL_STRING
 
 #include <osg/Depth>
+#include <osg/Fog>
 #include <osg/Geode>
 #include <osg/Geometry>
 #include <osg/Group>
 #include <osg/MatrixTransform>
 #include <osg/StateSet>
 
+#include <osgUtil/Optimizer>
+#include <osgDB/WriteFile>
+
 #include <simgear/bucket/newbucket.hxx>
 #include <simgear/io/sg_binobj.hxx>
 #include <simgear/math/sg_geodesy.hxx>
+#include <simgear/math/sg_random.h>
 #include <simgear/math/sg_types.hxx>
 #include <simgear/misc/texcoord.hxx>
 #include <simgear/scene/material/mat.hxx>
 #include <simgear/scene/material/matlib.hxx>
 #include <simgear/scene/util/SGUpdateVisitor.hxx>
+#include <simgear/scene/util/SGNodeMasks.hxx>
 #include <simgear/scene/tgdb/leaf.hxx>
 #include <simgear/scene/tgdb/pt_lights.hxx>
 #include <simgear/scene/tgdb/userdata.hxx>
@@ -64,14 +70,12 @@ struct Leaf {
 
 
 // Generate an ocean tile
-bool SGGenTile( const string& path, SGBucket b,
-                Point3D *center, double *bounding_radius,
+bool SGGenTile( const string& path, const SGBucket& b,
                 SGMaterialLib *matlib, osg::Group* group )
 {
     osg::StateSet *state = 0;
 
     double tex_width = 1000.0;
-    // double tex_height;
 
     // find Ocean material in the properties list
     SGMaterial *mat = matlib->find( "Ocean" );
@@ -79,7 +83,6 @@ bool SGGenTile( const string& path, SGBucket b,
         // set the texture width and height values for this
         // material
         tex_width = mat->get_xsize();
-        // tex_height = newmat->get_ysize();
         
         // set ssgState
         state = mat->get_state();
@@ -90,16 +93,14 @@ bool SGGenTile( const string& path, SGBucket b,
     }
 
     // Calculate center point
+    SGVec3d cartCenter = SGVec3d::fromGeod(b.get_center());
+    Point3D center = Point3D(cartCenter[0], cartCenter[1], cartCenter[2]);
+
     double clon = b.get_center_lon();
     double clat = b.get_center_lat();
     double height = b.get_height();
     double width = b.get_width();
 
-    *center = sgGeodToCart( Point3D(clon*SGD_DEGREES_TO_RADIANS,
-                                    clat*SGD_DEGREES_TO_RADIANS,
-                                    0.0) );
-    // cout << "center = " << center << endl;;
-    
     // Caculate corner vertices
     Point3D geod[4];
     geod[0] = Point3D( clon - width/2.0, clat - height/2.0, 0.0 );
@@ -118,14 +119,10 @@ bool SGGenTile( const string& path, SGBucket b,
     Point3D cart[4], rel[4];
     for ( i = 0; i < 4; ++i ) {
         cart[i] = sgGeodToCart(rad[i]);
-        rel[i] = cart[i] - *center;
+        rel[i] = cart[i] - center;
         // cout << "corner " << i << " = " << cart[i] << endl;
     }
 
-    // Calculate bounding radius
-    *bounding_radius = center->distance3D( cart[0] );
-    // cout << "bounding radius = " << t->bounding_radius << endl;
-
     // Calculate normals
     Point3D normals[4];
     for ( i = 0; i < 4; ++i ) {
@@ -252,7 +249,7 @@ bool SGGenTile( const string& path, SGBucket b,
  * @param material_name The name of the surface's material.
  */
 static void
-gen_random_surface_objects (osg::Node *leaf,
+gen_random_surface_objects (osg::Drawable *leaf,
                             osg::Group *branch,
                             Point3D *center,
                             SGMaterial *mat )
@@ -320,7 +317,7 @@ class SGLightOffsetTransform : public osg::Transform {
 public:
 #define SCALE_FACTOR 0.94
   virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
-                                         osg::NodeVisitor* nv) const 
+                                         osg::NodeVisitor* nv) const
   {
     if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR) {
       double scaleFactor = SCALE_FACTOR;
@@ -349,13 +346,44 @@ public:
       transform(3,0) = center[0]*(1 - scaleFactor);
       transform(3,1) = center[1]*(1 - scaleFactor);
       transform(3,2) = center[2]*(1 - scaleFactor);
-      matrix.preMult(transform);
+      matrix.postMult(transform);
     }
     return true;
   }
 #undef SCALE_FACTOR
 };
 
+static SGMaterial* findMaterial(const std::string& material,
+                                const std::string& path,
+                                SGMaterialLib *matlib)
+{
+  SGMaterial *mat = matlib->find( material );
+  if (mat)
+    return mat;
+
+  // see if this is an on the fly texture
+  string file = path;
+  string::size_type pos = file.rfind( "/" );
+  file = file.substr( 0, pos );
+  // cout << "current file = " << file << endl;
+  file += "/";
+  file += material;
+  // cout << "current file = " << file << endl;
+  if ( ! matlib->add_item( file ) ) {
+    SG_LOG( SG_TERRAIN, SG_ALERT, 
+            "Ack! unknown usemtl name = " << material 
+            << " in " << path );
+  } else {
+    // locate our newly created material
+    mat = matlib->find( material );
+    if ( mat == NULL ) {
+      SG_LOG( SG_TERRAIN, SG_ALERT, 
+              "Ack! bad on the fly material create = "
+              << material << " in " << path );
+    }
+  }
+  return mat;
+}
 
 \f
 ////////////////////////////////////////////////////////////////////////
@@ -363,15 +391,14 @@ public:
 ////////////////////////////////////////////////////////////////////////
 
 // Load an Binary obj file
-bool SGBinObjLoad( const string& path, const bool is_base,
-                   Point3D *center,
-                   double *bounding_radius,
+static bool SGBinObjLoad( const string& path, const bool is_base,
+                   Point3D& center,
                    SGMaterialLib *matlib,
                    bool use_random_objects,
-                   osg::Group *geometry,
-                   osg::Group *_vasi_lights,
-                   osg::Group *_rwy_lights,
-                   osg::Group *_taxi_lights,
+                   osg::Group *local_terrain,
+                   osg::Group *vasi_lights,
+                   osg::Group *rwy_lights,
+                   osg::Group *taxi_lights,
                    osg::Vec3Array *ground_lights )
 {
     SGBinObject obj;
@@ -380,37 +407,10 @@ bool SGBinObjLoad( const string& path, const bool is_base,
         return false;
     }
 
-    // Ok, somehow polygon offset for lights ...
-    // Could never make the polygon offset for our lights get right.
-    // So, why not in this way ...
-    SGLightOffsetTransform* vasi_lights = 0;
-    if (_vasi_lights) {
-      vasi_lights = new SGLightOffsetTransform;
-      _vasi_lights->addChild(vasi_lights);
-    }
-    SGLightOffsetTransform *rwy_lights = 0;
-    if (_rwy_lights) {
-      rwy_lights = new SGLightOffsetTransform;
-      _rwy_lights->addChild(rwy_lights);
-    }
-    SGLightOffsetTransform *taxi_lights = 0;
-    if (_taxi_lights) {
-      taxi_lights = new SGLightOffsetTransform;
-      _taxi_lights->addChild(taxi_lights);
-    }
-
-    osg::Group *local_terrain = new osg::Group;
-    local_terrain->setName( "LocalTerrain" );
-    geometry->addChild( local_terrain );
-
-    geometry->setName(path);
-
     // reference point (center offset/bounding sphere)
-    *center = obj.get_gbs_center();
-    *bounding_radius = obj.get_gbs_radius();
+    center = obj.get_gbs_center();
 
     point_list const& nodes = obj.get_wgs84_nodes();
-    // point_list const& colors = obj.get_colors();
     point_list const& normals = obj.get_normals();
     point_list const& texcoords = obj.get_texcoords();
 
@@ -419,6 +419,9 @@ bool SGBinObjLoad( const string& path, const bool is_base,
 
     group_list::size_type i;
 
+    osg::Geode* geode = new osg::Geode;
+    local_terrain->addChild( geode );
+
     // generate points
     string_list const& pt_materials = obj.get_pt_materials();
     group_list const& pts_v = obj.get_pts_v();
@@ -427,7 +430,7 @@ bool SGBinObjLoad( const string& path, const bool is_base,
         // cout << "pts_v.size() = " << pts_v.size() << endl;
         if ( pt_materials[i].substr(0, 3) == "RWY" ) {
             // airport environment lighting
-            SGVec3d up(center->x(), center->y(), center->z());
+            SGVec3d up(center.x(), center.y(), center.z());
             // returns a transform -> lod -> leaf structure
             osg::Node *branch = SGMakeDirectionalLights( nodes, normals,
                                                          pts_v[i], pts_n[i],
@@ -444,27 +447,30 @@ bool SGBinObjLoad( const string& path, const bool is_base,
             }
         } else {
             // other geometry
-            material = pt_materials[i];
+            SGMaterial *mat = findMaterial( pt_materials[i], path, matlib );
             tex_index.clear();
-            osg::Node *leaf = SGMakeLeaf( path, GL_POINTS, matlib, material,
+            osg::Drawable *leaf = SGMakeLeaf( path, GL_POINTS, mat,
                                         nodes, normals, texcoords,
                                         pts_v[i], pts_n[i], tex_index,
                                         false, ground_lights );
-            local_terrain->addChild( leaf );
+            
+
+
+            geode->addDrawable( leaf );
         }
     }
 
     // Put all randomly-placed objects under a separate branch
     // (actually an ssgRangeSelector) named "random-models".
     osg::Group * random_object_branch = 0;
-    if (use_random_objects) {
-        osg::LOD* object_lod = new osg::LOD;
-        object_lod->setName("random-models");
-        geometry->addChild(object_lod);
-        random_object_branch = new osg::Group;
-        // Maximum 20km range for random objects
-        object_lod->addChild(random_object_branch, 0, 20000);
-    }
+//     if (use_random_objects) {
+//         osg::LOD* object_lod = new osg::LOD;
+//         object_lod->setName("random-models");
+//         geometry->addChild(object_lod);
+//         random_object_branch = new osg::Group;
+//         // Maximum 20km range for random objects
+//         object_lod->addChild(random_object_branch, 0, 20000);
+//     }
 
     typedef map<string,list<Leaf> > LeafMap;
     LeafMap leafMap;
@@ -499,65 +505,48 @@ bool SGBinObjLoad( const string& path, const bool is_base,
 
     LeafMap::iterator lmi = leafMap.begin();
     while ( lmi != leafMap.end() ) {
+        SGMaterial *mat = findMaterial( lmi->first, path, matlib );
         list<Leaf> &leaf_list = lmi->second;
         list<Leaf>::iterator li = leaf_list.begin();
         while ( li != leaf_list.end() ) {
             Leaf &leaf = *li;
             int ind = leaf.index;
             if ( leaf.type == GL_TRIANGLES ) {
-                osg::Node *leaf = SGMakeLeaf( path, GL_TRIANGLES, matlib,
-                                            tri_materials[ind],
+                osg::Drawable *leaf = SGMakeLeaf( path, GL_TRIANGLES, mat,
                                             nodes, normals, texcoords,
                                             tris_v[ind], tris_n[ind], tris_tc[ind],
                                             is_base, ground_lights );
-                if ( use_random_objects ) {
-                    SGMaterial *mat = matlib->find( tri_materials[ind] );
-                    if ( mat == NULL ) {
-                        SG_LOG( SG_INPUT, SG_ALERT,
-                                "Unknown material for random surface objects = "
-                                << tri_materials[ind] );
-                    } else {
+                if ( random_object_branch ) {
+                    if ( mat ) {
                         gen_random_surface_objects( leaf, random_object_branch,
-                                                    center, mat );
+                                                    &center, mat );
                     }
                 }
-                local_terrain->addChild( leaf );
+                geode->addDrawable( leaf );
             } else if ( leaf.type == GL_TRIANGLE_STRIP ) {
-                osg::Node *leaf = SGMakeLeaf( path, GL_TRIANGLE_STRIP,
-                                            matlib, strip_materials[ind],
+                osg::Drawable *leaf = SGMakeLeaf( path, GL_TRIANGLE_STRIP, mat,
                                             nodes, normals, texcoords,
                                             strips_v[ind], strips_n[ind], strips_tc[ind],
                                             is_base, ground_lights );
-                if ( use_random_objects ) {
-                    SGMaterial *mat = matlib->find( strip_materials[ind] );
-                    if ( mat == NULL ) {
-                        SG_LOG( SG_INPUT, SG_ALERT,
-                                "Unknown material for random surface objects = "
-                                << strip_materials[ind] );
-                    } else {
+                if ( random_object_branch ) {
+                    if ( mat ) {
                         gen_random_surface_objects( leaf, random_object_branch,
-                                                    center, mat );
+                                                    &center, mat );
                     }
                 }
-                local_terrain->addChild( leaf );
+                geode->addDrawable( leaf );
             } else {
-                osg::Node *leaf = SGMakeLeaf( path, GL_TRIANGLE_FAN,
-                                            matlib, fan_materials[ind],
+                osg::Drawable *leaf = SGMakeLeaf( path, GL_TRIANGLE_FAN, mat,
                                             nodes, normals, texcoords,
                                             fans_v[ind], fans_n[ind], fans_tc[ind],
                                             is_base, ground_lights );
-                if ( use_random_objects ) {
-                    SGMaterial *mat = matlib->find( fan_materials[ind] );
-                    if ( mat == NULL ) {
-                        SG_LOG( SG_INPUT, SG_ALERT,
-                                "Unknown material for random surface objects = "
-                                << fan_materials[ind] );
-                    } else {
+                if ( random_object_branch ) {
+                    if ( mat ) {
                         gen_random_surface_objects( leaf, random_object_branch,
-                                                    center, mat );
+                                                    &center, mat );
                     }
                 }
-                local_terrain->addChild( leaf );
+                geode->addDrawable( leaf );
             }
             ++li;
         }
@@ -566,3 +555,236 @@ bool SGBinObjLoad( const string& path, const bool is_base,
 
     return true;
 }
+
+
+
+
+static osg::Node*
+gen_lights( SGMaterialLib *matlib, osg::Vec3Array *lights, int inc, float bright )
+{
+    // generate a repeatable random seed
+    sg_srandom( (unsigned)(*lights)[0][0] );
+
+    // Allocate ssg structure
+    osg::Vec3Array *vl = new osg::Vec3Array;
+    osg::Vec4Array *cl = new osg::Vec4Array;
+
+    for ( unsigned i = 0; i < lights->size(); ++i ) {
+        // this loop is slightly less efficient than it otherwise
+        // could be, but we want a red light to always be red, and a
+        // yellow light to always be yellow, etc. so we are trying to
+        // preserve the random sequence.
+        float zombie = sg_random();
+        if ( i % inc == 0 ) {
+            vl->push_back( (*lights)[i] );
+
+            // factor = sg_random() ^ 2, range = 0 .. 1 concentrated towards 0
+            float factor = sg_random();
+            factor *= factor;
+
+            osg::Vec4 color;
+            if ( zombie > 0.5 ) {
+                // 50% chance of yellowish
+                color = osg::Vec4( 0.9, 0.9, 0.3, bright - factor * 0.2 );
+            } else if ( zombie > 0.15 ) {
+                // 35% chance of whitish
+                color = osg::Vec4( 0.9, 0.9, 0.8, bright - factor * 0.2 );
+            } else if ( zombie > 0.05 ) {
+                // 10% chance of orangish
+                color = osg::Vec4( 0.9, 0.6, 0.2, bright - factor * 0.2 );
+            } else {
+                // 5% chance of redish
+                color = osg::Vec4( 0.9, 0.2, 0.2, bright - factor * 0.2 );
+            }
+            cl->push_back( color );
+        }
+    }
+
+    // create ssg leaf
+    osg::Geometry* geometry = new osg::Geometry;
+    geometry->setVertexArray(vl);
+    geometry->setColorArray(cl);
+    geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
+    geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vl->size()));
+    osg::Geode* geode = new osg::Geode;
+    geode->addDrawable(geometry);
+
+    // assign state
+    SGMaterial *mat = matlib->find( "GROUND_LIGHTS" );
+    geometry->setStateSet(mat->get_state());
+
+    return geode;
+}
+
+class SGTileUpdateCallback : public osg::NodeCallback {
+public:
+  virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+  {
+    assert(dynamic_cast<osg::Switch*>(node));
+    assert(dynamic_cast<SGUpdateVisitor*>(nv));
+
+    osg::Switch* lightSwitch = static_cast<osg::Switch*>(node);
+    SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
+
+    // The current sun angle in degree
+    float sun_angle = updateVisitor->getSunAngleDeg();
+
+    // vasi is always on
+    lightSwitch->setValue(0, true);
+    if (sun_angle > 85 || updateVisitor->getVisibility() < 5000) {
+      // runway and taxi
+      lightSwitch->setValue(1, true);
+      lightSwitch->setValue(2, true);
+    } else {
+      // runway and taxi
+      lightSwitch->setValue(1, false);
+      lightSwitch->setValue(2, false);
+    }
+    
+    // ground lights
+    if ( sun_angle > 95 )
+      lightSwitch->setValue(5, true);
+    else
+      lightSwitch->setValue(5, false);
+    if ( sun_angle > 92 )
+      lightSwitch->setValue(4, true);
+    else
+      lightSwitch->setValue(4, false);
+    if ( sun_angle > 89 )
+      lightSwitch->setValue(3, true);
+    else
+      lightSwitch->setValue(3, false);
+
+    traverse(node, nv);
+  }
+};
+
+class SGRunwayLightFogUpdateCallback : public osg::StateAttribute::Callback {
+public:
+  virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
+  {
+    assert(dynamic_cast<SGUpdateVisitor*>(nv));
+    assert(dynamic_cast<osg::Fog*>(sa));
+    SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
+    osg::Fog* fog = static_cast<osg::Fog*>(sa);
+    fog->setMode(osg::Fog::EXP2);
+    fog->setColor(updateVisitor->getFogColor().osg());
+    fog->setDensity(updateVisitor->getRunwayFogExp2Density());
+  }
+};
+
+class SGTaxiLightFogUpdateCallback : public osg::StateAttribute::Callback {
+public:
+  virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
+  {
+    assert(dynamic_cast<SGUpdateVisitor*>(nv));
+    assert(dynamic_cast<osg::Fog*>(sa));
+    SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
+    osg::Fog* fog = static_cast<osg::Fog*>(sa);
+    fog->setMode(osg::Fog::EXP2);
+    fog->setColor(updateVisitor->getFogColor().osg());
+    fog->setDensity(updateVisitor->getTaxiFogExp2Density());
+  }
+};
+
+class SGGroundLightFogUpdateCallback : public osg::StateAttribute::Callback {
+public:
+  virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
+  {
+    assert(dynamic_cast<SGUpdateVisitor*>(nv));
+    assert(dynamic_cast<osg::Fog*>(sa));
+    SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
+    osg::Fog* fog = static_cast<osg::Fog*>(sa);
+    fog->setMode(osg::Fog::EXP2);
+    fog->setColor(updateVisitor->getFogColor().osg());
+    fog->setDensity(updateVisitor->getGroundLightsFogExp2Density());
+  }
+};
+
+
+osg::Node*
+SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects)
+{
+  osg::Group* vasiLights = new osg::Group;
+  osg::StateSet* stateSet = vasiLights->getOrCreateStateSet();
+  osg::Fog* fog = new osg::Fog;
+  fog->setUpdateCallback(new SGRunwayLightFogUpdateCallback);
+  stateSet->setAttribute(fog);
+
+  osg::Group* rwyLights = new osg::Group;
+  stateSet = rwyLights->getOrCreateStateSet();
+  fog = new osg::Fog;
+  fog->setUpdateCallback(new SGRunwayLightFogUpdateCallback);
+  stateSet->setAttribute(fog);
+
+  osg::Group* taxiLights = new osg::Group;
+  stateSet = taxiLights->getOrCreateStateSet();
+  fog = new osg::Fog;
+  fog->setUpdateCallback(new SGTaxiLightFogUpdateCallback);
+  stateSet->setAttribute(fog);
+
+  osg::Group* groundLights0 = new osg::Group;
+  stateSet = groundLights0->getOrCreateStateSet();
+  fog = new osg::Fog;
+  fog->setUpdateCallback(new SGGroundLightFogUpdateCallback);
+  stateSet->setAttribute(fog);
+
+  osg::Group* groundLights1 = new osg::Group;
+  stateSet = groundLights1->getOrCreateStateSet();
+  fog = new osg::Fog;
+  fog->setUpdateCallback(new SGGroundLightFogUpdateCallback);
+  stateSet->setAttribute(fog);
+
+  osg::Group* groundLights2 = new osg::Group;
+  stateSet = groundLights2->getOrCreateStateSet();
+  fog = new osg::Fog;
+  fog->setUpdateCallback(new SGGroundLightFogUpdateCallback);
+  stateSet->setAttribute(fog);
+
+  osg::Switch* lightSwitch = new osg::Switch;
+  lightSwitch->setUpdateCallback(new SGTileUpdateCallback);
+  lightSwitch->addChild(vasiLights, true);
+  lightSwitch->addChild(rwyLights, true);
+  lightSwitch->addChild(taxiLights, true);
+  lightSwitch->addChild(groundLights0, true);
+  lightSwitch->addChild(groundLights1, true);
+  lightSwitch->addChild(groundLights2, true);
+
+  osg::Group* lightGroup = new SGLightOffsetTransform;
+  lightGroup->addChild(lightSwitch);
+  unsigned nodeMask = ~0u;
+  nodeMask &= ~SG_NODEMASK_CASTSHADOW_BIT;
+  nodeMask &= ~SG_NODEMASK_RECIEVESHADOW_BIT;
+  nodeMask &= ~SG_NODEMASK_PICK_BIT;
+  nodeMask &= ~SG_NODEMASK_TERRAIN_BIT;
+  lightGroup->setNodeMask(nodeMask);
+  
+  osg::Group* terrainGroup = new osg::Group;
+
+  osg::ref_ptr<osg::Vec3Array> light_pts = new osg::Vec3Array;
+  Point3D center;
+  SGBinObjLoad(path, calc_lights, center, matlib, use_random_objects,
+               terrainGroup, vasiLights, rwyLights, taxiLights, light_pts.get());
+
+  if ( light_pts->size() ) {
+    osg::Node *lights;
+    
+    lights = gen_lights( matlib, light_pts.get(), 4, 0.7 );
+    groundLights0->addChild( lights );
+    
+    lights = gen_lights( matlib, light_pts.get(), 2, 0.85 );
+    groundLights1->addChild( lights );
+    
+    lights = gen_lights( matlib, light_pts.get(), 1, 1.0 );
+    groundLights2->addChild( lights );
+  }
+
+  // The toplevel transform for that tile.
+  osg::MatrixTransform* transform = new osg::MatrixTransform;
+  transform->setName(path);
+  transform->setMatrix(osg::Matrix::translate(osg::Vec3d(center[0], center[1], center[2])));
+  transform->addChild(terrainGroup);
+  transform->addChild(lightGroup);
+
+  return transform;
+}
index 5e3ae30a586bc1107aa10d25e25aa41dbf68dada..34080c0cef9e537ce81a4ef7064037396f32d7a5 100644 (file)
@@ -45,23 +45,12 @@ SG_USING_STD(string);
 class SGBucket;
 class SGMaterialLib;
 
-
-// Load a Binary obj file
-bool SGBinObjLoad( const string& path, const bool is_base,
-                   Point3D *center,
-                   double *bounding_radius,
-                   SGMaterialLib *matlib,
-                   bool use_random_objects,
-                   osg::Group *geometry,
-                   osg::Group *vasi_lights,
-                   osg::Group *rwy_lights,
-                   osg::Group *taxi_lights,
-                   osg::Vec3Array *ground_lights );
-
 // Generate an ocean tile
-bool SGGenTile( const string& path, SGBucket b,
-                Point3D *center, double *bounding_radius,
+bool SGGenTile( const string& path, const SGBucket& b,
                 SGMaterialLib *matlib, osg::Group *geometry );
 
+osg::Node*
+SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects);
+
 
 #endif // _SG_OBJ_HXX
index 68f8ecdb878defafd8b78ad74273990cc5d6c3da..74d60e995169c474d38bc6b84940fb48687a7f8c 100644 (file)
 
 class SGUpdateVisitor : public osgUtil::UpdateVisitor {
 public:
-  SGUpdateVisitor()
+  SGUpdateVisitor() :
+    mVisibility(-1)
   {
     // Need to traverse all children, else some LOD nodes do not get updated
     // Note that the broad number of updates is not done due to
     // the update callback in the global position node.
     setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
+    setVisibility(10000);
   }
   void setViewData(const SGVec3d& globalEyePos,
                    const SGQuatd& globalViewOrientation)
@@ -48,15 +50,32 @@ public:
     mHorizLocalDown = mGlobalHorizLocalOr.backTransform(SGVec3d(0, 0, 1));
   }
 
-  void setSceneryCenter(const SGVec3d& sceneryCenter)
-  {
-    mSceneryCenter = sceneryCenter;
-  }
-
   void setVisibility(double visibility)
   {
+    if (mVisibility == visibility)
+      return;
     mVisibility = visibility;
     mSqrVisibility = visibility*visibility;
+
+    double m_log01 = -log( 0.01 );
+    double sqrt_m_log01 = sqrt( m_log01 );
+    double fog_exp_density = m_log01 / visibility;
+    double fog_exp2_density = sqrt_m_log01 / visibility;
+    double ground_exp2_punch_through = sqrt_m_log01 / (visibility * 1.5);
+    double rwy_exp2_punch_through, taxi_exp2_punch_through;
+    if ( visibility < 8000 ) {
+      rwy_exp2_punch_through = sqrt_m_log01 / (visibility * 2.5);
+      taxi_exp2_punch_through = sqrt_m_log01 / (visibility * 1.5);
+    } else {
+      rwy_exp2_punch_through = sqrt_m_log01 / ( 8000 * 2.5 );
+      taxi_exp2_punch_through = sqrt_m_log01 / ( 8000 * 1.5 );
+    }
+    
+    mFogExpDensity = fog_exp_density;
+    mFogExp2Density = fog_exp2_density;
+    mRunwayFogExp2Density = rwy_exp2_punch_through;
+    mTaxiFogExp2Density = taxi_exp2_punch_through;
+    mGroundLightsFogExp2Density = ground_exp2_punch_through;
   }
 
   double getVisibility() const
@@ -64,6 +83,17 @@ public:
   double getSqrVisibility() const
   { return mSqrVisibility; }
 
+  double getFogExpDensity() const
+  { return mFogExpDensity; }
+  double getFogExp2Density() const
+  { return mFogExp2Density; }
+  double getRunwayFogExp2Density() const
+  { return mRunwayFogExp2Density; }
+  double getTaxiFogExp2Density() const
+  { return mTaxiFogExp2Density; }
+  double getGroundLightsFogExp2Density() const
+  { return mGroundLightsFogExp2Density; }
+
   const SGVec3d& getGlobalEyePos() const
   { return mGlobalEyePos; }
   const SGGeod& getGeodEyePos() const
@@ -80,11 +110,15 @@ public:
   { return mHorizLocalDown; }
 
   void setLight(const SGVec3f& direction, const SGVec4f& ambient,
-                const SGVec4f& diffuse, const SGVec4f& specular)
+                const SGVec4f& diffuse, const SGVec4f& specular,
+                const SGVec4f& fogColor, double sunAngleDeg)
   {
     mLightDirection = direction;
     mAmbientLight = ambient;
     mDiffuseLight = diffuse;
+    mSpecularLight = specular;
+    mFogColor = fogColor;
+    mSunAngleDeg = sunAngleDeg;
   }
 
   const SGVec3f& getLightDirection() const
@@ -95,6 +129,11 @@ public:
   { return mDiffuseLight; }
   const SGVec4f& getSpecularLight() const
   { return mSpecularLight; }
+  const SGVec4f& getFogColor() const
+  { return mFogColor; }
+
+  double getSunAngleDeg() const
+  { return mSunAngleDeg; }
 
 private:
   SGGeod mGlobalGeodEyePos;
@@ -105,15 +144,21 @@ private:
   SGVec3d mHorizLocalEast;
   SGVec3d mHorizLocalDown;
 
-  SGVec3d mSceneryCenter;
-
   double mVisibility;
   double mSqrVisibility;
+  double mFogExpDensity;
+  double mFogExp2Density;
+  double mRunwayFogExp2Density;
+  double mTaxiFogExp2Density;
+  double mGroundLightsFogExp2Density;
 
   SGVec3f mLightDirection;
   SGVec4f mAmbientLight;
   SGVec4f mDiffuseLight;
   SGVec4f mSpecularLight;
+  SGVec4f mFogColor;
+
+  double mSunAngleDeg;
 };
 
 #endif