station_elevation_ft(0.0),
_controller( controller ),
snd_lightning(NULL),
- rebuild_required(true),
- last_scenario( "none" ),
+ clouds_3d_enabled(false),
+ last_scenario( "unset" ),
last_env_config( new SGPropertyNode() ),
last_env_clouds( new SGPropertyNode() )
{
update_event = 0;
- fgSetString("/environment/weather-scenario", last_scenario.c_str());
}
FGClouds::~FGClouds() {
}
}
void FGClouds::set_update_event(int count) {
update_event = count;
- build();
+ buildCloudLayers();
}
void FGClouds::init(void) {
soundMgr->add( snd_lightning, "thunder" );
sgEnviro.set_soundMgr( soundMgr );
}
-
- rebuild_required = true;
}
void FGClouds::buildCloud(SGPropertyNode *cloud_def_root, SGPropertyNode *box_def_root, const string& name, sgVec3 pos, SGCloudField *layer) {
string texture = cld_def->getStringValue("texture", "cl_cumulus.rgb");
SGNewCloud *cld =
- new SGNewCloud(texture_root,
+ new SGNewCloud(type,
+ texture_root,
texture,
min_width,
max_width,
int CloudVarietyCount = 0;
double totalCount = 0.0;
- if (! clouds_3d_enabled) return;
-
SGPropertyNode *cloud_def_root = fgGetNode("/environment/cloudlayers/clouds", false);
SGPropertyNode *box_def_root = fgGetNode("/environment/cloudlayers/boxes", false);
SGPropertyNode *layer_def_root = fgGetNode("/environment/cloudlayers/layers", false);
SGCloudField *layer = thesky->get_cloud_layer(iLayer)->get_layer3D();
-
layer->clear();
- // when we don't generate clouds the layer is rendered in 2D
- if( coverage == 0.0 )
- return;
- if( layer_def_root == NULL || cloud_def_root == NULL || box_def_root == NULL)
+
+ // If we don't have the required properties, then render the cloud in 2D
+ if ((! clouds_3d_enabled) || coverage == 0.0 ||
+ layer_def_root == NULL || cloud_def_root == NULL || box_def_root == NULL)
+ {
+ thesky->get_cloud_layer(iLayer)->set_enable3dClouds(false);
return;
-
+ }
+
+ // If we can't find a definition for this cloud type, then render the cloud in 2D
SGPropertyNode *layer_def=NULL;
-
layer_def = layer_def_root->getChild(name.c_str());
if( !layer_def ) {
if( name[2] == '-' ) {
layer_def = layer_def_root->getChild(base_name.c_str());
}
if( !layer_def )
- return;
+ {
+ thesky->get_cloud_layer(iLayer)->set_enable3dClouds(false);
+ return;
+ }
}
+ // At this point, we know we've got some 3D clouds to generate.
+ thesky->get_cloud_layer(iLayer)->set_enable3dClouds(true);
+
double grid_x_size = layer_def->getDoubleValue("grid-x-size", 1000.0);
double grid_y_size = layer_def->getDoubleValue("grid-y-size", 1000.0);
double grid_x_rand = layer_def->getDoubleValue("grid-x-rand", grid_x_size);
}
}
totalCount = 1.0 / totalCount;
- double currCoverage = 0.0;
-
+
for(double px = 0.0; px < SGCloudField::fieldSize; px += grid_x_size) {
for(double py = 0.0; py < SGCloudField::fieldSize; py += grid_y_size) {
double x = px + grid_x_rand * (sg_random() - 0.5) - (SGCloudField::fieldSize / 2.0);
double y = py + grid_y_rand * (sg_random() - 0.5) - (SGCloudField::fieldSize / 2.0);
- double z = alt + grid_z_rand * (sg_random() - 0.5);
- double choice = sg_random();
- currCoverage += coverage;
- if( currCoverage < 1.0 )
- continue;
- currCoverage -= 1.0;
-
- for(int i = 0; i < CloudVarietyCount ; i ++) {
- choice -= tCloudVariety[i].count * totalCount;
- if( choice <= 0.0 ) {
- sgVec3 pos={x,z,y};
-
- buildCloud(cloud_def_root, box_def_root, tCloudVariety[i].name, pos, layer);
- break;
- }
- }
+ double z = grid_z_rand * (sg_random() - 0.5);
+
+ if (sg_random() < coverage)
+ {
+ double choice = sg_random();
+
+ for(int i = 0; i < CloudVarietyCount ; i ++) {
+ choice -= tCloudVariety[i].count * totalCount;
+ if( choice <= 0.0 ) {
+ sgVec3 pos={x,z,y};
+
+ buildCloud(cloud_def_root,
+ box_def_root,
+ tCloudVariety[i].name,
+ pos,
+ layer);
+ break;
+ }
+ }
+ }
}
}
- // Now we've built any clouds, enable them
+ // Now we've built any clouds, enable them and set the density (coverage)
+ //layer->setCoverage(coverage);
+ //layer->applyCoverage();
thesky->get_cloud_layer(iLayer)->set_enable3dClouds(clouds_3d_enabled);
}
-// TODO:call this after real metar updates
-void FGClouds::buildMETAR(void) {
+void FGClouds::buildCloudLayers(void) {
SGPropertyNode *metar_root = fgGetNode("/environment", true);
double wind_speed_kt = metar_root->getDoubleValue("wind-speed-kt");
double alt_ft = cloud_root->getDoubleValue("elevation-ft");
double alt_m = alt_ft * SG_FEET_TO_METER;
- string coverage = cloud_root->getStringValue("coverage");
+ string coverage = cloud_root->getStringValue("coverage");
+
+
double coverage_norm = 0.0;
if( coverage == "few" )
coverage_norm = 2.0/8.0; // <1-2
} else if( alt_ft > 6500 ) {
// layer_type = "as|ac|ns";
layer_type = "ac";
- if( pressure_mb < 1005.0 && coverage_norm >= 5.5 )
+ if( pressure_mb < 1005.0 && coverage_norm >= 0.5 )
layer_type = "ns";
} else {
// layer_type = "st|cu|cb|sc";
- // +/- 20% from stratus probable base
- if( stratus_base * 0.80 < alt_m && stratus_base * 1.40 > alt_m )
- layer_type = "st";
- // +/- 20% from cumulus probable base
- else if( cumulus_base * 0.80 < alt_m && cumulus_base * 1.20 > alt_m )
- layer_type = "cu";
- else {
+ if( cumulus_base * 0.80 < alt_m && cumulus_base * 1.20 > alt_m ) {
+ // +/- 20% from cumulus probable base
+ layer_type = "cu";
+ } else if( stratus_base * 0.80 < alt_m && stratus_base * 1.40 > alt_m ) {
+ // +/- 20% from stratus probable base
+ layer_type = "st";
+ } else {
// above formulae is far from perfect
- if ( alt_ft < 2000 )
+ if ( alt_ft < 2000 )
layer_type = "st";
else if( alt_ft < 4500 )
layer_type = "cu";
layer_type = "sc";
}
}
-
+
buildLayer(iLayer, layer_type, alt_m, coverage_norm);
}
}
FGClouds::update_metar_properties( const FGMetar *m )
{
int i;
+ int j;
double d;
char s[128];
vector<SGMetarCloud> cv = m->getClouds();
vector<SGMetarCloud>::const_iterator cloud;
- const char *cl = "/environment/clouds/layer[%i]";
- for (i = 0, cloud = cv.begin(); cloud != cv.end(); cloud++, i++) {
- const char *coverage_string[5] =
- { "clear", "few", "scattered", "broken", "overcast" };
- const double thickness[5] = { 0, 65, 600,750, 1000};
- int q;
-
- snprintf(s, 128, cl, i);
- strncat(s, "/coverage", 128);
- q = cloud->getCoverage();
- fgSetString(s, coverage_string[q] );
-
- snprintf(s, 128, cl, i);
- strncat(s, "/elevation-ft", 128);
- fgSetDouble(s, cloud->getAltitude_ft() + station_elevation_ft);
-
- snprintf(s, 128, cl, i);
- strncat(s, "/thickness-ft", 128);
- fgSetDouble(s, thickness[q]);
-
- snprintf(s, 128, cl, i);
- strncat(s, "/span-m", 128);
- fgSetDouble(s, 40000.0);
- }
-
- for (; i < FGEnvironmentMgr::MAX_CLOUD_LAYERS; i++) {
- snprintf(s, 128, cl, i);
- strncat(s, "/coverage", 128);
- fgSetString(s, "clear");
+ // Load into both the METAR and environment properties to stop interpolation
+ const char *cl[] = {"/environment/metar/clouds/layer[%i]",
+ "/environment/clouds/layer[%i]"};
- snprintf(s, 128, cl, i);
- strncat(s, "/elevation-ft", 128);
- fgSetDouble(s, -9999);
-
- snprintf(s, 128, cl, i);
- strncat(s, "/thickness-ft", 128);
- fgSetDouble(s, 0);
-
- snprintf(s, 128, cl, i);
- strncat(s, "/span-m", 128);
- fgSetDouble(s, 40000.0);
+ for (j = 0; j < 2; j++)
+ {
+ for (i = 0, cloud = cv.begin(); cloud != cv.end(); cloud++, i++) {
+ const char *coverage_string[5] =
+ { "clear", "few", "scattered", "broken", "overcast" };
+ const double thickness[5] = { 0, 65, 600,750, 1000};
+ int q;
+
+ snprintf(s, 128, cl[j], i);
+ strncat(s, "/coverage", 128);
+ q = cloud->getCoverage();
+ fgSetString(s, coverage_string[q] );
+
+ snprintf(s, 128, cl[j], i);
+ strncat(s, "/elevation-ft", 128);
+ fgSetDouble(s, cloud->getAltitude_ft() + station_elevation_ft);
+
+ snprintf(s, 128, cl[j], i);
+ strncat(s, "/thickness-ft", 128);
+ fgSetDouble(s, thickness[q]);
+
+ snprintf(s, 128, cl[j], i);
+ strncat(s, "/span-m", 128);
+ fgSetDouble(s, 40000.0);
+ }
+
+ for (; i < FGEnvironmentMgr::MAX_CLOUD_LAYERS; i++) {
+
+
+ snprintf(s, 128, cl[j], i);
+ strncat(s, "/coverage", 128);
+ fgSetString(s, "clear");
+
+ snprintf(s, 128, cl[j], i);
+ strncat(s, "/elevation-ft", 128);
+ fgSetDouble(s, -9999);
+
+ snprintf(s, 128, cl[j], i);
+ strncat(s, "/thickness-ft", 128);
+ fgSetDouble(s, 0);
+
+ snprintf(s, 128, cl[j], i);
+ strncat(s, "/span-m", 128);
+ fgSetDouble(s, 40000.0);
+ }
}
fgSetDouble("/environment/metar/rain-norm", m->getRain());
fgGetDouble("/environment/metar/pressure-inhg") );
}
-
void FGClouds::setLayer( int iLayer, float alt_ft, const string& coverage, const string& layer_type ) {
double coverage_norm = 0.0;
if( coverage == "few" )
void FGClouds::buildScenario( const string& scenario ) {
string fakeMetar="";
string station = fgGetString("/environment/metar/station-id", "XXXX");
-
+
// fetch station elevation if exists
- if( station == "XXXX" )
- station_elevation_ft = fgGetDouble("/position/ground-elev-m", 0.0);
- else {
- const FGAirport* a = globals->get_airports()->search( station );
- station_elevation_ft = (a ? a->getElevation() : 0.0);
- }
+ if( station == "XXXX" )
+ station_elevation_ft = fgGetDouble("/position/ground-elev-m", 0.0);
+ else {
+ const FGAirport* a = FGAirport::findByIdent(station);
+ station_elevation_ft = (a ? a->getElevation() : 0.0);
+ }
for(int iLayer = 0 ; iLayer < thesky->get_cloud_layer_count(); iLayer++) {
thesky->get_cloud_layer(iLayer)
station += " 011000Z ";
if( scenario == "Fair weather" ) {
- fakeMetar = "15003KT 12SM SCT033 FEW200 20/08 Q1015 NOSIG";
- setLayer(0, 3300.0, "scattered", "cu");
- } else if( scenario == "Thunderstorm" ) {
+ fakeMetar = "15003KT 12SM SCT041 FEW200 20/08 Q1015 NOSIG";
+ //setLayer(0, 3300.0, "scattered", "cu");
+ } else if( scenario == "Thunderstorm" ) {
fakeMetar = "15012KT 08SM TSRA SCT040 BKN070 20/12 Q0995";
setLayer(0, 4000.0, "scattered", "cb");
setLayer(1, 7000.0, "scattered", "ns");
update_metar_properties( m );
update_env_config();
// propagate aloft tables
- _controller->reinit();
+ //_controller->reinit();
fgSetString("/environment/metar/last-metar", m->getData());
- // TODO:desactivate real metar updates
+ // TODO:de-activate real metar updates
if( scenario == "Fair weather" ) {
fgSetString("/environment/clouds/layer[1]/coverage", "cirrus");
}
}
+void FGClouds::set_scenario(const char * sc) {
-void FGClouds::build() {
- string scenario = fgGetString("/environment/weather-scenario", "METAR");
-
- if(!rebuild_required && (scenario == last_scenario))
- return;
-
+ scenario = string(sc);
+// if(!rebuild_required && (scenario == last_scenario))
+// return;
if( last_scenario == "none" ) {
// save clouds and weather conditions
param = fgGetNode("/environment/clouds", true);
copyProperties( param, last_env_clouds );
}
+
if( scenario == "METAR" ) {
string realMetar = fgGetString("/environment/metar/real-metar", "");
+
if( realMetar != "" ) {
fgSetString("/environment/metar/last-metar", realMetar.c_str());
FGMetar *m = new FGMetar( realMetar );
update_env_config();
// propagate aloft tables
_controller->reinit();
+ buildCloudLayers();
}
- buildMETAR();
}
else if( scenario == "none" ) {
// restore clouds and weather conditions
// update_env_config();
// propagate aloft tables
_controller->reinit();
- buildMETAR();
+ buildCloudLayers();
}
- else
+ else {
buildScenario( scenario );
+ _controller->reinit();
+ buildCloudLayers();
+ }
last_scenario = scenario;
- rebuild_required = false;
- // ...
if( snd_lightning == NULL )
init();
}
+const char * FGClouds::get_scenario(void) const
+{
+ return scenario.c_str();
+}
+
void FGClouds::set_3dClouds(bool enable)
{
- if (enable != clouds_3d_enabled)
- {
+ if (enable != clouds_3d_enabled) {
clouds_3d_enabled = enable;
-
- for(int iLayer = 0 ; iLayer < thesky->get_cloud_layer_count(); iLayer++) {
- thesky->get_cloud_layer(iLayer)->set_enable3dClouds(enable);
-
- if (!enable) {
- thesky->get_cloud_layer(iLayer)->get_layer3D()->clear();
- }
- }
-
- if (enable)
- {
- rebuild_required = true;
- build();
- }
+ buildCloudLayers();
}
}
-
+
bool FGClouds::get_3dClouds() const {
return clouds_3d_enabled;
}