#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(0),
+ layer_transform(0),
+ texture_path(tex_path),
+ layer_asl(0),
+ layer_thickness(0),
+ layer_transition(0),
+ layer_type(SG_CLOUD_CLEAR)
+{
+ rebuild();
}
-
// Destructor
SGCloudLayer::~SGCloudLayer( void ) {
}
+float
+SGCloudLayer::getSpan_m () const
+{
+ return layer_span;
+}
+
+void
+SGCloudLayer::setSpan_m (float span_m)
+{
+ layer_span = span_m;
+}
+
+float
+SGCloudLayer::getElevation_m () const
+{
+ return layer_asl;
+}
+
+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;
+}
+
+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)
+{
+ layer_type = type;
+ rebuild();
+}
+
// build the cloud object
-void SGCloudLayer::build( double s, double asl, double thickness,
- double transition, ssgSimpleState *state )
+void
+SGCloudLayer::rebuild()
{
- scale = 4000.0;
+ // Initialize states and sizes if necessary.
+ if (layer_states[0] == 0) {
+ SGPath cloud_path;
- layer_asl = asl;
- layer_thickness = thickness;
- layer_transition = transition;
+ cloud_path.set(texture_path.str());
+ cloud_path.append("overcast.rgb");
+ layer_states[SG_CLOUD_OVERCAST] = SGCloudMakeState(cloud_path.str());
- size = s;
- last_lon = last_lat = -999.0f;
+ 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;
+ }
+
+ delete layer_root;
- layer_state = state;
+ scale = 4000.0;
+
+ last_lon = last_lat = -999.0f;
cl = new ssgColourArray( 4 );
vl = new ssgVertexArray( 4 );
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] );
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_states[layer_type] != 0)
+ layer->setState( layer_states[layer_type] );
// force a repaint of the moon colors with arbitrary defaults
repaint( color );
// 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;
SG_USING_STD(string);
-#define SG_MAX_CLOUD_TYPES 4 // change this if we add/remove cloud
- // types en the enum below
-
-enum SGCloudType {
- SG_CLOUD_OVERCAST = 0,
- SG_CLOUD_MOSTLY_CLOUDY,
- SG_CLOUD_MOSTLY_SUNNY,
- SG_CLOUD_CIRRUS
-};
-
-
class SGCloudLayer {
-private:
+public:
- ssgRoot *layer_root;
- ssgTransform *layer_transform;
- ssgSimpleState *layer_state;
+ enum Type {
+ SG_CLOUD_OVERCAST = 0,
+ SG_CLOUD_MOSTLY_CLOUDY,
+ SG_CLOUD_MOSTLY_SUNNY,
+ SG_CLOUD_CIRRUS,
+ SG_CLOUD_CLEAR,
+ SG_MAX_CLOUD_TYPES
+ };
- ssgColourArray *cl;
- ssgVertexArray *vl;
- ssgTexCoordArray *tl;
+ // Constructors
+ SGCloudLayer( const string &tex_path );
- // height above sea level (meters)
- float layer_asl;
- float layer_thickness;
- float layer_transition;
- float size;
- float scale;
+ // Destructor
+ ~SGCloudLayer( void );
- // for handling texture coordinates to simulate cloud movement
- // from winds, and to simulate the clouds being tied to ground
- // position, not view position
- // double xoff, yoff;
- double last_lon, last_lat;
+ float getSpan_m () const;
+ void setSpan_m (float span_m);
-public:
+ float getElevation_m () const;
+ void setElevation_m (float elevation_m);
- // Constructor
- SGCloudLayer( void );
+ float getThickness_m () const;
+ void setThickness_m (float thickness_m);
- // Destructor
- ~SGCloudLayer( void );
+ float getTransition_m () const;
+ void setTransition_m (float transition_m);
+
+ Type getType () const;
+ void setType (Type type);
// build the cloud object
- void build( double size, double asl, double thickness,
- double transition, ssgSimpleState *state );
+ void rebuild();
// repaint the cloud colors based on current value of sun_angle,
// sky, and fog colors. This updates the color arrays for
// draw the cloud layer
void draw();
- inline float get_asl() const { return layer_asl; }
- inline float get_thickness() const { return layer_thickness; }
- inline float get_transition() const { return layer_transition; }
+private:
+
+ static ssgSimpleState *layer_states[SG_MAX_CLOUD_TYPES];
+ static int layer_sizes[SG_MAX_CLOUD_TYPES];
+
+ ssgRoot *layer_root;
+ ssgTransform *layer_transform;
+ ssgLeaf * layer;
+
+ ssgColourArray *cl;
+ ssgVertexArray *vl;
+ ssgTexCoordArray *tl;
+
+ // height above sea level (meters)
+ SGPath texture_path;
+ float layer_span;
+ float layer_asl;
+ float layer_thickness;
+ float layer_transition;
+ Type layer_type;
+ float scale;
+
+ // for handling texture coordinates to simulate cloud movement
+ // from winds, and to simulate the clouds being tied to ground
+ // position, not view position
+ // double xoff, yoff;
+ double last_lon, last_lat;
+
};
// Destructor
-SGSky::~SGSky( void ) {
+SGSky::~SGSky( void )
+{
+ for (int i = 0; i < cloud_layers.size(); i++)
+ delete cloud_layers[i];
}
pre_root->addKid( pre_selector );
post_root->addKid( post_selector );
-
- // add the cloud ssgStates to the material lib
- SGPath cloud_path;
-
- cloud_path.set( tex_path.str() );
- cloud_path.append( "overcast.rgb" );
- cloud_mats[SG_CLOUD_OVERCAST] = SGCloudMakeState( cloud_path.str() );
-
- cloud_path.set( tex_path.str() );
- cloud_path.append( "mostlycloudy.rgba" );
- cloud_mats[SG_CLOUD_MOSTLY_CLOUDY] = SGCloudMakeState( cloud_path.str() );
-
- cloud_path.set( tex_path.str() );
- cloud_path.append( "mostlysunny.rgba" );
- cloud_mats[SG_CLOUD_MOSTLY_SUNNY] = SGCloudMakeState( cloud_path.str() );
-
- cloud_path.set( tex_path.str() );
- cloud_path.append( "cirrus.rgba" );
- cloud_mats[SG_CLOUD_CIRRUS] = SGCloudMakeState( cloud_path.str() );
}
// check where we are relative to the cloud layers
for ( i = 0; i < (int)cloud_layers.size(); ++i ) {
- float asl = cloud_layers[i]->get_asl();
- float thickness = cloud_layers[i]->get_thickness();
+ float asl = cloud_layers[i]->getElevation_m();
+ float thickness = cloud_layers[i]->getThickness_m();
if ( alt < asl - slop ) {
// below cloud layer
// determine rendering order
int pos = 0;
while ( pos < (int)cloud_layers.size() &&
- alt > cloud_layers[pos]->get_asl())
+ alt > cloud_layers[pos]->getElevation_m())
{
++pos;
}
}
}
-
-void SGSky::add_cloud_layer( double asl, double thickness,
- double transition, double span,
- ssgSimpleState *state ) {
- SGCloudLayer *layer = new SGCloudLayer;
- layer->build( span, asl, thickness, transition, state );
-
- layer_list_iterator current = cloud_layers.begin();
- layer_list_iterator last = cloud_layers.end();
- while ( current != last && (*current)->get_asl() < asl ) {
- ++current;
- }
-
- if ( current != last ) {
- cloud_layers.insert( current, layer );
- } else {
- cloud_layers.push_back( layer );
- }
-
- // for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
- // cout << "layer " << i << " = " << cloud_layers[i]->get_asl() << endl;
- // }
- // cout << endl;
+void
+SGSky::add_cloud_layer( SGCloudLayer * layer )
+{
+ cloud_layers.push_back(layer);
}
-
-void SGSky::add_cloud_layer( double asl, double thickness,
- double transition, double span,
- const string &tex_path ) {
- ssgSimpleState *state = SGCloudMakeState( tex_path );
- add_cloud_layer( asl, thickness, transition, span, state );
+const SGCloudLayer *
+SGSky::get_cloud_layer (int i) const
+{
+ return cloud_layers[i];
}
-
-void SGSky::add_cloud_layer( double asl, double thickness,
- double transition, double span,
- SGCloudType type ) {
- if ( type > 0 && type < SG_MAX_CLOUD_TYPES ) {
- add_cloud_layer( asl, thickness, transition, span, cloud_mats[type] );
- }
+SGCloudLayer *
+SGSky::get_cloud_layer (int i)
+{
+ return cloud_layers[i];
}
+int
+SGSky::get_cloud_layer_count () const
+{
+ return cloud_layers.size();
+}
// modify the current visibility based on cloud layers, thickness,
// transition range, and simulated "puffs".
float effvis = visibility;
for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
- float asl = cloud_layers[i]->get_asl();
- float thickness = cloud_layers[i]->get_thickness();
- float transition = cloud_layers[i]->get_transition();
+ float asl = cloud_layers[i]->getElevation_m();
+ float thickness = cloud_layers[i]->getThickness_m();
+ float transition = cloud_layers[i]->getTransition_m();
double ratio = 1.0;
effective_visibility = effvis;
}
-
SGMoon *moon;
SGStars *planets;
SGStars *stars;
- ssgSimpleState *cloud_mats[SG_MAX_CLOUD_TYPES];
layer_list_type cloud_layers;
ssgRoot *pre_root, *post_root;
}
/**
- * Add a cloud layer (distances in meters).
- * @param asl cloud base height above sea level
- * @param thickness cloud layer thickness
- * @param transition thickness of transition layer from 100% out of
- * cloud to 100% in cloud. Used for scudded clouds effect.
- * @param span horizontal size of cloud object
- * @param type type of cloud (chosen from available cloud types)
+ * Add a cloud layer.
+ *
+ * Transfer pointer ownership to this object.
+ *
+ * @param layer The new cloud layer to add.
*/
- void add_cloud_layer( double asl, double thickness,
- double transition, double span,
- SGCloudType type );
+ void add_cloud_layer (SGCloudLayer * layer);
+
/**
- * Add a cloud layer (distances in meters).
- * @param asl cloud base height above sea level
- * @param thickness cloud layer thickness
- * @param transition thickness of transition layer from 100% out of
- * cloud to 100% in cloud. Used for scudded clouds effect.
- * @param span horizontal size of cloud object
- * @param tex_path file name of a cloud texture
+ * Get a cloud layer (const).
+ *
+ * Pointer ownership remains with this object.
+ *
+ * @param i The index of the cloud layer, zero-based.
+ * @return A const pointer to the cloud layer.
*/
- void add_cloud_layer( double asl, double thickness,
- double transition, double span,
- const string &tex_path );
+ const SGCloudLayer * get_cloud_layer (int i) const;
+
/**
- * Add a cloud layer (distances in meters).
- * @param asl cloud base height above sea level
- * @param thickness cloud layer thickness
- * @param transition thickness of transition layer from 100% out of
- * cloud to 100% in cloud. Used for scudded clouds effect.
- * @param span horizontal size of cloud object
- * @param state pointer to an existing ssgSimpleState
+ * Get a cloud layer (non-const).
+ *
+ * Pointer ownership remains with this object.
+ *
+ * @param i The index of the cloud layer, zero-based.
+ * @return A non-const pointer to the cloud layer.
*/
- void add_cloud_layer( double asl, double thickness,
- double transition, double span,
- ssgSimpleState *state );
+ SGCloudLayer * get_cloud_layer (int i);
- /** @return number of cloud layers */
- inline int get_num_layers() const { return cloud_layers.size(); }
/**
- * Get a cloud layer
- * @param i which cloud layer
- * @return cloud layer number i */
- inline SGCloudLayer *get_cloud_layer( int i ) const {
- return cloud_layers[i];
- }
+ * Return the number of cloud layers currently available.
+ *
+ * @return The cloud layer count.
+ */
+ int get_cloud_layer_count () const;
+
/** @return current effective visibility */
inline float get_visibility() const { return effective_visibility; }
#endif // _SG_SKY_HXX
-
-