X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FEnvironment%2Ffgclouds.cxx;h=58653e05364c3dce780ab2695d3f308743ff8406;hb=c152e7f118881183199285a8b1a9e33d3cbff750;hp=c66eb7a1094263272ab707abb3f0a33fe983fe78;hpb=8f6098024bfb1d80c0d26fb2e1b791c3f781a46b;p=flightgear.git diff --git a/src/Environment/fgclouds.cxx b/src/Environment/fgclouds.cxx index c66eb7a10..58653e053 100644 --- a/src/Environment/fgclouds.cxx +++ b/src/Environment/fgclouds.cxx @@ -24,36 +24,43 @@ # include "config.h" #endif +#include "fgclouds.hxx" + #include +#include #include
#include #include #include -#include +//#include #include #include -#include +#include #include #include
-#include #include
+#include +#include -#include "fgclouds.hxx" - -extern SGSky *thesky; - +// RNG seed to ensure cloud synchronization across multi-process +// deployments +static mt seed; FGClouds::FGClouds() : - snd_lightning(0), - clouds_3d_enabled(false) + clouds_3d_enabled(false), + index(0) { update_event = 0; } -FGClouds::~FGClouds() +FGClouds::~FGClouds() { + globals->get_commands()->removeCommand("add-cloud"); + globals->get_commands()->removeCommand("del-cloud"); + globals->get_commands()->removeCommand("move-cloud"); + } int FGClouds::get_update_event(void) const { @@ -65,20 +72,19 @@ void FGClouds::set_update_event(int count) { buildCloudLayers(); } -void FGClouds::init(void) { - if( snd_lightning == NULL ) { - snd_lightning = new SGSoundSample("Sounds/thunder.wav", SGPath()); - snd_lightning->set_max_dist(7000.0f); - snd_lightning->set_reference_dist(3000.0f); - SGSoundMgr *smgr = globals->get_soundmgr(); - SGSampleGroup *sgr = smgr->find("weather", true); - sgr->add( snd_lightning, "thunder" ); - sgEnviro.set_sampleGroup( sgr ); - } +void FGClouds::Init(void) +{ + mt_init_time_10(&seed); + + globals->get_commands()->addCommand("add-cloud", this, &FGClouds::add3DCloud); + globals->get_commands()->addCommand("del-cloud", this, &FGClouds::delete3DCloud); + globals->get_commands()->addCommand("move-cloud", this, &FGClouds::move3DCloud); } // Build an invidual cloud. Returns the extents of the cloud for coverage calculations -double FGClouds::buildCloud(SGPropertyNode *cloud_def_root, SGPropertyNode *box_def_root, const string& name, double grid_z_rand, SGCloudField *layer) { +double FGClouds::buildCloud(SGPropertyNode *cloud_def_root, SGPropertyNode *box_def_root, + const std::string& name, double grid_z_rand, SGCloudField *layer) +{ SGPropertyNode *box_def=NULL; SGPropertyNode *cld_def=NULL; double extent = 0.0; @@ -98,10 +104,13 @@ double FGClouds::buildCloud(SGPropertyNode *cloud_def_root, SGPropertyNode *box_ return 0.0; } - double x = sg_random() * SGCloudField::fieldSize - (SGCloudField::fieldSize / 2.0); - double y = sg_random() * SGCloudField::fieldSize - (SGCloudField::fieldSize / 2.0); - double z = grid_z_rand * (sg_random() - 0.5); - + double x = mt_rand(&seed) * SGCloudField::fieldSize - (SGCloudField::fieldSize / 2.0); + double y = mt_rand(&seed) * SGCloudField::fieldSize - (SGCloudField::fieldSize / 2.0); + double z = grid_z_rand * (mt_rand(&seed) - 0.5); + + float lon = fgGetNode("/position/longitude-deg", false)->getFloatValue(); + float lat = fgGetNode("/position/latitude-deg", false)->getFloatValue(); + SGVec3f pos(x,y,z); for(int i = 0; i < box_def->nChildren() ; i++) { @@ -111,16 +120,16 @@ double FGClouds::buildCloud(SGPropertyNode *cloud_def_root, SGPropertyNode *box_ string type = abox->getStringValue("type", "cu-small"); cld_def = cloud_def_root->getChild(type.c_str()); if ( !cld_def ) return 0.0; - + double w = abox->getDoubleValue("width", 1000.0); double h = abox->getDoubleValue("height", 1000.0); int hdist = abox->getIntValue("hdist", 1); int vdist = abox->getIntValue("vdist", 1); double c = abox->getDoubleValue("count", 5); - int count = (int) (c + (sg_random() - 0.5) * c); + int count = (int) (c + (mt_rand(&seed) - 0.5) * c); - extent = max(w*w, extent); + extent = std::max(w*w, extent); for (int j = 0; j < count; j++) { @@ -133,52 +142,24 @@ double FGClouds::buildCloud(SGPropertyNode *cloud_def_root, SGPropertyNode *box_ for (int k = 0; k < hdist; k++) { - x += (sg_random() / hdist); - y += (sg_random() / hdist); + x += (mt_rand(&seed) / hdist); + y += (mt_rand(&seed) / hdist); } for (int k = 0; k < vdist; k++) { - z += (sg_random() / vdist); + z += (mt_rand(&seed) / vdist); } x = w * (x - 0.5) + pos[0]; // N/S y = w * (y - 0.5) + pos[1]; // E/W z = h * z + pos[2]; // Up/Down. pos[2] is the cloudbase - SGVec3f newpos = SGVec3f(x, y, z); - - double min_width = cld_def->getDoubleValue("min-cloud-width-m", 500.0); - double max_width = cld_def->getDoubleValue("max-cloud-width-m", 1000.0); - double min_height = cld_def->getDoubleValue("min-cloud-height-m", min_width); - double max_height = cld_def->getDoubleValue("max-cloud-height-m", max_width); - double min_sprite_width = cld_def->getDoubleValue("min-sprite-width-m", 200.0); - double max_sprite_width = cld_def->getDoubleValue("max-sprite-width-m", min_sprite_width); - double min_sprite_height = cld_def->getDoubleValue("min-sprite-height-m", min_sprite_width); - double max_sprite_height = cld_def->getDoubleValue("max-sprite-height-m", max_sprite_width); - int num_sprites = cld_def->getIntValue("num-sprites", 20); - int num_textures_x = cld_def->getIntValue("num-textures-x", 1); - int num_textures_y = cld_def->getIntValue("num-textures-y", 1); - double bottom_shade = cld_def->getDoubleValue("bottom-shade", 1.0); - string texture = cld_def->getStringValue("texture", "cu.png"); - - SGNewCloud *cld = - new SGNewCloud(type, - texture_root, - texture, - min_width, - max_width, - min_height, - max_height, - min_sprite_width, - max_sprite_width, - min_sprite_height, - max_sprite_height, - bottom_shade, - num_sprites, - num_textures_x, - num_textures_y); - layer->addCloud(newpos, cld); + //SGVec3f newpos = SGVec3f(x, y, z); + SGNewCloud cld(texture_root, cld_def, &seed); + + //layer->addCloud(newpos, cld.genCloud()); + layer->addCloud(lon, lat, z, x, y, index++, cld.genCloud()); } } } @@ -195,6 +176,8 @@ void FGClouds::buildLayer(int iLayer, const string& name, double coverage) { int CloudVarietyCount = 0; double totalCount = 0.0; + SGSky* thesky = globals->get_renderer()->getSky(); + 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); @@ -235,11 +218,10 @@ void FGClouds::buildLayer(int iLayer, const string& name, double coverage) { double count = acloud->getDoubleValue("count", 1.0); tCloudVariety[CloudVarietyCount].count = count; int variety = 0; - cloud_name = cloud_name + "-%d"; char variety_name[50]; do { variety++; - snprintf(variety_name, sizeof(variety_name) - 1, cloud_name.c_str(), variety); + snprintf(variety_name, sizeof(variety_name) - 1, "%s-%d", cloud_name.c_str(), variety); } while( box_def_root->getChild(variety_name, 0, false) ); totalCount += count; @@ -253,7 +235,7 @@ void FGClouds::buildLayer(int iLayer, const string& name, double coverage) { double cov = coverage * SGCloudField::fieldSize * SGCloudField::fieldSize; while (cov > 0.0f) { - double choice = sg_random(); + double choice = mt_rand(&seed); for(int i = 0; i < CloudVarietyCount ; i ++) { choice -= tCloudVariety[i].count * totalCount; @@ -266,7 +248,6 @@ void FGClouds::buildLayer(int iLayer, const string& name, double coverage) { break; } } - } // Now we've built any clouds, enable them and set the density (coverage) @@ -288,6 +269,7 @@ void FGClouds::buildCloudLayers(void) { double cumulus_base = 122.0 * (temperature_degc - dewpoint_degc); double stratus_base = 100.0 * (100.0 - rel_humidity) * SG_FEET_TO_METER; + SGSky* thesky = globals->get_renderer()->getSky(); for(int iLayer = 0 ; iLayer < thesky->get_cloud_layer_count(); iLayer++) { SGPropertyNode *cloud_root = fgGetNode("/environment/clouds/layer", iLayer, true); @@ -335,7 +317,7 @@ void FGClouds::buildCloudLayers(void) { layer_type = "sc"; } } - + cloud_root->setStringValue("layer-type",layer_type); buildLayer(iLayer, layer_type, coverage_norm); } @@ -349,8 +331,87 @@ void FGClouds::set_3dClouds(bool enable) } } -bool FGClouds::get_3dClouds() const +bool FGClouds::get_3dClouds() const { return clouds_3d_enabled; } +/** + * Adds a 3D cloud to a cloud layer. + * + * Property arguments + * layer - the layer index to add this cloud to. (Defaults to 0) + * index - the index for this cloud (to be used later) + * lon/lat/alt - the position for the cloud + * (Various) - cloud definition properties. See README.3DClouds + * + */ + bool FGClouds::add3DCloud(const SGPropertyNode *arg) + { + int l = arg->getIntValue("layer", 0); + int index = arg->getIntValue("index", 0); + + SGPath texture_root = globals->get_fg_root(); + texture_root.append("Textures"); + texture_root.append("Sky"); + + float lon = arg->getFloatValue("lon-deg", 0.0f); + float lat = arg->getFloatValue("lat-deg", 0.0f); + float alt = arg->getFloatValue("alt-ft", 0.0f); + float x = arg->getFloatValue("x-offset-m", 0.0f); + float y = arg->getFloatValue("y-offset-m", 0.0f); + + SGSky* thesky = globals->get_renderer()->getSky(); + SGCloudField *layer = thesky->get_cloud_layer(l)->get_layer3D(); + SGNewCloud cld(texture_root, arg, &seed); + bool success = layer->addCloud(lon, lat, alt, x, y, index, cld.genCloud()); + + // Adding a 3D cloud immediately makes this layer 3D. + thesky->get_cloud_layer(l)->set_enable3dClouds(true); + + return success; + } + + /** + * Removes a 3D cloud from a cloud layer + * + * Property arguments + * + * layer - the layer index to remove this cloud from. (defaults to 0) + * index - the cloud index + * + */ + bool FGClouds::delete3DCloud(const SGPropertyNode *arg) + { + int l = arg->getIntValue("layer", 0); + int i = arg->getIntValue("index", 0); + + SGSky* thesky = globals->get_renderer()->getSky(); + SGCloudField *layer = thesky->get_cloud_layer(l)->get_layer3D(); + return layer->deleteCloud(i); + } + +/** + * Move a cloud within a 3D layer + * + * Property arguments + * layer - the layer index to add this cloud to. (Defaults to 0) + * index - the cloud index to move. + * lon/lat/alt - the position for the cloud + * + */ +bool FGClouds::move3DCloud(const SGPropertyNode *arg) + { + int l = arg->getIntValue("layer", 0); + int i = arg->getIntValue("index", 0); + SGSky* thesky = globals->get_renderer()->getSky(); + + float lon = arg->getFloatValue("lon-deg", 0.0f); + float lat = arg->getFloatValue("lat-deg", 0.0f); + float alt = arg->getFloatValue("alt-ft", 0.0f); + float x = arg->getFloatValue("x-offset-m", 0.0f); + float y = arg->getFloatValue("y-offset-m", 0.0f); + + SGCloudField *layer = thesky->get_cloud_layer(l)->get_layer3D(); + return layer->repositionCloud(i, lon, lat, alt, x, y); + }