]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/sky/cloudfield.cxx
simgear/scene/sky/sky.cxx: Include sg_inlines.h with simgear/ prefix as all other...
[simgear.git] / simgear / scene / sky / cloudfield.cxx
index 18ecd53a8d44ab6fa9624f7caa97e906ae6925bf..7d738563f5ac936e2ccdf5e160033c0dd7e464fc 100644 (file)
 #  include <simgear_config.h>
 #endif
 
+#include <osg/Fog>
 #include <osg/Texture2D>
 #include <osg/PositionAttitudeTransform>
+#include <osg/Vec4f>
 
 #include <simgear/compiler.h>
 
-#include <plib/sg.h>
 #include <simgear/math/sg_random.h>
 #include <simgear/math/sg_geodesy.hxx>
-#include <simgear/math/polar3d.hxx>
 
 #include <algorithm>
 #include <vector>
@@ -41,6 +41,7 @@ using std::vector;
 
 #include <simgear/environment/visual_enviro.hxx>
 #include <simgear/scene/util/RenderConstants.hxx>
+#include <simgear/scene/util/SGUpdateVisitor.hxx>
 #include "sky.hxx"
 #include "newcloud.hxx"
 #include "cloudfield.hxx"
@@ -60,16 +61,10 @@ using std::vector;
 using namespace simgear;
 
 
-#if defined (__CYGWIN__)
-#include <ieeefp.h>
-#endif
-
 float SGCloudField::fieldSize = 50000.0f;
-float SGCloudField::coverage = 1.0f;
 double SGCloudField::timer_dt = 0.0;
 float SGCloudField::view_distance = 20000.0f;
-sgVec3 SGCloudField::view_vec, SGCloudField::view_X, SGCloudField::view_Y;
-
+SGVec3f SGCloudField::view_vec, SGCloudField::view_X, SGCloudField::view_Y;
 
 // reposition the cloud layer at the specified origin and orientation
 bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon, double lat,
@@ -77,6 +72,10 @@ bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
 {
     osg::Matrix T, LON, LAT;
     
+    // Always update the altitude transform, as this allows
+    // the clouds to rise and fall smoothly depending on environment updates.
+    altitude_transform->setPosition(osg::Vec3d(0.0, 0.0, (double) asl));
+    
     // Calculating the reposition information is expensive. 
     // Only perform the reposition every 60 frames.
     reposition_count = (reposition_count + 1) % 60;
@@ -90,7 +89,7 @@ bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
         // First time or very large distance
         SGVec3<double> cart;
         SGGeodesy::SGGeodToCart(SGGeod::fromRad(lon, lat), cart);
-        T.makeTranslate(cart.osg());
+        T.makeTranslate(toOsg(cart));
         
         LON.makeRotate(lon, osg::Vec3(0, 0, 1));
         LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - lat, osg::Vec3(0, 1, 0));
@@ -123,7 +122,7 @@ bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
         
         SGVec3<double> cart;
         SGGeodesy::SGGeodToCart(SGGeod::fromRad(cld_pos.getLongitudeRad(), cld_pos.getLatitudeRad()), cart);
-        T.makeTranslate(cart.osg());
+        T.makeTranslate(toOsg(cart));
         
         LON.makeRotate(cld_pos.getLongitudeRad(), osg::Vec3(0, 0, 1));
         LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - cld_pos.getLatitudeRad(), osg::Vec3(0, 1, 0));
@@ -131,7 +130,8 @@ bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
         field_transform->setMatrix( LAT*LON*T );
     }
     
-    field_root->getStateSet()->setRenderBinDetails(asl, "RenderBin");
+    // Render the clouds in order from farthest away layer to nearest one.
+    field_root->getStateSet()->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
 
     return true;
 }
@@ -139,18 +139,21 @@ bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
 SGCloudField::SGCloudField() :
         field_root(new osg::Group),
         field_transform(new osg::MatrixTransform),
+        altitude_transform(new osg::PositionAttitudeTransform),
        deltax(0.0),
        deltay(0.0),
        last_course(0.0),
        last_coverage(0.0),
-        defined3D(false),
-        reposition_count(0)
+        coverage(0.0),
+        reposition_count(0),
+        defined3D(false)
 {
     cld_pos = SGGeoc();
     field_root->addChild(field_transform.get());
     field_root->setName("3D Cloud field root");
     osg::StateSet *rootSet = field_root->getOrCreateStateSet();
     rootSet->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
+    rootSet->setAttributeAndModes(getFog());
     
     osg::ref_ptr<osg::Group> quad_root = new osg::Group();
     
@@ -175,7 +178,9 @@ SGCloudField::SGCloudField() :
             quad[i][j]->addChild(field_group[x][y].get(), 0.0f, view_distance);
         }
     }
-
+    
+    field_transform->addChild(altitude_transform.get());
+            
     // We duplicate the defined field group in a 3x3 array. This way,
     // we can simply shift entire groups around.
     // TODO: "Bend" the edge groups so when shifted they line up.
@@ -187,7 +192,7 @@ SGCloudField::SGCloudField() :
             transform->addChild(quad_root.get());
             transform->setPosition(osg::Vec3(x*fieldSize, y * fieldSize, 0.0));
             
-            field_transform->addChild(transform.get());
+            altitude_transform->addChild(transform.get());
         }
     }
 }
@@ -200,10 +205,7 @@ void SGCloudField::clear(void) {
     for (int x = 0; x < QUADTREE_SIZE; x++) {
         for (int y = 0; y < QUADTREE_SIZE; y++) {
             int num_children = field_group[x][y]->getNumChildren();
-
-            for (int i = 0; i < num_children; i++) {
-                field_group[x][y]->removeChild(i);
-            }
+            field_group[x][y]->removeChildren(0, num_children);
         }
     }
     
@@ -228,7 +230,7 @@ static int densTable[][10] = {
 void SGCloudField::applyCoverage(void) {
 
         int row = (int) (coverage * 10.0);
-        if (row > 10) row = 9;
+        if (row > 9) row = 9;
         int col = 0;
 
         if (coverage != last_coverage) {
@@ -266,7 +268,7 @@ void SGCloudField::addCloud( SGVec3f& pos, SGNewCloud *cloud) {
         
         osg::ref_ptr<osg::PositionAttitudeTransform> transform = new osg::PositionAttitudeTransform;
 
-        transform->setPosition(pos.osg());
+        transform->setPosition(toOsg(pos));
         transform->addChild(geode.get());
         
         field_group[x][y]->addChild(transform.get(), true);
@@ -284,3 +286,17 @@ void SGCloudField::applyVisRange(void) {
     }
 }
 
+SGCloudField::CloudFog::CloudFog()
+{
+    fog = new osg::Fog;
+    fog->setMode(osg::Fog::EXP2);
+    fog->setDataVariance(osg::Object::DYNAMIC);
+}
+
+void SGCloudField::updateFog(double visibility, const osg::Vec4f& color)
+{
+    const double sqrt_m_log01 = sqrt(-log(0.01));
+    osg::Fog* fog = CloudFog::instance()->fog.get();
+    fog->setColor(color);
+    fog->setDensity(sqrt_m_log01 / visibility);
+}