]> git.mxchange.org Git - simgear.git/commitdiff
Stuart:
authorfredb <fredb>
Wed, 26 Nov 2008 07:28:10 +0000 (07:28 +0000)
committerfredb <fredb>
Wed, 26 Nov 2008 07:28:10 +0000 (07:28 +0000)
> Something has changed in the environment manager which means that clouds
> generateion is now inconsistent. I'm still tracking it down, as my recent
> changes shouldn't have affected this.

Well, the cause was a bug in my code, but it didn't expose itself until we moved
to multiple cameras. The attached patch fixes the problem.

I've also put in a new heuristic to improve the frame-rate. Clouds that are already sorted
are likely to still be sorted in subsequent frames. Therefore I've put in a back-off
mechanism for the bubble-sort pass. This should mean that if you stay completely
stationary, once the clouds become sorted they will eventually only perform a
bubble sort pass every 128 frames.

simgear/scene/sky/CloudShaderGeometry.cxx
simgear/scene/sky/CloudShaderGeometry.hxx
simgear/scene/sky/cloud.cxx
simgear/scene/sky/cloudfield.cxx
simgear/scene/sky/cloudfield.hxx

index 87905434ec31489760dc55211330f2a4e60f10c3..a556afb0d1ac70cd7636e07244709c3a7e479099 100755 (executable)
@@ -37,27 +37,56 @@ void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
     if (!_cloudsprites.size()) return;
     
     osg::State& state = *renderInfo.getState();
-    osg::Matrix vm = state.getModelViewMatrix();
     
-    //TODO: It isn't clear whether this is worth the perf hit ATM.
+    // If the cloud is already sorted, then it is likely to still be sorted.
+    // Therefore we can avoid re-sorting it for a period. If it is still
+    // sorted after that period, then we can wait for a longer period before
+    // checking again. In this way, only clouds that are changing regularly
+    // are sorted.
     
-    // Transform the viewing direction, represented by the eye space vector (0,0,-1, 0), into model-space
-    // (here we simply take the opposite direction and reverse the ordering when sorting)
-    osg::Vec3f view_dir(vm(0, 2), vm(1, 2), vm(2, 2));      // Caveat: OpenSceneGraph matrices are transposed!
-
-    float p = view_dir*_cloudsprites[0]->position.osg();
-    // Do a single iteration of a bubble sort, sorting
-    // back to front.
-    for(int i = 0; i < _cloudsprites.size() - 1; i++)
+    skip_info->skip_count = (skip_info->skip_count + 1) % skip_info->skip_limit;
+    
+    if (skip_info->skip_count == 0)
     {
-        float q = view_dir*_cloudsprites[i+1]->position.osg();
-        if (p > q) {  
-            CloudSprite c = *_cloudsprites[i];
-            *_cloudsprites[i] = *_cloudsprites[i+1];
-            *_cloudsprites[i+1] = c;
+        osg::Matrix vm = state.getModelViewMatrix();
+        bool sorted = true;
+        
+        // Transform the viewing direction, represented by the eye space vector (0,0,-1, 0), into model-space
+        // (here we simply take the opposite direction and reverse the ordering when sorting)
+        osg::Vec3f view_dir(vm(0, 2), vm(1, 2), vm(2, 2));      // Caveat: OpenSceneGraph matrices are transposed!
+    
+        float p = view_dir*_cloudsprites[0]->position.osg();
+        // Do a single iteration of a bubble sort, sorting
+        // back to front.
+        for(int i = 0; i < _cloudsprites.size() - 1; i++)
+        {
+            float q = view_dir*_cloudsprites[i+1]->position.osg();
+            if (p > q) {  
+                CloudSprite c = *_cloudsprites[i];
+                *_cloudsprites[i] = *_cloudsprites[i+1];
+                *_cloudsprites[i+1] = c;
+                
+                sorted = false;
+            }
+            else
+                p = q;
+        }
+        
+        if (sorted)
+        {
+            // This cloud is sorted, so no need to re-sort.
+            // Maximum of every 128 frames (2 - 4 seconds)
+            skip_info->skip_limit = skip_info->skip_limit * 2;
+            if (skip_info->skip_limit > 128) 
+            {
+                skip_info->skip_limit = 128;
+            }
         }
         else
-            p = q;
+        {
+            // This cloud is unsorted, so we need to sort next frame
+            skip_info->skip_limit = 1;
+        }
     }
 
     const Extensions* extensions = getExtensions(state.getContextID(),true);
@@ -74,7 +103,7 @@ void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
         _geometry->draw(renderInfo);
     }
 }
