]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/sky/cloud.cxx
Don't reset the random texture base when rebuilding a cloud layer
[simgear.git] / simgear / scene / sky / cloud.cxx
index b97d39b08b267d699939e6f09a59a9d9d786421f..5ff1b0891ebdbbe671e60a6ee6f31e766783deba 100644 (file)
@@ -39,6 +39,7 @@
 #include <osg/TexEnv>
 #include <osg/Texture2D>
 #include <osg/TextureCubeMap>
+#include <osg/TexMat>
 
 #include <simgear/math/sg_random.h>
 #include <simgear/debug/logstream.hxx>
@@ -75,7 +76,8 @@ bool SGCloudLayer::enable_bump_mapping = false;
 
 // make an StateSet for a cloud layer given the named texture
 static osg::StateSet*
-SGMakeState(const SGPath &path, const char* colorTexture, const char* normalTexture)
+SGMakeState(const SGPath &path, const char* colorTexture,
+            const char* normalTexture)
 {
     osg::StateSet *stateSet = new osg::StateSet;
 
@@ -157,6 +159,11 @@ SGCloudLayer::SGCloudLayer( const string &tex_path ) :
 {
   layer_root->addChild(group_bottom.get());
   layer_root->addChild(group_top.get());
+  // Force the cloud layers into recursive bins of bin 4.
+  osg::StateSet *rootSet = layer_root->getOrCreateStateSet();
+  rootSet->setRenderBinDetails(4, "RenderBin");
+  rootSet->setTextureAttribute(0, new osg::TexMat());
+  base = osg::Vec2(sg_random(), sg_random());
 
   group_top->addChild(layer_transform.get());
   group_bottom->addChild(layer_transform.get());
@@ -244,6 +251,17 @@ SGCloudLayer::setCoverage (Coverage coverage)
     }
 }
 
+void
+SGCloudLayer::setTextureOffset(const osg::Vec2& offset)
+{
+    osg::StateAttribute* attr = layer_root->getStateSet()
+        ->getTextureAttribute(0, osg::StateAttribute::TEXMAT);
+    osg::TexMat* texMat = dynamic_cast<osg::TexMat*>(attr);
+    if (!texMat)
+        return;
+    texMat->setMatrix(osg::Matrix::translate(offset[0], offset[1], 0.0));
+}
+
 // build the cloud object
 void
 SGCloudLayer::rebuild()
@@ -418,9 +436,8 @@ SGCloudLayer::rebuild()
 
     scale = 4000.0;
     last_lon = last_lat = -999.0f;
-    
-    base = osg::Vec2(sg_random(), sg_random());
-    
+
+    setTextureOffset(base);
     // build the cloud layer
     const float layer_scale = layer_span / scale;
     const float mpi = SG_PI/4;
@@ -447,7 +464,7 @@ SGCloudLayer::rebuild()
       
       osg::Vec3 vertex(layer_span*(i-2)/2, -layer_span,
                        alt_diff * (sin(i*mpi) - 2));
-      osg::Vec2 tc(base[0] + layer_scale * i/4, base[1]);
+      osg::Vec2 tc(layer_scale * i/4, 0.0f);
       osg::Vec4 color(1.0f, 1.0f, 1.0f, (i == 0) ? 0.0f : 0.15f);
       
       cl[i]->push_back(color);
