diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx index 40a6a2d32..e4142d90b 100644 --- a/src/AIModel/AIBase.cxx +++ b/src/AIModel/AIBase.cxx @@ -273,6 +273,8 @@ void FGAIBase::readFromScenario(SGPropertyNode* scFileNode) setLatitude(scFileNode->getDoubleValue("latitude", 0.0)); setBank(scFileNode->getDoubleValue("roll", 0.0)); setPitch(scFileNode->getDoubleValue("pitch", 0.0)); + setCollisionHeight(scFileNode->getDoubleValue("collision-height", 0.0)); + setCollisionLength(scFileNode->getDoubleValue("collision-length", 0.0)); SGPropertyNode* submodels = scFileNode->getChild("submodels"); diff --git a/src/AIModel/AIBase.hxx b/src/AIModel/AIBase.hxx index 167795d8e..13af98939 100644 --- a/src/AIModel/AIBase.hxx +++ b/src/AIModel/AIBase.hxx @@ -138,6 +138,9 @@ public: bool setParentNode(); void setParentName(const std::string& p); + void setCollisionLength(int range); + void setCollisionHeight(int height); + void calcRangeBearing(double lat, double lon, double lat2, double lon2, double &range, double &bearing) const; double calcRelBearingDeg(double bearing, double heading); @@ -167,6 +170,9 @@ public: osg::LOD* getSceneBranch() const; + virtual int getCollisionHeight() const; + virtual int getCollisionLength() const; + /** * * @return true if at least one model (either low_res or high_res) is loaded @@ -190,6 +196,9 @@ protected: double _max_speed = 300.0; + int collisionHeight = 0; + int collisionLength = 0; + std::string _path; std::string _callsign; std::string _submodel; @@ -488,6 +497,14 @@ inline void FGAIBase::setName(const std::string& n) { _name = n; } +inline void FGAIBase::setCollisionLength(int length){ + collisionLength = length; +} + +inline void FGAIBase::setCollisionHeight(int height){ + collisionHeight = height; +} + inline void FGAIBase::setDie( bool die ) { delete_me = die; } inline bool FGAIBase::getDie() { return delete_me; } @@ -525,3 +542,47 @@ inline void FGAIBase::setMaxSpeed(double m) { _max_speed = m; } +/* + * Default height and lengths for AI submodel collision detection. + * The difference in height is used first and then the range must be within + * the value specifed in the length field. This effective chops the top and + * bottom off the circle - but does not take into account the orientation of the + * AI model; so this algorithm is fast but fairly innaccurate. + * + * Default values: + * +---------------+-------------+------------+ + * | Type | Height(m) | Length(m) | + * +---------------+-------------+------------+ + * | Null | 0 | 0 | + * | Aircraft | 50 | 100 | + * | Ship | 100 | 200 | + * | Carrier | 250 | 750 | + * | Ballistic | 0 | 0 | + * | Rocket | 100 | 50 | + * | Storm | 0 | 0 | + * | Thermal | 0 | 0 | + * | Static | 50 | 200 | + * | Wingman | 50 | 100 | + * | GroundVehicle | 20 | 40 | + * | Escort | 100 | 200 | + * | Multiplayer | 50 | 100 | + * +---------------+-------------+------------+ + */ +const static double tgt_ht[] = {0, 50, 100, 250, 0, 100, 0, 0, 50, 50, 20, 100, 50}; +const static double tgt_length[] = {0, 100, 200, 750, 0, 50, 0, 0, 200, 100, 40, 200, 100}; + +inline int FGAIBase::getCollisionHeight() const +{ + if (collisionHeight == 0) + return tgt_ht[static_cast(_otype)]; + + return collisionHeight; +} +inline int FGAIBase::getCollisionLength() const +{ + if (collisionLength == 0) + return tgt_length[static_cast(_otype)]; + + return collisionLength; +} + diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index efb4a33e3..6457e5352 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -708,9 +708,6 @@ FGAIManager::loadScenarioFile(const std::string& scenarioName, SGPath& outPath) const FGAIBase * FGAIManager::calcCollision(double alt, double lat, double lon, double fuse_range) { - // we specify tgt extent (ft) according to the AIObject type - double tgt_ht[] = {0, 50, 100, 250, 0, 100, 0, 0, 50, 50, 20, 100, 50}; - double tgt_length[] = {0, 100, 200, 750, 0, 50, 0, 0, 200, 100, 40, 200, 100}; ai_list_iterator ai_list_itr = ai_list.begin(); ai_list_iterator end = ai_list.end(); @@ -718,11 +715,12 @@ FGAIManager::calcCollision(double alt, double lat, double lon, double fuse_range SGVec3d cartPos(SGVec3d::fromGeod(pos)); while (ai_list_itr != end) { - double tgt_alt = (*ai_list_itr)->_getAltitude(); - FGAIBase::object_type type = (*ai_list_itr)->getType(); - tgt_ht[static_cast(type)] += fuse_range; + FGAIBasePtr aiModel = *ai_list_itr; + FGAIBase::object_type type = aiModel->getType(); + double tgt_alt = aiModel->_getAltitude(); + int tgt_ht = aiModel->getCollisionHeight() + fuse_range; - if (fabs(tgt_alt - alt) > tgt_ht[static_cast(type)] || type == FGAIBase::object_type::otBallistic + if (fabs(tgt_alt - alt) > tgt_ht || type == FGAIBase::object_type::otBallistic || type == FGAIBase::object_type::otStorm || type == FGAIBase::object_type::otThermal ) { //SG_LOG(SG_AI, SG_DEBUG, "AIManager: skipping " // << fabs(tgt_alt - alt) @@ -746,16 +744,17 @@ FGAIManager::calcCollision(double alt, double lat, double lon, double fuse_range // << " alt " << tgt_alt // ); - tgt_length[static_cast(type)] += fuse_range; + int tgt_length = aiModel->getCollisionLength() + fuse_range; - if (range < tgt_length[static_cast(type)]){ + if (range < tgt_length){ SG_LOG(SG_AI, SG_DEBUG, "AIManager: HIT! " + << " (h:" << tgt_ht << ", w:" << tgt_length << ")" << " type " << static_cast(type) << " ID " << id << " range " << range << " alt " << tgt_alt ); - return (*ai_list_itr).get(); + return aiModel.get(); } ++ai_list_itr; }