-
+    
 BoundingBox CloudShaderGeometry::computeBound() const
 {
     BoundingBox geom_box = _geometry->getBound();
index 50225f6537dfcb30bcc3983dc72aeb858bc835c9..2401e9626f4905cbaedfae2f012ccda233bfe2c4 100755 (executable)
@@ -52,12 +52,14 @@ class CloudShaderGeometry : public osg::Drawable
         CloudShaderGeometry()
         { 
             setUseDisplayList(false); 
+            skip_info = new SkipInfo();
         }
 
         CloudShaderGeometry(int vx, int vy) :
             varieties_x(vx), varieties_y(vy)
         { 
             setUseDisplayList(false); 
+            skip_info = new SkipInfo();
         }
         
         /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
@@ -66,6 +68,14 @@ class CloudShaderGeometry : public osg::Drawable
 
         META_Object(flightgear, CloudShaderGeometry);
         
+        struct SkipInfo {
+            SkipInfo() : skip_count(0), skip_limit(1) {}
+            int skip_count;
+            int skip_limit;
+        };
+        
+        SkipInfo* skip_info;
+        
         struct CloudSprite {
             CloudSprite(SGVec3f& p, int tx, int ty, float w, float h, float s, float ch) :
                     position(p), texture_index_x(tx), texture_index_y(ty), width(w), height(h), shade(s), cloud_height(ch)
@@ -128,8 +138,13 @@ class CloudShaderGeometry : public osg::Drawable
         
     protected:
     
-        virtual ~CloudShaderGeometry() {}
-        
+        virtual ~CloudShaderGeometry() {
+            delete skip_info;
+            for (int i = 0; i < _cloudsprites.size(); i++)
+            {
+                delete _cloudsprites[i];
+            }
+        }
 };
 
 }
index 0ec7139b01615acf9bef1816277d4f1907d2fa85..4a9bf2e12b6343f1a064ea7a14975d9269846ee4 100644 (file)
@@ -731,7 +731,7 @@ void SGCloudLayer::set_enable3dClouds(bool enable) {
     } else {
         cloud_root->setChildValue(layer3D->getNode(), false);
         cloud_root->setChildValue(layer_root.get(),   true);
-    }        
+    }
 }
 
 void SGCloudLayer::applyDensity() {
index f901b0f4d5fe949628488e17e3111ca4cf769d86..7fd7ce98f91595b1f0e77f50609a7714895bf762 100644 (file)
@@ -64,7 +64,6 @@ using std::vector;
 float SGCloudField::fieldSize = 50000.0f;
 float SGCloudField::density = 100.0f;
 double SGCloudField::timer_dt = 0.0;
-int reposition_count = 0;
 sgVec3 SGCloudField::view_vec, SGCloudField::view_X, SGCloudField::view_Y;
 
 void SGCloudField::set_density(float density) {
@@ -99,7 +98,6 @@ bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
         cld_pos = SGGeoc::fromGeod(SGGeod::fromRad(lon, lat));
     } else if (dist > fieldSize) {
         // Distance requires repositioning of cloud field.
-        
         // We can easily work out the direction to reposition
         // from the course between the cloud position and the
         // camera position.
@@ -141,10 +139,12 @@ SGCloudField::SGCloudField() :
        deltay(0.0),
        last_course(0.0),
        last_density(0.0),
-        defined3D(false)               
+        defined3D(false),
+        reposition_count(0)
 {
     cld_pos = SGGeoc();
-    field_root->addChild(field_transform.get());         
+    field_root->addChild(field_transform.get());
+    field_root->setName("3D Cloud field root");
     
     osg::ref_ptr<osg::Group> quad_root = new osg::Group();
     osg::ref_ptr<osg::LOD> quad[BRANCH_SIZE][BRANCH_SIZE];
@@ -263,5 +263,5 @@ void SGCloudField::addCloud( SGVec3f& pos, SGNewCloud *cloud) {
         transform->setPosition(pos.osg());
         transform->addChild(geode.get());
         
-        field_group[x][y]->addChild(transform.get());
+        field_group[x][y]->addChild(transform.get(), true);
 }
index 40333d6d81d1abce007ee85d3956279e0306a3ae..50207aac455a127d0c75ff3aff001ddc89834c34 100644 (file)
@@ -75,7 +75,7 @@ private:
         sgSphere field_sphere;
        float   last_density;
         SGGeoc cld_pos;
-
+        int reposition_count;
 public:
 
        SGCloudField();