@@ -457,8 +474,7 @@ SGCloudLayer::rebuild()
       for (int j = 0; j < 4; j++) {
         vertex = osg::Vec3(layer_span*(i-1)/2, layer_span*(j-2)/2,
                            alt_diff * (sin((i+1)*mpi) + sin(j*mpi) - 2));
-        tc = osg::Vec2(base[0] + layer_scale * (i+1)/4,
-                       base[1] + layer_scale * j/4);
+        tc = osg::Vec2(layer_scale * (i+1)/4, layer_scale * j/4);
         color = osg::Vec4(1.0f, 1.0f, 1.0f,
                           ( (j == 0) || (i == 3)) ?  
                           ( (j == 0) && (i == 3)) ? 0.0f : 0.15f : 1.0f );
@@ -469,8 +485,7 @@ SGCloudLayer::rebuild()
         
         vertex = osg::Vec3(layer_span*(i-2)/2, layer_span*(j-1)/2,
                            alt_diff * (sin(i*mpi) + sin((j+1)*mpi) - 2) );
-        tc = osg::Vec2(base[0] + layer_scale * i/4,
-                       base[1] + layer_scale * (j+1)/4 );
+        tc = osg::Vec2(layer_scale * i/4, layer_scale * (j+1)/4 );
         color = osg::Vec4(1.0f, 1.0f, 1.0f,
                           ((j == 3) || (i == 0)) ?
                           ((j == 3) && (i == 0)) ? 0.0f : 0.15f : 1.0f );
@@ -482,8 +497,7 @@ SGCloudLayer::rebuild()
       vertex = osg::Vec3(layer_span*(i-1)/2, layer_span, 
                          alt_diff * (sin((i+1)*mpi) - 2));
       
-      tc = osg::Vec2(base[0] + layer_scale * (i+1)/4,
-                     base[1] + layer_scale);
+      tc = osg::Vec2(layer_scale * (i+1)/4, layer_scale);
       
       color = osg::Vec4(1.0f, 1.0f, 1.0f, (i == 3) ? 0.0f : 0.15f );
       
@@ -513,13 +527,12 @@ SGCloudLayer::rebuild()
     if ( layer_states[layer_coverage].valid() ) {
       osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_ALL
                          & ~osg::CopyOp::DEEP_COPY_TEXTURES);
-      
+      // render bin will be set in reposition
       osg::StateSet* stateSet = static_cast<osg::StateSet*>(layer_states2[layer_coverage]->clone(copyOp));
-      // OSGFIXME
-      stateSet->setRenderBinDetails(4, "RenderBin");
+      stateSet->setDataVariance(osg::Object::DYNAMIC);
       group_top->setStateSet(stateSet);
       stateSet = static_cast<osg::StateSet*>(layer_states2[layer_coverage]->clone(copyOp));
-      stateSet->setRenderBinDetails(4, "RenderBin");
+      stateSet->setDataVariance(osg::Object::DYNAMIC);
       group_bottom->setStateSet(stateSet);
     }
 }
@@ -847,12 +860,24 @@ bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
     LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - lat, osg::Vec3(0, 1, 0));
 
     layer_transform->setMatrix( LAT*LON*T );
-
+    // The layers need to be drawn in order because they are
+    // translucent, but OSG transparency sorting doesn't work because
+    // the cloud polys are huge. However, the ordering is simple: the
+    // bottom polys should be drawn from high altitude to low, and the
+    // top polygons from low to high. The altitude can be used
+    // directly to order the polygons!
+    layer_root->getChild(0)->getStateSet()->setRenderBinDetails(-(int)layer_asl,
+                                                                "RenderBin");
+    layer_root->getChild(1)->getStateSet()->setRenderBinDetails((int)layer_asl,
+                                                                "RenderBin");
     if ( alt <= layer_asl ) {
       layer_root->setSingleChildOn(0);
-    } else {
+    } else if ( alt >= layer_asl + layer_thickness ) {
       layer_root->setSingleChildOn(1);
+    } else {
+      layer_root->setAllChildrenOff();
     }
+        
 
     // now calculate update texture coordinates
     if ( last_lon < -900 ) {
@@ -932,15 +957,7 @@ bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
 
         // cout << "base = " << base[0] << "," << base[1] << endl;
 
-        for (int i = 0; i < 4; i++) {
-          (*tl[i])[0] = base + osg::Vec2(i, 0)*layer_scale/4;
-          for (int j = 0; j < 4; j++) {
-            (*tl[i])[j*2+1] = base + osg::Vec2(i+1, j)*layer_scale/4;
-            (*tl[i])[j*2+2] = base + osg::Vec2(i, j+1)*layer_scale/4;
-          }
-          (*tl[i])[9] = base + osg::Vec2(i+1, 4)*layer_scale/4;
-        }
-
+        setTextureOffset(base);
         last_lon = lon;
         last_lat = lat;
     }