]> git.mxchange.org Git - simgear.git/blobdiff - simgear/sky/cloud.cxx
Be more conservative and reuse SSG objects.
[simgear.git] / simgear / sky / cloud.cxx
index 78bde43cad524ff33a5940be86013e514a9a0fc8..4f9b5a15d05a92802fb1b25c9b2eb33e5b16e0a1 100644 (file)
 // $Id$
 
 
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
 #include <simgear/compiler.h>
 
 #include <stdio.h>
 #include <simgear/math/point3d.hxx>
 #include <simgear/math/polar3d.hxx>
 #include <simgear/math/sg_random.h>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/misc/sg_path.hxx>
 
 #include "cloud.hxx"
 
+ssgSimpleState *
+SGCloudLayer::layer_states[SGCloudLayer::SG_MAX_CLOUD_TYPES];
+
 
 // Constructor
-SGCloudLayer::SGCloudLayer( void ) {
+SGCloudLayer::SGCloudLayer( const string &tex_path )
+  : layer_root(new ssgRoot),
+    layer_transform(new ssgTransform),
+    layer(0),
+    texture_path(tex_path),
+    layer_asl(0),
+    layer_thickness(0),
+    layer_transition(0),
+    layer_type(SG_CLOUD_CLEAR)
+{
+    layer_root->addKid(layer_transform);
+    rebuild();
 }
 
-
 // Destructor
-SGCloudLayer::~SGCloudLayer( void ) {
+SGCloudLayer::~SGCloudLayer()
+{
+    delete layer_root;         // deletes layer_transform and layer as well
 }
 
+float
+SGCloudLayer::getSpan_m () const
+{
+    return layer_span;
+}
 
-// build the moon object
-void SGCloudLayer::build( double s, double asl, double thickness,
-                         double transition, ssgSimpleState *state )
+void
+SGCloudLayer::setSpan_m (float span_m)
 {
-    scale = 4000.0;
+    if (span_m != layer_span) {
+       layer_span = span_m;
+       rebuild();
+    }
+}
 
-    layer_asl = asl;
-    layer_thickness = thickness;
-    layer_transition = transition;
+float
+SGCloudLayer::getElevation_m () const
+{
+    return layer_asl;
+}
 
-    size = s;
-    last_lon = last_lat = -999.0f;
+void
+SGCloudLayer::setElevation_m (float elevation_m)
+{
+    layer_asl = elevation_m;
+}
+
+float
+SGCloudLayer::getThickness_m () const
+{
+    return layer_thickness;
+}
+
+void
+SGCloudLayer::setThickness_m (float thickness_m)
+{
+    layer_thickness = thickness_m;
+}
 
-    layer_state = state;
+float
+SGCloudLayer::getTransition_m () const
+{
+    return layer_transition;
+}
+
+void
+SGCloudLayer::setTransition_m (float transition_m)
+{
+    layer_transition = transition_m;
+}
+
+SGCloudLayer::Type
+SGCloudLayer::getType () const
+{
+    return layer_type;
+}
+
+void
+SGCloudLayer::setType (Type type)
+{
+    if (type != layer_type) {
+       layer_type = type;
+       rebuild();
+    }
+}
+
+
+// build the cloud object
+void
+SGCloudLayer::rebuild()
+{
+                               // Initialize states and sizes if necessary.
+    if (layer_states[0] == 0) {
+      SGPath cloud_path;
+
+      cloud_path.set(texture_path.str());
+      cloud_path.append("overcast.rgb");
+      layer_states[SG_CLOUD_OVERCAST] = SGCloudMakeState(cloud_path.str());
+
+      cloud_path.set(texture_path.str());
+      cloud_path.append("mostlycloudy.rgba");
+      layer_states[SG_CLOUD_MOSTLY_CLOUDY] =
+       SGCloudMakeState(cloud_path.str());
+
+      cloud_path.set(texture_path.str());
+      cloud_path.append("mostlysunny.rgba");
+      layer_states[SG_CLOUD_MOSTLY_SUNNY] = SGCloudMakeState(cloud_path.str());
+
+      cloud_path.set(texture_path.str());
+      cloud_path.append("cirrus.rgba");
+      layer_states[SG_CLOUD_CIRRUS] = SGCloudMakeState(cloud_path.str());
+
+      layer_states[SG_CLOUD_CLEAR] = 0;
+    }
+
+    scale = 4000.0;
+
+    last_lon = last_lat = -999.0f;
 
     cl = new ssgColourArray( 4 );
     vl = new ssgVertexArray( 4 );
@@ -70,7 +166,7 @@ void SGCloudLayer::build( double s, double asl, double thickness,
     sgVec2 tc;
     sgSetVec4( color, 1.0f, 1.0f, 1.0f, 1.0f );
 
-    sgSetVec3( vertex, -size, -size, 0.0f );
+    sgSetVec3( vertex, -layer_span, -layer_span, 0.0f );
     sgVec2 base;
     sgSetVec2( base, sg_random(), sg_random() );
     sgSetVec2( tc, base[0], base[1] );
@@ -78,40 +174,35 @@ void SGCloudLayer::build( double s, double asl, double thickness,
     vl->add( vertex );
     tl->add( tc );
 
-    sgSetVec3( vertex, size, -size, 0.0f );
-    sgSetVec2( tc, base[0] + size / scale, base[1] );
+    sgSetVec3( vertex, layer_span, -layer_span, 0.0f );
+    sgSetVec2( tc, base[0] + layer_span / scale, base[1] );
     cl->add( color );
     vl->add( vertex );
     tl->add( tc );
 
-    sgSetVec3( vertex, -size, size, 0.0f );
-    sgSetVec2( tc, base[0], base[1] + size / scale );
+    sgSetVec3( vertex, -layer_span, layer_span, 0.0f );
+    sgSetVec2( tc, base[0], base[1] + layer_span / scale );
     cl->add( color );
     vl->add( vertex );
     tl->add( tc );
 
-    sgSetVec3( vertex, size, size, 0.0f );
-    sgSetVec2( tc, base[0] + size / scale, base[1] + size / scale );
+    sgSetVec3( vertex, layer_span, layer_span, 0.0f );
+    sgSetVec2( tc, base[0] + layer_span / scale, base[1] + layer_span / scale );
     cl->add( color );
     vl->add( vertex );
     tl->add( tc );
 
-    ssgLeaf *layer = 
-       new ssgVtxTable ( GL_TRIANGLE_STRIP, vl, NULL, tl, cl );
-    layer->setState( layer_state );
+    if (layer != 0)
+      layer_transform->removeKid(layer); // automatic delete
+    layer = new ssgVtxTable ( GL_TRIANGLE_STRIP, vl, NULL, tl, cl );
+    if (layer_states[layer_type] != 0)
+      layer->setState( layer_states[layer_type] );
 
     // force a repaint of the moon colors with arbitrary defaults
     repaint( color );
 
-    // build the ssg scene graph sub tree for the sky and connected
-    // into the provide scene graph branch
-    layer_transform = new ssgTransform;
-
     // moon_transform->addKid( halo );
     layer_transform->addKid( layer );
-
-    layer_root = new ssgRoot;
-    layer_root->addKid( layer_transform );
 }
 
 
@@ -208,23 +299,42 @@ bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat,
        base = tl->get( 0 );
 
        base[0] += xoff;
-       while ( base[0] > 1.0 ) { base[0] -= 1.0; }
-       while ( base[0] < 0.0 ) { base[0] += 1.0; }
+
+       // the while loops can lead to *long* pauses if base[0] comes
+       // with a bogus value.
+        // while ( base[0] > 1.0 ) { base[0] -= 1.0; }
+       // while ( base[0] < 0.0 ) { base[0] += 1.0; }
+        if ( base[0] > -10.0 && base[0] < 10.0 ) {
+            base[0] -= (int)base[0];
+        } else {
+            base[0] = 0.0;
+           SG_LOG(SG_ASTRO, SG_ALERT,
+                  "Error: base = " << base[0] << "," << base[1]);
+        }
 
        base[1] += yoff;
-       while ( base[1] > 1.0 ) { base[1] -= 1.0; }
-       while ( base[1] < 0.0 ) { base[1] += 1.0; }
+       // the while loops can lead to *long* pauses if base[0] comes
+       // with a bogus value.
+       // while ( base[1] > 1.0 ) { base[1] -= 1.0; }
+       // while ( base[1] < 0.0 ) { base[1] += 1.0; }
+        if ( base[1] > -10.0 && base[1] < 10.0 ) {
+            base[1] -= (int)base[1];
+        } else {
+            base[1] = 0.0;
+           SG_LOG(SG_ASTRO, SG_ALERT,
+                  "Error: base = " << base[0] << "," << base[1]);
+        }
 
        // cout << "base = " << base[0] << "," << base[1] << endl;
 
        tc = tl->get( 1 );
-       sgSetVec2( tc, base[0] + size / scale, base[1] );
+       sgSetVec2( tc, base[0] + layer_span / scale, base[1] );
  
        tc = tl->get( 2 );
-       sgSetVec2( tc, base[0], base[1] + size / scale );
+       sgSetVec2( tc, base[0], base[1] + layer_span / scale );
  
        tc = tl->get( 3 );
-       sgSetVec2( tc, base[0] + size / scale, base[1] + size / scale );
+       sgSetVec2( tc, base[0] + layer_span / scale, base[1] + layer_span / scale );
  
        last_lon = lon;
        last_lat = lat;
@@ -235,7 +345,8 @@ bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat,
 
 
 void SGCloudLayer::draw() {
-    ssgCullAndDraw( layer_root );
+    if (layer_type != SG_CLOUD_CLEAR)
+      ssgCullAndDraw( layer_root );
 }