FlightGear next
environment_mgr.cxx
Go to the documentation of this file.
1/*
2 * SPDX-FileName: environment_mgr.cxx
3 * SPDX-FileComment: manager for natural environment information
4 * SPDX-FileCopyrightText: Copyright (C) 2002 David Megginson - david@megginson.com
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8#ifdef HAVE_CONFIG_H
9# include <config.h>
10#endif
11
12#include <cstring>
13
14#include <simgear/constants.h>
15#include <simgear/debug/logstream.hxx>
16
17#include <simgear/scene/sky/sky.hxx>
18#include <simgear/scene/model/particles.hxx>
19#include <simgear/structure/event_mgr.hxx>
20
21#include <Main/main.hxx>
22#include <Main/fg_props.hxx>
23#include <Viewer/renderer.hxx>
25
26#include <FDM/flight.hxx>
27
28#include "environment.hxx"
29#include "environment_mgr.hxx"
30#include "environment_ctrl.hxx"
31#include "realwx_ctrl.hxx"
32#include "fgclouds.hxx"
33#include "precipitation_mgr.hxx"
34#include "ridge_lift.hxx"
35#include "terrainsampler.hxx"
36#include "Airports/airport.hxx"
37#include "gravity.hxx"
38#include "climate.hxx"
39#include "magvarmanager.hxx"
40
42
43class FG3DCloudsListener : public SGPropertyChangeListener {
44public:
45 FG3DCloudsListener( FGClouds * fgClouds );
46 virtual ~FG3DCloudsListener();
47
48 virtual void valueChanged (SGPropertyNode * node);
49
50private:
51 FGClouds * _fgClouds;
52 SGPropertyNode_ptr _enableNode;
53};
54
56 _fgClouds( fgClouds )
57{
58 _enableNode = fgGetNode( "/sim/rendering/clouds3d-enable", true );
59 _enableNode->addChangeListener( this );
60
61 valueChanged( _enableNode );
62}
63
65{
66 _enableNode->removeChangeListener( this );
67}
68
69void FG3DCloudsListener::valueChanged( SGPropertyNode * node )
70{
71 _fgClouds->set_3dClouds( _enableNode->getBoolValue() );
72}
73
75 _environment(new FGEnvironment()),
76 _multiplayerListener(nullptr),
77 _sky(globals->get_renderer()->getSky()),
78 nearestCarrier(nullptr),
79 nearestAirport(nullptr)
80{
81 fgClouds = new FGClouds;
82 _3dCloudsEnableListener = new FG3DCloudsListener(fgClouds);
83 set_subsystem("controller", Environment::LayerInterpolateController::createInstance( fgGetNode("/environment/config", true ) ));
84
85 set_subsystem("climate", new FGClimate);
86 set_subsystem("precipitation", new FGPrecipitationMgr);
87 set_subsystem("realwx", Environment::RealWxController::createInstance( fgGetNode("/environment/realwx", true ) ), 1.0 );
88 set_subsystem("terrainsampler", Environment::TerrainSampler::createInstance( fgGetNode("/environment/terrain", true ) ));
89 set_subsystem("ridgelift", new FGRidgeLift);
90
91 set_subsystem("magvar", new FGMagVarManager);
92 max_tower_height_feet = fgGetDouble("/sim/airport/max-tower-height-ft", 70);
93 min_tower_height_feet = fgGetDouble("/sim/airport/min-tower-height-ft", 6);
94 default_tower_height_feet = fgGetDouble("default-tower-height-ft", 30);
95}
96
98{
99 remove_subsystem( "ridgelift" );
100 remove_subsystem( "terrainsampler" );
101 remove_subsystem("precipitation");
102 remove_subsystem("realwx");
103 remove_subsystem("controller");
104 remove_subsystem("magvar");
105
106 delete fgClouds;
107 delete _3dCloudsEnableListener;
108 delete _environment;
109}
110
111struct FGEnvironmentMgrMultiplayerListener : SGPropertyChangeListener {
113 :
114 _environmentmgr(environmentmgr)
115 {
116 _node = fgGetNode("/sim/current-view/model-view", true /*create*/);
117 _node->addChangeListener(this);
118 }
119 virtual void valueChanged(SGPropertyNode* node)
120 {
121 _environmentmgr->updateClosestAirport();
122 }
124 {
125 _node->removeChangeListener(this);
126 }
127 private:
128 FGEnvironmentMgr* _environmentmgr;
129 SGPropertyNode_ptr _node;
130};
131
132SGSubsystem::InitStatus FGEnvironmentMgr::incrementalInit()
133{
134
135 InitStatus r = SGSubsystemGroup::incrementalInit();
136 if (r == INIT_DONE) {
137 fgClouds->Init();
138 _multiplayerListener = new FGEnvironmentMgrMultiplayerListener(this);
139 globals->get_event_mgr()->addTask("updateClosestAirport",
140 [this](){ this->updateClosestAirport(); }, 10 );
141 }
142
143 return r;
144}
145
146void
148{
149 globals->get_event_mgr()->removeTask("updateClosestAirport");
150 delete _multiplayerListener;
151 _multiplayerListener = nullptr;
152 SGSubsystemGroup::shutdown();
153}
154
155void
157{
158 SG_LOG( SG_ENVIRONMENT, SG_INFO, "Reinitializing environment subsystem");
159 SGSubsystemGroup::reinit();
160}
161
162void
164{
165 SGSubsystemGroup::bind();
166 _environment->Tie( fgGetNode("/environment", true ) );
167
168 _tiedProperties.setRoot( fgGetNode( "/environment", true ) );
169
170 _tiedProperties.Tie( "effective-visibility-m", _sky,
171 &SGSky::get_visibility );
172
173 _tiedProperties.Tie("rebuild-layers", fgClouds,
176// _tiedProperties.Tie("turbulence/use-cloud-turbulence", &sgEnviro,
177// &SGEnviro::get_turbulence_enable_state,
178// &SGEnviro::set_turbulence_enable_state);
179
180 for (int i = 0; i < MAX_CLOUD_LAYERS; i++) {
181 SGPropertyNode_ptr layerNode = fgGetNode("/environment/clouds",true)->getChild("layer", i, true );
182
183 _tiedProperties.Tie( layerNode->getNode("span-m",true), this, i,
184 &FGEnvironmentMgr::get_cloud_layer_span_m,
185 &FGEnvironmentMgr::set_cloud_layer_span_m);
186
187 _tiedProperties.Tie( layerNode->getNode("elevation-ft",true), this, i,
188 &FGEnvironmentMgr::get_cloud_layer_elevation_ft,
189 &FGEnvironmentMgr::set_cloud_layer_elevation_ft);
190
191 _tiedProperties.Tie( layerNode->getNode("thickness-ft",true), this, i,
192 &FGEnvironmentMgr::get_cloud_layer_thickness_ft,
193 &FGEnvironmentMgr::set_cloud_layer_thickness_ft);
194
195 _tiedProperties.Tie( layerNode->getNode("transition-ft",true), this, i,
196 &FGEnvironmentMgr::get_cloud_layer_transition_ft,
197 &FGEnvironmentMgr::set_cloud_layer_transition_ft);
198
199 _tiedProperties.Tie( layerNode->getNode("coverage",true), this, i,
200 &FGEnvironmentMgr::get_cloud_layer_coverage,
201 &FGEnvironmentMgr::set_cloud_layer_coverage);
202
203 _tiedProperties.Tie( layerNode->getNode("coverage-type",true), this, i,
204 &FGEnvironmentMgr::get_cloud_layer_coverage_type,
205 &FGEnvironmentMgr::set_cloud_layer_coverage_type);
206
207 _tiedProperties.Tie( layerNode->getNode( "visibility-m",true), this, i,
208 &FGEnvironmentMgr::get_cloud_layer_visibility_m,
209 &FGEnvironmentMgr::set_cloud_layer_visibility_m);
210
211 _tiedProperties.Tie( layerNode->getNode( "alpha",true), this, i,
212 &FGEnvironmentMgr::get_cloud_layer_maxalpha,
213 &FGEnvironmentMgr::set_cloud_layer_maxalpha);
214 }
215
216 _tiedProperties.setRoot( fgGetNode("/sim/rendering", true ) );
217
218 _tiedProperties.Tie( "clouds3d-density", _sky,
219 &SGSky::get_3dCloudDensity,
220 &SGSky::set_3dCloudDensity);
221
222 _tiedProperties.Tie("clouds3d-vis-range", _sky,
223 &SGSky::get_3dCloudVisRange,
224 &SGSky::set_3dCloudVisRange);
225
226 _tiedProperties.Tie("clouds3d-impostor-range", _sky,
227 &SGSky::get_3dCloudImpostorDistance,
228 &SGSky::set_3dCloudImpostorDistance);
229
230 _tiedProperties.Tie("clouds3d-lod1-range", _sky,
231 &SGSky::get_3dCloudLoD1Range,
232 &SGSky::set_3dCloudLoD1Range);
233
234 _tiedProperties.Tie("clouds3d-lod2-range", _sky,
235 &SGSky::get_3dCloudLoD2Range,
236 &SGSky::set_3dCloudLoD2Range);
237
238 _tiedProperties.Tie("clouds3d-wrap", _sky,
239 &SGSky::get_3dCloudWrap,
240 &SGSky::set_3dCloudWrap);
241
242 _tiedProperties.Tie("clouds3d-use-impostors", _sky,
243 &SGSky::get_3dCloudUseImpostors,
244 &SGSky::set_3dCloudUseImpostors);
245}
246
247void
249{
250 _tiedProperties.Untie();
251 _environment->Untie();
252 SGSubsystemGroup::unbind();
253}
254
255void
257{
258 SGGeod aircraftPos(globals->get_aircraft_position());
259
260 SGSubsystemGroup::update(dt);
261
262 _environment->set_elevation_ft( aircraftPos.getElevationFt() );
263
264 auto particlesManager = simgear::ParticlesGlobalManager::instance();
265 particlesManager->setWindFrom(_environment->get_wind_from_heading_deg(),
266 _environment->get_wind_speed_kt());
267 particlesManager->update(dt, globals->get_aircraft_position());
268
269 if( _cloudLayersDirty ) {
270 _cloudLayersDirty = false;
271 fgClouds->set_update_event( fgClouds->get_update_event()+1 );
272 }
273 updateTowerPosition();
274
275 fgSetDouble( "/environment/gravitational-acceleration-mps2",
276 Environment::Gravity::instance()->getGravity(aircraftPos));
277}
278
279void FGEnvironmentMgr::updateTowerPosition()
280{
281 if (towerViewPositionLatDegNode != nullptr && towerViewPositionLonDegNode != nullptr && towerViewPositionAltFtNode != nullptr) {
282 auto automaticTowerActive = fgGetBool("/sim/tower/auto-position", true);
283
284 fgSetDouble("/sim/airport/nearest-tower-latitude-deg", towerViewPositionLatDegNode->getDoubleValue());
285 fgSetDouble("/sim/airport/nearest-tower-longitude-deg", towerViewPositionLonDegNode->getDoubleValue());
286 fgSetDouble("/sim/airport/nearest-tower-altitude-ft", towerViewPositionAltFtNode->getDoubleValue());
287
288 if (automaticTowerActive) {
289 fgSetDouble("/sim/tower/latitude-deg", towerViewPositionLatDegNode->getDoubleValue());
290 fgSetDouble("/sim/tower/longitude-deg", towerViewPositionLonDegNode->getDoubleValue());
291 fgSetDouble("/sim/tower/altitude-ft", towerViewPositionAltFtNode->getDoubleValue());
292 }
293 }
294}
295
296void FGEnvironmentMgr::updateClosestAirport()
297{
298 SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "FGEnvironmentMgr::update: updating closest airport");
299
300 SGGeod pos = globals->get_aircraft_position();
301
302 //
303 // If we are viewing a multiplayer aircraft, find nearest airport so that
304 // Tower View etc works.
305 std::string view_config_root = ViewPropertyEvaluator::getStringValue("(/sim/view[(/sim/current-view/view-number-raw)]/config/root)");
306
307 if (view_config_root != "/" && view_config_root != "") {
308 /* We are currently viewing a multiplayer aircraft. */
309 pos = SGGeod::fromDegFt(
310 ViewPropertyEvaluator::getDoubleValue("((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/position/longitude-deg)"),
311 ViewPropertyEvaluator::getDoubleValue("((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/position/latitude-deg)"),
312 ViewPropertyEvaluator::getDoubleValue("((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/position/altitude-ft)"));
313 }
314
315 // nearest tower logic;
316 // 1. find nearest airport
317 // 2. find nearest carrier
318 // - select the nearest one as the tower.
319
320 nearestAirport = FGAirport::findClosest(pos, 100.0);
321 auto automaticTowerActive = fgGetBool("/sim/tower/auto-position", true);
322
323 SGGeod nearestTowerPosition;
324 std::string nearestIdent;
325 const SGGeod airportGeod;
326 double towerDistance = std::numeric_limits<double>::max();
327 if (nearestAirport) {
328 const std::string currentId = fgGetString("/sim/airport/closest-airport-id", "");
329 if (currentId != nearestAirport->ident()) {
330 SG_LOG(SG_ENVIRONMENT, SG_INFO, "FGEnvironmentMgr::updateClosestAirport: selected:" << nearestAirport->ident());
331 fgSetString("/sim/airport/closest-airport-id", nearestAirport->ident().c_str());
332 }
333
334 if (nearestAirport->hasTower()) {
335 nearestTowerPosition = nearestAirport->getTowerLocation();
336 SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "airport-id=" << nearestAirport->getId() << " tower_pos=" << nearestTowerPosition);
337 }
338 else {
339 nearestTowerPosition = nearestAirport->geod();
340 SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "no tower for airport-id=" << nearestAirport->getId());
341 }
342 //Ensure that the tower isn't at ground level by adding a nominal amount
343 // TODO: (fix the data so that too short or too tall towers aren't present in the data)
344 auto towerAirpotDistance = abs(nearestTowerPosition.getElevationFt() - nearestAirport->geod().getElevationFt());
345 if (towerAirpotDistance < min_tower_height_feet) {
346 nearestTowerPosition.setElevationFt(nearestTowerPosition.getElevationFt() + default_tower_height_feet);
347 SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "Tower altitude adjusted because it was at below minimum height above ground (" << min_tower_height_feet << "feet) for airport " << nearestAirport->getId());
348 }
349 else if (towerAirpotDistance > max_tower_height_feet) {
350 nearestTowerPosition.setElevationFt(nearestTowerPosition.getElevationFt() + default_tower_height_feet);
351 SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "Tower altitude adjusted because it was taller than the permitted maximum of (" << max_tower_height_feet << "feet) for airport " << nearestAirport->getId());
352 }
353 //
354 nearestIdent = nearestAirport->ident();
355 towerDistance = SGGeodesy::distanceM(nearestTowerPosition, pos);
356
357 // when the tower doesn't move we can clear these.
358 // if the carrier is nearer these variables will be set in that logic.
359 towerViewPositionLatDegNode = towerViewPositionLonDegNode = towerViewPositionAltFtNode = nullptr;
360 }
361 else {
362 SG_LOG(SG_ENVIRONMENT, SG_INFO, "FGEnvironmentMgr::update: No airport within 100NM range");
363 }
364 auto nctn = SGSharedPtr< NearestCarrierToNotification> (new NearestCarrierToNotification(pos));
365 if (simgear::Emesary::ReceiptStatus::OK == simgear::Emesary::GlobalTransmitter::instance()->NotifyAll(nctn)) {
366 if (nearestCarrier != nctn->GetCarrier()) {
367 nearestCarrier = nctn->GetCarrier();
368 fgSetString("/sim/airport/nearest-carrier", nctn->GetCarrierIdent());
369 }
370 } else {
371 fgSetString("/sim/airport/nearest-carrier", "");
372 fgSetDouble("/sim/airport/nearest-carrier-latitude-deg", 0);
373 fgSetDouble("/sim/airport/nearest-carrier-longitude-deg", 0);
374 fgSetDouble("/sim/airport/nearest-carrier-altitude-ft", 0);
375 fgSetDouble("/sim/airport/nearest-carrier-deck-height", 0);
376 nearestCarrier = nullptr;
377 }
378
379 // figure out if the carrier's tower is closer
380 if (nearestCarrier && (nctn->GetDistanceMeters() < towerDistance)) {
381 nearestIdent = nctn->GetCarrierIdent();
382
383 //
384 // these will be used to determine and update the tower position
385 towerViewPositionLatDegNode = nctn->GetViewPositionLatNode();
386 towerViewPositionLonDegNode = nctn->GetViewPositionLonNode();
387 towerViewPositionAltFtNode = nctn->GetViewPositionAltNode();
388
389 // although the carrier is moving - these values can afford to be 10 seconds old so we don't need to
390 // update them.
391 fgSetDouble("/sim/airport/nearest-carrier-latitude-deg", nctn->GetPosition()->getLatitudeDeg());
392 fgSetDouble("/sim/airport/nearest-carrier-longitude-deg", nctn->GetPosition()->getLongitudeDeg());
393 fgSetDouble("/sim/airport/nearest-carrier-altitude-ft", nctn->GetPosition()->getElevationFt());
394 fgSetDouble("/sim/airport/nearest-carrier-deck-height", nctn->GetDeckheight());
395 } else {
396 if (nearestAirport != nullptr) {
397
398 if (automaticTowerActive) {
399 std::string path = ViewPropertyEvaluator::getStringValue("(/sim/view[(/sim/current-view/view-number-raw)]/config/root)/sim/tower/");
400 fgSetString(path + "airport-id", nearestAirport->getId());
401
402 fgSetDouble(path + "latitude-deg", nearestTowerPosition.getLatitudeDeg());
403 fgSetDouble(path + "longitude-deg", nearestTowerPosition.getLongitudeDeg());
404 fgSetDouble(path + "altitude-ft", nearestTowerPosition.getElevationFt());
405 }
406 }
407 else {
408 SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "FGEnvironmentMgr::update: No airport or carrier within 100NM range of current multiplayer aircraft");
409 }
410 }
411
412
413 if (fgGetString("/sim/airport/nearest-tower-ident") != nearestIdent) {
414 SG_LOG(SG_ENVIRONMENT, SG_INFO, "Nearest airport tower now " << nearestIdent);
415 fgSetString("/sim/airport/nearest-tower-ident", nearestIdent);
416 }
417 if (automaticTowerActive) {
418 if (fgGetString("/sim/tower/airport-id") != nearestIdent) {
419 fgSetString("/sim/tower/airport-id", nearestIdent);
420 SG_LOG(SG_ENVIRONMENT, SG_INFO, "Auto Tower: now " << nearestIdent);
421 }
422 }
423 updateTowerPosition();
424}
425
426
429{
430 return *_environment;
431}
432
434{
435 return _environment;
436}
437
440{
441 // Always returns the same environment
442 // for now; we'll make it interesting
443 // later.
444 FGEnvironment env = *_environment;
445 env.set_elevation_ft(aPos.getElevationFt());
446 return env;
447
448}
449
450double
451FGEnvironmentMgr::get_cloud_layer_span_m (int index) const
452{
453 return _sky->get_cloud_layer(index)->getSpan_m();
454}
455
456void
457FGEnvironmentMgr::set_cloud_layer_span_m (int index, double span_m)
458{
459 _sky->get_cloud_layer(index)->setSpan_m(span_m);
460}
461
462double
463FGEnvironmentMgr::get_cloud_layer_elevation_ft (int index) const
464{
465 return _sky->get_cloud_layer(index)->getElevation_m() * SG_METER_TO_FEET;
466}
467
468void
469FGEnvironmentMgr::set_cloud_layer_elevation_ft (int index, double elevation_ft)
470{
471 FGEnvironment env = *_environment;
472 env.set_elevation_ft(elevation_ft);
473
474 _sky->get_cloud_layer(index)
475 ->setElevation_m(elevation_ft * SG_FEET_TO_METER);
476
477 _sky->get_cloud_layer(index)
478 ->setSpeed(env.get_wind_speed_kt() * 0.5151); // 1 kt = 0.5151 m/s
479
480 _sky->get_cloud_layer(index)
481 ->setDirection(env.get_wind_from_heading_deg());
482}
483
484double
485FGEnvironmentMgr::get_cloud_layer_thickness_ft (int index) const
486{
487 return _sky->get_cloud_layer(index)->getThickness_m() * SG_METER_TO_FEET;
488}
489
490void
491FGEnvironmentMgr::set_cloud_layer_thickness_ft (int index, double thickness_ft)
492{
493 _sky->get_cloud_layer(index)
494 ->setThickness_m(thickness_ft * SG_FEET_TO_METER);
495}
496
497double
498FGEnvironmentMgr::get_cloud_layer_transition_ft (int index) const
499{
500 return _sky->get_cloud_layer(index)->getTransition_m() * SG_METER_TO_FEET;
501}
502
503void
504FGEnvironmentMgr::set_cloud_layer_transition_ft (int index,
505 double transition_ft)
506{
507 _sky->get_cloud_layer(index)
508 ->setTransition_m(transition_ft * SG_FEET_TO_METER);
509}
510
511const char *
512FGEnvironmentMgr::get_cloud_layer_coverage (int index) const
513{
514 return _sky->get_cloud_layer(index)->getCoverageString().c_str();
515}
516
517void
518FGEnvironmentMgr::set_cloud_layer_coverage (int index,
519 const char * coverage_name)
520{
521 if( _sky->get_cloud_layer(index)->getCoverageString() == coverage_name )
522 return;
523
524 _sky->get_cloud_layer(index)->setCoverageString(coverage_name);
525 _cloudLayersDirty = true;
526}
527
528int
529FGEnvironmentMgr::get_cloud_layer_coverage_type (int index) const
530{
531 return _sky->get_cloud_layer(index)->getCoverage();
532}
533
534double
535FGEnvironmentMgr::get_cloud_layer_visibility_m (int index) const
536{
537 return _sky->get_cloud_layer(index)->getVisibility_m();
538}
539
540void
541FGEnvironmentMgr::set_cloud_layer_visibility_m (int index, double visibility_m)
542{
543 _sky->get_cloud_layer(index)->setVisibility_m(visibility_m);
544}
545
546double
547FGEnvironmentMgr::get_cloud_layer_maxalpha (int index ) const
548{
549 return _sky->get_cloud_layer(index)->getMaxAlpha();
550}
551
552void
553FGEnvironmentMgr::set_cloud_layer_maxalpha (int index, double maxalpha)
554{
555 _sky->get_cloud_layer(index)->setMaxAlpha(maxalpha);
556}
557
558void
559FGEnvironmentMgr::set_cloud_layer_coverage_type (int index, int type )
560{
561 if( type < 0 || type >= SGCloudLayer::SG_MAX_CLOUD_COVERAGES ) {
562 SG_LOG(SG_ENVIRONMENT,SG_WARN,"Unknown cloud layer type " << type << " ignored" );
563 return;
564 }
565
566 if( static_cast<SGCloudLayer::Coverage>(type) == _sky->get_cloud_layer(index)->getCoverage() )
567 return;
568
569 _sky->get_cloud_layer(index)->setCoverage(static_cast<SGCloudLayer::Coverage>(type));
570 _cloudLayersDirty = true;
571}
572
573
574// Register the subsystem.
575SGSubsystemMgr::Registrant<FGEnvironmentMgr> registrantFGEnvironmentMgr;
576
577// end of environment-mgr.cxx
#define i(x)
static const Gravity * instance()
Definition gravity.cxx:80
static LayerInterpolateController * createInstance(SGPropertyNode_ptr rootNode)
static RealWxController * createInstance(SGPropertyNode_ptr rootNode)
static TerrainSampler * createInstance(SGPropertyNode_ptr rootNode)
virtual void valueChanged(SGPropertyNode *node)
FG3DCloudsListener(FGClouds *fgClouds)
static FGAirportRef findClosest(const SGGeod &aPos, double aCuttofNm, Filter *filter=NULL)
Syntactic wrapper around FGPositioned::findClosest - find the closest match for filter,...
Definition airport.cxx:425
void set_update_event(int count)
Definition fgclouds.cxx:70
int get_update_event(void) const
Definition fgclouds.cxx:66
Manage environment information.
virtual ~FGEnvironmentMgr()
InitStatus incrementalInit() override
void unbind() override
void bind() override
const FGEnvironment * getAircraftEnvironment() const
void update(double dt) override
virtual FGEnvironment getEnvironmentAtPosition(const SGGeod &aPos) const
void reinit() override
void shutdown() override
virtual FGEnvironment getEnvironment() const
Get the environment information for the plane's current position.
Model the natural environment.
virtual double get_wind_speed_kt() const
virtual double get_wind_from_heading_deg() const
virtual void set_elevation_ft(double elevation_ft)
SGGeod get_aircraft_position() const
Definition globals.cxx:611
SGSubsystemMgr::Registrant< FGEnvironmentMgr > registrantFGEnvironmentMgr
std::string fgGetString(const char *name, const char *defaultValue)
Get a string value for a property.
Definition fg_props.cxx:556
FGGlobals * globals
Definition globals.cxx:142
const std::string & getStringValue(const char *spec)
double getDoubleValue(const char *spec, double default_)
float abs(float f)
Definition Airplane.cpp:21
Precipitation manager This manager calculate the intensity of precipitation in function of the altitu...
bool fgSetDouble(const char *name, double defaultValue)
Set a double value for a property.
Definition proptest.cpp:31
bool fgGetBool(char const *name, bool def)
Get a bool value for a property.
Definition proptest.cpp:25
double fgGetDouble(const char *name, double defaultValue)
Get a double value for a property.
Definition proptest.cpp:30
bool fgSetString(char const *name, char const *str)
Set a string value for a property.
Definition proptest.cpp:26
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
Definition proptest.cpp:27
FGEnvironmentMgrMultiplayerListener(FGEnvironmentMgr *environmentmgr)
virtual void valueChanged(SGPropertyNode *node)