diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index 40c790a16..ab293b98b 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -54,11 +54,12 @@ FGAIAircraft *FGAIAircraft::_self = NULL; FGAIAircraft::FGAIAircraft(FGAIManager* mgr) { manager = mgr; _self = this; + _type_str = "aircraft"; + _otype = otAircraft; // set heading and altitude locks hdg_lock = false; alt_lock = false; - _type_str = "aircraft"; } diff --git a/src/AIModel/AIBallistic.cxx b/src/AIModel/AIBallistic.cxx index 0e7249e4e..c712a989b 100644 --- a/src/AIModel/AIBallistic.cxx +++ b/src/AIModel/AIBallistic.cxx @@ -30,6 +30,7 @@ FGAIBallistic::FGAIBallistic(FGAIManager* mgr) { manager = mgr; _type_str = "ballistic"; + _otype = otBallistic; } FGAIBallistic::~FGAIBallistic() { diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx index 123a936e8..bb1af2279 100644 --- a/src/AIModel/AIBase.cxx +++ b/src/AIModel/AIBase.cxx @@ -52,6 +52,7 @@ FGAIBase::FGAIBase() { x_shift = y_shift = rotation = 0.0; invisible = true; model_path = ""; + _otype = otNull; } FGAIBase::~FGAIBase() { @@ -103,6 +104,12 @@ bool FGAIBase::init() { return true; } +bool FGAIBase::isa( object_type otype ) { + if ( otype == _otype ) { return true; } + else { return false; } +} + + void FGAIBase::bind() { props->tie("id", SGRawValuePointer(&id)); props->tie("velocities/true-airspeed-kt", SGRawValuePointer(&speed)); diff --git a/src/AIModel/AIBase.hxx b/src/AIModel/AIBase.hxx index a9a00408c..44ebd61e8 100644 --- a/src/AIModel/AIBase.hxx +++ b/src/AIModel/AIBase.hxx @@ -41,6 +41,9 @@ public: virtual void update(double dt); inline Point3D GetPos() { return(pos); } + enum object_type { otNull, otAircraft, otShip, otBallistic, + otRocket, otStorm, otThermal }; + virtual bool init(); virtual void bind(); virtual void unbind(); @@ -103,6 +106,7 @@ protected: static FGAIBase *_self; const char *_type_str; + object_type _otype; public: @@ -129,6 +133,7 @@ public: static double _getRotation(); static bool _isNight(); + bool isa( object_type otype ); }; diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index 394951f09..ceffc4c4a 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -37,6 +37,7 @@ SG_USING_STD(list); FGAIManager::FGAIManager() { initDone = false; numObjects = 0; + _dt = 0.0; dt_count = 9; } @@ -54,6 +55,7 @@ FGAIManager::~FGAIManager() { void FGAIManager::init() { int rval; root = fgGetNode("sim/ai", true); + wind_from_down = fgGetNode("/environment/wind-from-down-fps", true); for (int i = 0; i < root->nChildren(); i++) { const SGPropertyNode * entry = root->getChild(i); @@ -127,10 +129,16 @@ void FGAIManager::unbind() { void FGAIManager::update(double dt) { - + + // initialize these for finding nearest thermals + range_nearest = 10000.0; + strength = 0.0; + + _dt = dt; + ai_list_itr = ai_list.begin(); while(ai_list_itr != ai_list.end()) { - if ((*ai_list_itr)->getDie()) { + if ((*ai_list_itr)->getDie()) { freeID((*ai_list_itr)->getID()); delete (*ai_list_itr); ai_list.erase(ai_list_itr); @@ -138,10 +146,15 @@ void FGAIManager::update(double dt) { --numObjects; } else { fetchUserState(); - (*ai_list_itr)->update(dt); + if ((*ai_list_itr)->isa(FGAIBase::otThermal)) { + processThermal((FGAIThermal*)*ai_list_itr); + } else { + (*ai_list_itr)->update(_dt); + } } ++ai_list_itr; } + wind_from_down->setDoubleValue( strength ); } @@ -277,7 +290,7 @@ int FGAIManager::createThermal( double latitude, double longitude, ++numObjects; ai_thermal->setLongitude(longitude); ai_thermal->setLatitude(latitude); - ai_thermal->setStrength(strength); + ai_thermal->setMaxStrength(strength); ai_thermal->setDiameter(diameter / 6076.11549); ai_thermal->init(); ai_thermal->bind(); @@ -313,3 +326,13 @@ void FGAIManager::fetchUserState( void ) { dt_count = 0; } } + + +// only keep the results from the nearest thermal +void FGAIManager::processThermal( FGAIThermal* thermal ) { + thermal->update(_dt); + if ( thermal->_getRange() < range_nearest ) { + range_nearest = thermal->_getRange(); + strength = thermal->getStrength(); + } +} diff --git a/src/AIModel/AIManager.hxx b/src/AIModel/AIManager.hxx index 5b0e962b1..537d5145e 100644 --- a/src/AIModel/AIManager.hxx +++ b/src/AIModel/AIManager.hxx @@ -29,6 +29,7 @@ #include "AIBase.hxx" SG_USING_STD(list); +class FGAIThermal; class FGAIManager : public SGSubsystem @@ -53,8 +54,6 @@ private: public: - enum object_type { otAircraft, otShip, otBallistic, otRocket, otStorm, otThermal }; - FGAIManager(); ~FGAIManager(); @@ -120,6 +119,7 @@ private: bool initDone; int numObjects; SGPropertyNode* root; + SGPropertyNode* wind_from_down; double user_latitude; double user_longitude; @@ -128,9 +128,15 @@ private: double user_pitch; double user_yaw; double user_speed; + double _dt; int dt_count; void fetchUserState( void ); + // used by thermals + double range_nearest; + double strength; + void processThermal( FGAIThermal* thermal ); + }; #endif // _FG_AIMANAGER_HXX diff --git a/src/AIModel/AIShip.cxx b/src/AIModel/AIShip.cxx index d9fc379fe..c1d4ce809 100644 --- a/src/AIModel/AIShip.cxx +++ b/src/AIModel/AIShip.cxx @@ -29,9 +29,11 @@ FGAIShip::FGAIShip(FGAIManager* mgr) { manager = mgr; + _type_str = "ship"; + _otype = otShip; + hdg_lock = false; rudder = 0.0; - _type_str = "ship"; } FGAIShip::~FGAIShip() { diff --git a/src/AIModel/AIStorm.cxx b/src/AIModel/AIStorm.cxx index fa09aad79..532a3f106 100644 --- a/src/AIModel/AIStorm.cxx +++ b/src/AIModel/AIStorm.cxx @@ -40,6 +40,7 @@ FGAIStorm::FGAIStorm(FGAIManager* mgr) { manager = mgr; _self = this; _type_str = "thunderstorm"; + _otype = otStorm; } diff --git a/src/AIModel/AIThermal.cxx b/src/AIModel/AIThermal.cxx index 812f5e01e..7ceafcee9 100644 --- a/src/AIModel/AIThermal.cxx +++ b/src/AIModel/AIThermal.cxx @@ -40,8 +40,10 @@ FGAIThermal::FGAIThermal(FGAIManager* mgr) { manager = mgr; _self = this; _type_str = "thermal"; - strength = 6.0; + _otype = otThermal; + max_strength = 6.0; diameter = 0.5; + strength = factor = 0.0; } @@ -51,8 +53,7 @@ FGAIThermal::~FGAIThermal() { bool FGAIThermal::init() { - wind_from_down = fgGetNode("/environment/wind-from-down-fps", true); - scaler = 8.0 * strength / (diameter * diameter * diameter); + factor = 8.0 * max_strength / (diameter * diameter * diameter); return FGAIBase::init(); } @@ -100,13 +101,13 @@ void FGAIThermal::Run(double dt) { double range_ft = sqrt( lat_range*lat_range + lon_range*lon_range ); range = range_ft / 6076.11549; - // Set rising air if within range. + // Calculate speed of rising air if within range. // Air vertical speed is maximum at center of thermal, // and decreases to zero at the edge (as distance cubed). if (range < (diameter * 0.5)) { - wind_from_down->setDoubleValue( strength - (range * range * range * scaler) ); + strength = max_strength - ( range * range * range * factor ); } else { - wind_from_down->setDoubleValue( 0.0 ); + strength = 0.0; } } diff --git a/src/AIModel/AIThermal.hxx b/src/AIModel/AIThermal.hxx index c4eb171d1..1da663ff8 100644 --- a/src/AIModel/AIThermal.hxx +++ b/src/AIModel/AIThermal.hxx @@ -40,8 +40,10 @@ public: virtual void unbind(); void update(double dt); - inline void setStrength( double s ) { strength = s; }; + inline void setMaxStrength( double s ) { max_strength = s; }; inline void setDiameter( double d ) { diameter = d; }; + inline double getStrength() const { return strength; }; + inline double getDiameter() const { return diameter; }; protected: static FGAIThermal *_self; @@ -50,10 +52,10 @@ private: double dt; void Run(double dt); - SGPropertyNode* wind_from_down; + double max_strength; double strength; double diameter; - double scaler; + double factor; };