diff --git a/CHANGELOG.md b/CHANGELOG.md index e11d05d3d..ce01b7293 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,6 @@ Bug #2069: Fireflies in Fireflies invade Morrowind look wrong Bug #2311: Targeted scripts are not properly supported on non-unique RefIDs Bug #2473: Unable to overstock merchants - Bug #2798: Mutable ESM records Bug #2976: [reopened]: Issues combining settings from the command line and both config files Bug #3137: Walking into a wall prevents jumping Bug #3372: Projectiles and magic bolts go through moving targets @@ -20,7 +19,6 @@ Bug #4039: Multiple followers should have the same following distance Bug #4055: Local scripts don't inherit variables from their base record Bug #4083: Door animation freezes when colliding with actors - Bug #4201: Projectile-projectile collision Bug #4247: Cannot walk up stairs in Ebonheart docks Bug #4357: OpenMW-CS: TopicInfos index sorting and rearranging isn't fully functional Bug #4363: OpenMW-CS: Defect in Clone Function for Dialogue Info records @@ -89,7 +87,7 @@ Bug #5644: Summon effects running on the player during game initialization cause crashes Bug #5656: Sneaking characters block hits while standing Bug #5661: Region sounds don't play at the right interval - Bug #5675: OpenMW-cs. FRMR subrecords are saved with the wrong MastIdx + Bug #5675: OpenMW-CS: FRMR subrecords are saved with the wrong MastIdx Bug #5680: Bull Netches incorrectly aim over the player character's head and always miss Bug #5681: Player character can clip or pass through bridges instead of colliding against them Bug #5687: Bound items covering the same inventory slot expiring at the same time freezes the game @@ -102,7 +100,7 @@ Bug #5739: Saving and loading the save a second or two before hitting the ground doesn't count fall damage Bug #5758: Paralyzed actors behavior is inconsistent with vanilla Bug #5762: Movement solver is insufficiently robust - BUG #5800: Equipping a CE enchanted ring deselects an already equipped and selected enchanted ring from the spell menu + Bug #5800: Equipping a CE enchanted ring deselects an already equipped and selected enchanted ring from the spell menu Bug #5807: Video decoding crash on ARM Bug #5821: NPCs from mods getting removed if mod order was changed Bug #5835: OpenMW doesn't accept negative values for NPC's hello, alarm, fight, and flee @@ -135,11 +133,15 @@ Feature #390: 3rd person look "over the shoulder" Feature #832: OpenMW-CS: Handle deleted references Feature #1536: Show more information about level on menu + Feature #2159: "Graying out" exhausted dialogue topics Feature #2386: Distant Statics in the form of Object Paging Feature #2404: Levelled List can not be placed into a container Feature #2686: Timestamps in openmw.log + Feature #2798: Mutable ESM records Feature #3171: OpenMW-CS: Instance drag selection Feature #3983: Wizard: Add link to buy Morrowind + Feature #4201: Projectile-projectile collision + Feature #4486: Handle crashes on Windows Feature #4894: Consider actors as obstacles for pathfinding Feature #4899: Alpha-To-Coverage Anti-Aliasing for alpha testing Feature #4917: Do not trigger NavMesh update when RecastMesh update should not change NavMesh @@ -176,7 +178,6 @@ Feature #6034: Find path based on area cost depending on NPC stats Task #5480: Drop Qt4 support Task #5520: Improve cell name autocompleter implementation - Task #5844: Update 'toggle sneak' documentation 0.46.0 ------ @@ -186,7 +187,7 @@ Bug #2395: Duplicated plugins in the launcher when multiple data directories provide the same plugin Bug #2679: Unable to map mouse wheel under control settings Bug #2969: Scripted items can stack - Bug #2976: Data lines in global openmw.cfg take priority over user openmw.cfg + Bug #2976: [reopened in 0.47] Data lines in global openmw.cfg take priority over user openmw.cfg Bug #2987: Editor: some chance and AI data fields can overflow Bug #3006: 'else if' operator breaks script compilation Bug #3109: SetPos/Position handles actors differently @@ -204,7 +205,6 @@ Bug #4009: Launcher does not show data files on the first run after installing Bug #4077: Enchanted items are not recharged if they are not in the player's inventory Bug #4141: PCSkipEquip isn't set to 1 when reading books/scrolls - Bug #4202: Open .omwaddon files without needing toopen openmw-cs first Bug #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect Bug #4262: Rain settings are hardcoded Bug #4270: Closing doors while they are obstructed desyncs closing sfx @@ -294,7 +294,6 @@ Bug #4964: Multiple effect spell projectile sounds play louder than vanilla Bug #4965: Global light attenuation settings setup is lacking Bug #4969: "Miss" sound plays for any actor - Bug #4971: OpenMW-CS: Make rotations display as degrees instead of radians Bug #4972: Player is able to use quickkeys while disableplayerfighting is active Bug #4979: AiTravel maximum range depends on "actors processing range" setting Bug #4980: Drowning mechanics is applied for actors indifferently from distance to player @@ -392,7 +391,6 @@ Bug #5350: An attempt to launch magic bolt causes "AL error invalid value" error Bug #5352: Light source items' duration is decremented while they aren't visible Feature #1724: Handle AvoidNode - Feature #2159: "Graying out" exhausted dialogue topics Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls Feature #3442: Default values for fallbacks from ini file @@ -405,6 +403,7 @@ Feature #4001: Toggle sneak controller shortcut Feature #4068: OpenMW-CS: Add a button to reset key bindings to defaults Feature #4129: Beta Comment to File + Feature #4202: Open .omwaddon files without needing to open openmw-cs first Feature #4209: Editor: Faction rank sub-table Feature #4255: Handle broken RepairedOnMe script function Feature #4316: Implement RaiseRank/LowerRank functions properly @@ -427,6 +426,7 @@ Feature #4958: Support eight blood types Feature #4962: Add casting animations for magic items Feature #4968: Scalable UI widget skins + Feature #4971: OpenMW-CS: Make rotations display as degrees instead of radians Feature #4994: Persistent pinnable windows hiding Feature #5000: Compressed BSA format support Feature #5005: Editor: Instance window via Scene window diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index ed36634b6..bddb70aa0 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -136,6 +136,7 @@ bool Launcher::AdvancedPage::loadSettings() loadSettingBool(activeGridObjectPagingCheckBox, "object paging active grid", "Terrain"); viewingDistanceComboBox->setValue(convertToCells(Settings::Manager::getInt("viewing distance", "Camera"))); + objectPagingMinSizeComboBox->setValue(Settings::Manager::getDouble("object paging min size", "Terrain")); } // Audio @@ -287,6 +288,9 @@ void Launcher::AdvancedPage::saveSettings() { Settings::Manager::setInt("viewing distance", "Camera", convertToUnits(viewingDistance)); } + double objectPagingMinSize = objectPagingMinSizeComboBox->value(); + if (objectPagingMinSize != Settings::Manager::getDouble("object paging min size", "Terrain")) + Settings::Manager::setDouble("object paging min size", "Terrain", objectPagingMinSize); } // Audio diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index b3fc6f104..f61f246e9 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -144,12 +144,14 @@ namespace MWClass MWBase::Environment::get().getWorld()->getMaxActivationDistance()) { MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr); + if(animation) + { + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + int index = ESM::MagicEffect::effectStringToId("sEffectTelekinesis"); + const ESM::MagicEffect *effect = store.get().find(index); - const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - int index = ESM::MagicEffect::effectStringToId("sEffectTelekinesis"); - const ESM::MagicEffect *effect = store.get().find(index); - - animation->addSpellCastGlow(effect, 1); // 1 second glow to match the time taken for a door opening or closing + animation->addSpellCastGlow(effect, 1); // 1 second glow to match the time taken for a door opening or closing + } } const std::string keyId = ptr.getCellRef().getKey(); diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 0701f42cf..523949179 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -160,7 +160,8 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& static const bool smoothMovement = Settings::Manager::getBool("smooth movement", "Game"); mPathFinder.update(position, pointTolerance, DEFAULT_TOLERANCE, - /*shortenIfAlmostStraight=*/smoothMovement, actorCanMoveByZ); + /*shortenIfAlmostStraight=*/smoothMovement, actorCanMoveByZ, + halfExtents, getNavigatorFlags(actor)); if (isDestReached || mPathFinder.checkPathCompleted()) // if path is finished { @@ -476,6 +477,6 @@ osg::Vec3f MWMechanics::AiPackage::getNextPathPoint(const osg::Vec3f& destinatio float MWMechanics::AiPackage::getNextPathPointTolerance(float speed, float duration, const osg::Vec3f& halfExtents) const { if (mPathFinder.getPathSize() <= 1) - return mLastDestinationTolerance; + return std::max(DEFAULT_TOLERANCE, mLastDestinationTolerance); return getPointTolerance(speed, duration, halfExtents); } diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 3f113802f..2f8e83043 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -105,6 +105,19 @@ namespace return checkAngle && checkDist; } + + struct IsValidShortcut + { + const DetourNavigator::Navigator* mNavigator; + const osg::Vec3f mHalfExtents; + const DetourNavigator::Flags mFlags; + + bool operator()(const osg::Vec3f& start, const osg::Vec3f& end) const + { + const auto position = mNavigator->raycast(mHalfExtents, start, end, mFlags); + return position.has_value() && std::abs((position.value() - start).length2() - (end - start).length2()) <= 1; + } + }; } namespace MWMechanics @@ -296,7 +309,8 @@ namespace MWMechanics } void PathFinder::update(const osg::Vec3f& position, float pointTolerance, float destinationTolerance, - bool shortenIfAlmostStraight, bool canMoveByZ) + bool shortenIfAlmostStraight, bool canMoveByZ, const osg::Vec3f& halfExtents, + const DetourNavigator::Flags flags) { if (mPath.empty()) return; @@ -306,9 +320,15 @@ namespace MWMechanics if (shortenIfAlmostStraight) { - while (mPath.size() > 2 && isAlmostStraight(mPath[0], mPath[1], mPath[2], pointTolerance)) + const IsValidShortcut isValidShortcut { + MWBase::Environment::get().getWorld()->getNavigator(), + halfExtents, flags + }; + while (mPath.size() > 2 && isAlmostStraight(mPath[0], mPath[1], mPath[2], pointTolerance) + && isValidShortcut(mPath[0], mPath[2])) mPath.erase(mPath.begin() + 1); - if (mPath.size() > 1 && isAlmostStraight(position, mPath[0], mPath[1], pointTolerance)) + if (mPath.size() > 1 && isAlmostStraight(position, mPath[0], mPath[1], pointTolerance) + && isValidShortcut(position, mPath[1])) mPath.pop_front(); } @@ -349,7 +369,13 @@ namespace MWMechanics mPath.clear(); // If it's not possible to build path over navmesh due to disabled navmesh generation fallback to straight path - if (!buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath))) + DetourNavigator::Status status = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, + areaCosts, std::back_inserter(mPath)); + + if (status != DetourNavigator::Status::Success) + mPath.clear(); + + if (status == DetourNavigator::Status::NavMeshNotFound) mPath.push_back(endPoint); mConstructed = !mPath.empty(); @@ -362,25 +388,33 @@ namespace MWMechanics mPath.clear(); mCell = cell; - bool hasNavMesh = false; + DetourNavigator::Status status = DetourNavigator::Status::NavMeshNotFound; if (!actor.getClass().isPureWaterCreature(actor) && !actor.getClass().isPureFlyingCreature(actor)) - hasNavMesh = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath)); + { + status = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath)); + if (status != DetourNavigator::Status::Success) + mPath.clear(); + } - if (hasNavMesh && mPath.empty()) - buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, + if (status != DetourNavigator::Status::NavMeshNotFound && mPath.empty()) + { + status = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags | DetourNavigator::Flag_usePathgrid, areaCosts, std::back_inserter(mPath)); + if (status != DetourNavigator::Status::Success) + mPath.clear(); + } if (mPath.empty()) buildPathByPathgridImpl(startPoint, endPoint, pathgridGraph, std::back_inserter(mPath)); - if (!hasNavMesh && mPath.empty()) + if (status == DetourNavigator::Status::NavMeshNotFound && mPath.empty()) mPath.push_back(endPoint); mConstructed = !mPath.empty(); } - bool PathFinder::buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, + DetourNavigator::Status PathFinder::buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator> out) { @@ -389,9 +423,6 @@ namespace MWMechanics const auto navigator = world->getNavigator(); const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, areaCosts, out); - if (status == DetourNavigator::Status::NavMeshNotFound) - return false; - if (status != DetourNavigator::Status::Success) { Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status) @@ -400,7 +431,7 @@ namespace MWMechanics << DetourNavigator::WriteFlags {flags} << ")"; } - return true; + return status; } void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents, diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index ed88a57ca..0d281d1e2 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -107,7 +108,8 @@ namespace MWMechanics /// Remove front point if exist and within tolerance void update(const osg::Vec3f& position, float pointTolerance, float destinationTolerance, - bool shortenIfAlmostStraight, bool canMoveByZ); + bool shortenIfAlmostStraight, bool canMoveByZ, const osg::Vec3f& halfExtents, + const DetourNavigator::Flags flags); bool checkPathCompleted() const { @@ -208,9 +210,10 @@ namespace MWMechanics void buildPathByPathgridImpl(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const PathgridGraph& pathgridGraph, std::back_insert_iterator> out); - bool buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, - const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags, - const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator> out); + [[nodiscard]] DetourNavigator::Status buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, + const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, + const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts, + std::back_insert_iterator> out); }; } diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index ec36a5cdf..0a9641635 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -221,7 +221,7 @@ void FFmpeg_Decoder::open(const std::string &fname) if(!mStream) throw std::runtime_error("No audio streams in "+fname); - AVCodec *codec = avcodec_find_decoder((*mStream)->codecpar->codec_id); + const AVCodec *codec = avcodec_find_decoder((*mStream)->codecpar->codec_id); if(!codec) { std::string ss = "No codec found for id " + diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f701acfef..e11ae9407 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2829,7 +2829,14 @@ namespace MWWorld MWRender::Animation* World::getAnimation(const MWWorld::Ptr &ptr) { - return mRendering->getAnimation(ptr); + auto* animation = mRendering->getAnimation(ptr); + if(!animation) { + mWorldScene->removeFromPagedRefs(ptr); + animation = mRendering->getAnimation(ptr); + if(animation) + mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr); + } + return animation; } const MWRender::Animation* World::getAnimation(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index bf8b4a002..b0fec1a1a 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -42,8 +42,8 @@ namespace DetourNavigatorNavigatorTest() : mPlayerPosition(0, 0, 0) , mAgentHalfExtents(29, 29, 66) - , mStart(-215, 215, 1) - , mEnd(215, -215, 1) + , mStart(-204, 204, 1) + , mEnd(204, -204, 1) , mOut(mPath) , mStepSize(28.333332061767578125f) { @@ -133,30 +133,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.85963428020477294921875), - Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), - Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), - Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), - Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), - Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), - Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), - Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), - Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), - Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), - Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), - Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), - Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), - Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), - Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), - Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), - Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), - Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), - Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), - Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), - Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), - Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), - Vec3fEq(215, -215, 1.87718021869659423828125) - )); + Vec3fEq(-204.0000152587890625, 204, 1.99998295307159423828125), + Vec3fEq(-183.96533203125, 183.9653167724609375, 1.99998819828033447265625), + Vec3fEq(-163.930633544921875, 163.9306182861328125, 1.99999344348907470703125), + Vec3fEq(-143.8959503173828125, 143.89593505859375, -2.720611572265625), + Vec3fEq(-123.86126708984375, 123.86124420166015625, -13.1089687347412109375), + Vec3fEq(-103.82657623291015625, 103.8265533447265625, -23.497333526611328125), + Vec3fEq(-83.7918853759765625, 83.7918548583984375, -33.885692596435546875), + Vec3fEq(-63.757190704345703125, 63.757171630859375, -44.274051666259765625), + Vec3fEq(-43.722503662109375, 43.72248077392578125, -54.66241455078125), + Vec3fEq(-23.687808990478515625, 23.6877918243408203125, -65.05077362060546875), + Vec3fEq(-3.6531188488006591796875, 3.6531002521514892578125, -75.43914031982421875), + Vec3fEq(16.3815746307373046875, -16.381591796875, -69.74927520751953125), + Vec3fEq(36.416263580322265625, -36.416286468505859375, -60.4739532470703125), + Vec3fEq(56.450958251953125, -56.450977325439453125, -51.1986236572265625), + Vec3fEq(76.48564910888671875, -76.4856719970703125, -41.92330169677734375), + Vec3fEq(96.5203399658203125, -96.52036285400390625, -31.46941375732421875), + Vec3fEq(116.55503082275390625, -116.5550537109375, -19.597003936767578125), + Vec3fEq(136.5897216796875, -136.5897369384765625, -7.724592685699462890625), + Vec3fEq(156.624420166015625, -156.624420166015625, 1.99999535083770751953125), + Vec3fEq(176.6591033935546875, -176.65911865234375, 1.99999010562896728515625), + Vec3fEq(196.69378662109375, -196.6938018798828125, 1.99998486042022705078125), + Vec3fEq(204, -204.0000152587890625, 1.99998295307159423828125) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, add_object_should_change_navmesh) @@ -183,30 +182,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.85963428020477294921875), - Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), - Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), - Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), - Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), - Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), - Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), - Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), - Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), - Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), - Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), - Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), - Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), - Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), - Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), - Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), - Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), - Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), - Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), - Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), - Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), - Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), - Vec3fEq(215, -215, 1.87718021869659423828125) - )); + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-183.965301513671875, 183.965301513671875, 1.99998819828033447265625), + Vec3fEq(-163.9306182861328125, 163.9306182861328125, 1.99999344348907470703125), + Vec3fEq(-143.89593505859375, 143.89593505859375, -2.7206256389617919921875), + Vec3fEq(-123.86124420166015625, 123.86124420166015625, -13.1089839935302734375), + Vec3fEq(-103.8265533447265625, 103.8265533447265625, -23.4973468780517578125), + Vec3fEq(-83.7918548583984375, 83.7918548583984375, -33.885707855224609375), + Vec3fEq(-63.75716400146484375, 63.75716400146484375, -44.27407073974609375), + Vec3fEq(-43.72247314453125, 43.72247314453125, -54.662433624267578125), + Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -65.0507965087890625), + Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -75.43915557861328125), + Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -69.749267578125), + Vec3fEq(36.416290283203125, -36.416290283203125, -60.4739532470703125), + Vec3fEq(56.450984954833984375, -56.450984954833984375, -51.1986236572265625), + Vec3fEq(76.4856719970703125, -76.4856719970703125, -41.92330169677734375), + Vec3fEq(96.52036285400390625, -96.52036285400390625, -31.46941375732421875), + Vec3fEq(116.5550537109375, -116.5550537109375, -19.597003936767578125), + Vec3fEq(136.5897369384765625, -136.5897369384765625, -7.724592685699462890625), + Vec3fEq(156.6244354248046875, -156.6244354248046875, 1.99999535083770751953125), + Vec3fEq(176.6591339111328125, -176.6591339111328125, 1.99999010562896728515625), + Vec3fEq(196.693817138671875, -196.693817138671875, 1.99998486042022705078125), + Vec3fEq(204, -204, 1.99998295307159423828125) + )) << mPath; mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); @@ -217,30 +215,30 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.87826788425445556640625), - Vec3fEq(-199.7968292236328125, 191.09100341796875, -3.54876613616943359375), - Vec3fEq(-184.5936431884765625, 167.1819915771484375, -8.97847843170166015625), - Vec3fEq(-169.3904571533203125, 143.2729949951171875, -14.408184051513671875), - Vec3fEq(-154.1872711181640625, 119.36397552490234375, -19.837890625), - Vec3fEq(-138.9840850830078125, 95.45496368408203125, -25.2675991058349609375), - Vec3fEq(-123.78090667724609375, 71.54595184326171875, -30.6973056793212890625), - Vec3fEq(-108.57772064208984375, 47.636936187744140625, -36.12701416015625), - Vec3fEq(-93.3745269775390625, 23.7279262542724609375, -40.754688262939453125), - Vec3fEq(-78.17134857177734375, -0.18108306825160980224609375, -37.128787994384765625), - Vec3fEq(-62.968158721923828125, -24.0900936126708984375, -33.50289154052734375), - Vec3fEq(-47.764972686767578125, -47.999103546142578125, -30.797946929931640625), - Vec3fEq(-23.852447509765625, -63.196765899658203125, -33.97112274169921875), - Vec3fEq(0.0600789971649646759033203125, -78.39443206787109375, -37.14543914794921875), - Vec3fEq(23.97260284423828125, -93.5920867919921875, -40.774089813232421875), - Vec3fEq(47.885128021240234375, -108.78974151611328125, -36.05129241943359375), - Vec3fEq(71.7976531982421875, -123.98740386962890625, -30.6235561370849609375), - Vec3fEq(95.71018218994140625, -139.18505859375, -25.1958255767822265625), - Vec3fEq(119.6226959228515625, -154.382720947265625, -19.7680912017822265625), - Vec3fEq(143.53521728515625, -169.58038330078125, -14.34035205841064453125), - Vec3fEq(167.4477386474609375, -184.778045654296875, -8.9126186370849609375), - Vec3fEq(191.360260009765625, -199.9757080078125, -3.4848802089691162109375), - Vec3fEq(215, -215, 1.87826788425445556640625) - )); + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-189.9427337646484375, 179.3997802734375, -3.622931003570556640625), + Vec3fEq(-175.8854522705078125, 154.7995452880859375, -9.24583911895751953125), + Vec3fEq(-161.82818603515625, 130.1993255615234375, -14.86874866485595703125), + Vec3fEq(-147.770904541015625, 105.5991058349609375, -20.4916591644287109375), + Vec3fEq(-133.7136383056640625, 80.99887847900390625, -26.1145648956298828125), + Vec3fEq(-119.65636444091796875, 56.39865875244140625, -31.7374725341796875), + Vec3fEq(-105.59909820556640625, 31.798435211181640625, -26.133396148681640625), + Vec3fEq(-91.54183197021484375, 7.1982135772705078125, -31.5624217987060546875), + Vec3fEq(-77.48455810546875, -17.402008056640625, -26.98972320556640625), + Vec3fEq(-63.427295684814453125, -42.00223541259765625, -19.9045581817626953125), + Vec3fEq(-42.193531036376953125, -60.761363983154296875, -20.4544773101806640625), + Vec3fEq(-20.9597682952880859375, -79.5204925537109375, -23.599918365478515625), + Vec3fEq(3.8312885761260986328125, -93.2384033203125, -30.7141361236572265625), + Vec3fEq(28.6223468780517578125, -106.95632171630859375, -24.8243885040283203125), + Vec3fEq(53.413402557373046875, -120.6742401123046875, -31.3303241729736328125), + Vec3fEq(78.20446014404296875, -134.39215087890625, -25.8431549072265625), + Vec3fEq(102.99552154541015625, -148.110076904296875, -20.3559894561767578125), + Vec3fEq(127.7865753173828125, -161.827972412109375, -14.868824005126953125), + Vec3fEq(152.57763671875, -175.5458984375, -9.3816623687744140625), + Vec3fEq(177.3686981201171875, -189.2638092041015625, -3.894496917724609375), + Vec3fEq(202.1597442626953125, -202.9817047119140625, 1.59266507625579833984375), + Vec3fEq(204, -204, 1.99998295307159423828125) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, update_changed_object_should_change_navmesh) @@ -268,30 +266,30 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.87826788425445556640625), - Vec3fEq(-199.7968292236328125, 191.09100341796875, -3.54876613616943359375), - Vec3fEq(-184.5936431884765625, 167.1819915771484375, -8.97847843170166015625), - Vec3fEq(-169.3904571533203125, 143.2729949951171875, -14.408184051513671875), - Vec3fEq(-154.1872711181640625, 119.36397552490234375, -19.837890625), - Vec3fEq(-138.9840850830078125, 95.45496368408203125, -25.2675991058349609375), - Vec3fEq(-123.78090667724609375, 71.54595184326171875, -30.6973056793212890625), - Vec3fEq(-108.57772064208984375, 47.636936187744140625, -36.12701416015625), - Vec3fEq(-93.3745269775390625, 23.7279262542724609375, -40.754688262939453125), - Vec3fEq(-78.17134857177734375, -0.18108306825160980224609375, -37.128787994384765625), - Vec3fEq(-62.968158721923828125, -24.0900936126708984375, -33.50289154052734375), - Vec3fEq(-47.764972686767578125, -47.999103546142578125, -30.797946929931640625), - Vec3fEq(-23.852447509765625, -63.196765899658203125, -33.97112274169921875), - Vec3fEq(0.0600789971649646759033203125, -78.39443206787109375, -37.14543914794921875), - Vec3fEq(23.97260284423828125, -93.5920867919921875, -40.774089813232421875), - Vec3fEq(47.885128021240234375, -108.78974151611328125, -36.05129241943359375), - Vec3fEq(71.7976531982421875, -123.98740386962890625, -30.6235561370849609375), - Vec3fEq(95.71018218994140625, -139.18505859375, -25.1958255767822265625), - Vec3fEq(119.6226959228515625, -154.382720947265625, -19.7680912017822265625), - Vec3fEq(143.53521728515625, -169.58038330078125, -14.34035205841064453125), - Vec3fEq(167.4477386474609375, -184.778045654296875, -8.9126186370849609375), - Vec3fEq(191.360260009765625, -199.9757080078125, -3.4848802089691162109375), - Vec3fEq(215, -215, 1.87826788425445556640625) - )); + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-189.9427337646484375, 179.3997802734375, -3.622931003570556640625), + Vec3fEq(-175.8854522705078125, 154.7995452880859375, -9.24583911895751953125), + Vec3fEq(-161.82818603515625, 130.1993255615234375, -14.86874866485595703125), + Vec3fEq(-147.770904541015625, 105.5991058349609375, -20.4916591644287109375), + Vec3fEq(-133.7136383056640625, 80.99887847900390625, -26.1145648956298828125), + Vec3fEq(-119.65636444091796875, 56.39865875244140625, -31.7374725341796875), + Vec3fEq(-105.59909820556640625, 31.798435211181640625, -26.133396148681640625), + Vec3fEq(-91.54183197021484375, 7.1982135772705078125, -31.5624217987060546875), + Vec3fEq(-77.48455810546875, -17.402008056640625, -26.98972320556640625), + Vec3fEq(-63.427295684814453125, -42.00223541259765625, -19.9045581817626953125), + Vec3fEq(-42.193531036376953125, -60.761363983154296875, -20.4544773101806640625), + Vec3fEq(-20.9597682952880859375, -79.5204925537109375, -23.599918365478515625), + Vec3fEq(3.8312885761260986328125, -93.2384033203125, -30.7141361236572265625), + Vec3fEq(28.6223468780517578125, -106.95632171630859375, -24.8243885040283203125), + Vec3fEq(53.413402557373046875, -120.6742401123046875, -31.3303241729736328125), + Vec3fEq(78.20446014404296875, -134.39215087890625, -25.8431549072265625), + Vec3fEq(102.99552154541015625, -148.110076904296875, -20.3559894561767578125), + Vec3fEq(127.7865753173828125, -161.827972412109375, -14.868824005126953125), + Vec3fEq(152.57763671875, -175.5458984375, -9.3816623687744140625), + Vec3fEq(177.3686981201171875, -189.2638092041015625, -3.894496917724609375), + Vec3fEq(202.1597442626953125, -202.9817047119140625, 1.59266507625579833984375), + Vec3fEq(204, -204, 1.99998295307159423828125) + )) << mPath; compoundShape.updateChildTransform(0, btTransform(btMatrix3x3::getIdentity(), btVector3(1000, 0, 0))); @@ -304,30 +302,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.85963428020477294921875), - Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), - Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), - Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), - Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), - Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), - Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), - Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), - Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), - Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), - Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), - Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), - Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), - Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), - Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), - Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), - Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), - Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), - Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), - Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), - Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), - Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), - Vec3fEq(215, -215, 1.87718021869659423828125) - )); + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-183.965301513671875, 183.965301513671875, 1.99998819828033447265625), + Vec3fEq(-163.9306182861328125, 163.9306182861328125, 1.99999344348907470703125), + Vec3fEq(-143.89593505859375, 143.89593505859375, -2.7206256389617919921875), + Vec3fEq(-123.86124420166015625, 123.86124420166015625, -13.1089839935302734375), + Vec3fEq(-103.8265533447265625, 103.8265533447265625, -23.4973468780517578125), + Vec3fEq(-83.7918548583984375, 83.7918548583984375, -33.885707855224609375), + Vec3fEq(-63.75716400146484375, 63.75716400146484375, -44.27407073974609375), + Vec3fEq(-43.72247314453125, 43.72247314453125, -54.662433624267578125), + Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -65.0507965087890625), + Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -75.43915557861328125), + Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -69.749267578125), + Vec3fEq(36.416290283203125, -36.416290283203125, -60.4739532470703125), + Vec3fEq(56.450984954833984375, -56.450984954833984375, -51.1986236572265625), + Vec3fEq(76.4856719970703125, -76.4856719970703125, -41.92330169677734375), + Vec3fEq(96.52036285400390625, -96.52036285400390625, -31.46941375732421875), + Vec3fEq(116.5550537109375, -116.5550537109375, -19.597003936767578125), + Vec3fEq(136.5897369384765625, -136.5897369384765625, -7.724592685699462890625), + Vec3fEq(156.6244354248046875, -156.6244354248046875, 1.99999535083770751953125), + Vec3fEq(176.6591339111328125, -176.6591339111328125, 1.99999010562896728515625), + Vec3fEq(196.693817138671875, -196.693817138671875, 1.99998486042022705078125), + Vec3fEq(204, -204, 1.99998295307159423828125) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, for_overlapping_heightfields_should_use_higher) @@ -361,30 +358,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.96328866481781005859375), - Vec3fEq(-194.9653167724609375, 194.9653167724609375, -0.242215454578399658203125), - Vec3fEq(-174.930633544921875, 174.930633544921875, -2.447719097137451171875), - Vec3fEq(-154.8959503173828125, 154.8959503173828125, -4.65322399139404296875), - Vec3fEq(-134.86126708984375, 134.86126708984375, -6.858726978302001953125), - Vec3fEq(-114.82657623291015625, 114.82657623291015625, -9.06423282623291015625), - Vec3fEq(-94.7918853759765625, 94.7918853759765625, -11.26973628997802734375), - Vec3fEq(-74.75719451904296875, 74.75719451904296875, -13.26497173309326171875), - Vec3fEq(-54.722499847412109375, 54.722499847412109375, -15.24860477447509765625), - Vec3fEq(-34.68780517578125, 34.68780517578125, -17.23223876953125), - Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -19.215869903564453125), - Vec3fEq(5.3815765380859375, -5.3815765380859375, -20.1338443756103515625), - Vec3fEq(25.41626739501953125, -25.41626739501953125, -18.1502132415771484375), - Vec3fEq(45.450958251953125, -45.450958251953125, -16.1665802001953125), - Vec3fEq(65.48564910888671875, -65.48564910888671875, -14.18294620513916015625), - Vec3fEq(85.5203399658203125, -85.5203399658203125, -12.199314117431640625), - Vec3fEq(105.55503082275390625, -105.55503082275390625, -10.08488368988037109375), - Vec3fEq(125.5897216796875, -125.5897216796875, -7.87938022613525390625), - Vec3fEq(145.6244049072265625, -145.6244049072265625, -5.673875331878662109375), - Vec3fEq(165.659088134765625, -165.659088134765625, -3.468370914459228515625), - Vec3fEq(185.6937713623046875, -185.6937713623046875, -1.26286637783050537109375), - Vec3fEq(205.7284698486328125, -205.7284698486328125, 0.942641556262969970703125), - Vec3fEq(215, -215, 1.96328866481781005859375) - )); + Vec3fEq(-204, 204, 1.999981403350830078125), + Vec3fEq(-183.965301513671875, 183.965301513671875, -0.428465187549591064453125), + Vec3fEq(-163.9306182861328125, 163.9306182861328125, -2.8569104671478271484375), + Vec3fEq(-143.89593505859375, 143.89593505859375, -5.28535556793212890625), + Vec3fEq(-123.86124420166015625, 123.86124420166015625, -7.7138004302978515625), + Vec3fEq(-103.8265533447265625, 103.8265533447265625, -10.142246246337890625), + Vec3fEq(-83.7918548583984375, 83.7918548583984375, -12.3704509735107421875), + Vec3fEq(-63.75716400146484375, 63.75716400146484375, -14.354084014892578125), + Vec3fEq(-43.72247314453125, 43.72247314453125, -16.3377170562744140625), + Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -18.32135009765625), + Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -20.3049831390380859375), + Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -19.044734954833984375), + Vec3fEq(36.416290283203125, -36.416290283203125, -17.061100006103515625), + Vec3fEq(56.450984954833984375, -56.450984954833984375, -15.0774688720703125), + Vec3fEq(76.4856719970703125, -76.4856719970703125, -13.0938358306884765625), + Vec3fEq(96.52036285400390625, -96.52036285400390625, -11.02784252166748046875), + Vec3fEq(116.5550537109375, -116.5550537109375, -8.5993976593017578125), + Vec3fEq(136.5897369384765625, -136.5897369384765625, -6.170953273773193359375), + Vec3fEq(156.6244354248046875, -156.6244354248046875, -3.74250507354736328125), + Vec3fEq(176.6591339111328125, -176.6591339111328125, -1.314060688018798828125), + Vec3fEq(196.693817138671875, -196.693817138671875, 1.1143856048583984375), + Vec3fEq(204, -204, 1.9999811649322509765625) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, path_should_be_around_avoid_shape) @@ -417,31 +413,30 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.9393787384033203125), - Vec3fEq(-200.8159637451171875, 190.47265625, -0.639537751674652099609375), - Vec3fEq(-186.6319427490234375, 165.9453125, -3.2184507846832275390625), - Vec3fEq(-172.447906494140625, 141.41796875, -5.797363758087158203125), - Vec3fEq(-158.263885498046875, 116.8906097412109375, -8.37627696990966796875), - Vec3fEq(-144.079864501953125, 92.3632659912109375, -10.9551906585693359375), - Vec3fEq(-129.89581298828125, 67.83591461181640625, -13.53410625457763671875), - Vec3fEq(-115.7117919921875, 43.308563232421875, -16.1130199432373046875), - Vec3fEq(-101.5277557373046875, 18.7812137603759765625, -18.6919345855712890625), - Vec3fEq(-87.34372711181640625, -5.7461376190185546875, -20.4680538177490234375), - Vec3fEq(-67.02922821044921875, -25.4970550537109375, -20.514247894287109375), - Vec3fEq(-46.714717864990234375, -45.2479705810546875, -20.560443878173828125), - Vec3fEq(-26.40021514892578125, -64.99889373779296875, -20.6066417694091796875), - Vec3fEq(-6.085712432861328125, -84.74980926513671875, -20.652835845947265625), - Vec3fEq(14.22879505157470703125, -104.50072479248046875, -18.151397705078125), - Vec3fEq(39.05098724365234375, -118.16222381591796875, -15.66748714447021484375), - Vec3fEq(63.87317657470703125, -131.82373046875, -13.18358135223388671875), - Vec3fEq(88.69537353515625, -145.4852142333984375, -10.699672698974609375), - Vec3fEq(113.51757049560546875, -159.146697998046875, -8.21576786041259765625), - Vec3fEq(138.3397674560546875, -172.808197021484375, -5.731859683990478515625), - Vec3fEq(163.1619720458984375, -186.469696044921875, -3.2479507923126220703125), - Vec3fEq(187.984161376953125, -200.1311798095703125, -0.764044821262359619140625), - Vec3fEq(212.8063507080078125, -213.7926788330078125, 1.719865322113037109375), - Vec3fEq(215, -215, 1.9393787384033203125) - )); + Vec3fEq(-204, 204, 1.99997997283935546875), + Vec3fEq(-191.328948974609375, 178.65789794921875, -0.815807759761810302734375), + Vec3fEq(-178.65789794921875, 153.3157806396484375, -3.6315968036651611328125), + Vec3fEq(-165.986846923828125, 127.9736785888671875, -6.4473857879638671875), + Vec3fEq(-153.3157806396484375, 102.6315765380859375, -9.26317310333251953125), + Vec3fEq(-140.6447296142578125, 77.28946685791015625, -12.07896137237548828125), + Vec3fEq(-127.9736785888671875, 51.947368621826171875, -14.894748687744140625), + Vec3fEq(-115.3026275634765625, 26.6052646636962890625, -17.7105388641357421875), + Vec3fEq(-102.63158416748046875, 1.2631585597991943359375, -20.5263233184814453125), + Vec3fEq(-89.9605712890625, -24.0789661407470703125, -19.591716766357421875), + Vec3fEq(-68.54410552978515625, -42.629238128662109375, -19.847625732421875), + Vec3fEq(-47.127635955810546875, -61.17951202392578125, -20.1035366058349609375), + Vec3fEq(-25.711170196533203125, -79.72978973388671875, -20.359447479248046875), + Vec3fEq(-4.294706821441650390625, -98.280059814453125, -20.6153545379638671875), + Vec3fEq(17.121753692626953125, -116.83034515380859375, -17.3710460662841796875), + Vec3fEq(42.7990570068359375, -128.80755615234375, -14.7094440460205078125), + Vec3fEq(68.4763641357421875, -140.7847747802734375, -12.0478420257568359375), + Vec3fEq(94.15366363525390625, -152.761993408203125, -9.3862361907958984375), + Vec3fEq(119.83097076416015625, -164.7392120361328125, -6.724635601043701171875), + Vec3fEq(145.508270263671875, -176.7164306640625, -4.06303119659423828125), + Vec3fEq(171.185577392578125, -188.69366455078125, -1.40142619609832763671875), + Vec3fEq(196.862884521484375, -200.6708831787109375, 1.2601754665374755859375), + Vec3fEq(204, -204, 1.999979496002197265625) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_water_ground_lower_than_water_with_only_swim_flag) @@ -469,25 +464,24 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mAreaCosts, mOut), Status::Success); - EXPECT_EQ(mPath, std::deque({ - osg::Vec3f(0, 215, 185.33331298828125), - osg::Vec3f(0, 186.6666717529296875, 185.33331298828125), - osg::Vec3f(0, 158.333343505859375, 185.33331298828125), - osg::Vec3f(0, 130.0000152587890625, 185.33331298828125), - osg::Vec3f(0, 101.66667938232421875, 185.33331298828125), - osg::Vec3f(0, 73.333343505859375, 185.33331298828125), - osg::Vec3f(0, 45.0000152587890625, 185.33331298828125), - osg::Vec3f(0, 16.6666812896728515625, 185.33331298828125), - osg::Vec3f(0, -11.66664981842041015625, 185.33331298828125), - osg::Vec3f(0, -39.999980926513671875, 185.33331298828125), - osg::Vec3f(0, -68.33331298828125, 185.33331298828125), - osg::Vec3f(0, -96.66664886474609375, 185.33331298828125), - osg::Vec3f(0, -124.99997711181640625, 185.33331298828125), - osg::Vec3f(0, -153.33331298828125, 185.33331298828125), - osg::Vec3f(0, -181.6666412353515625, 185.33331298828125), - osg::Vec3f(0, -209.999969482421875, 185.33331298828125), - osg::Vec3f(0, -215, 185.33331298828125), - })) << mPath; + EXPECT_THAT(mPath, ElementsAre( + Vec3fEq(0, 204, 185.33331298828125), + Vec3fEq(0, 175.6666717529296875, 185.33331298828125), + Vec3fEq(0, 147.3333282470703125, 185.33331298828125), + Vec3fEq(0, 119, 185.33331298828125), + Vec3fEq(0, 90.6666717529296875, 185.33331298828125), + Vec3fEq(0, 62.333339691162109375, 185.33331298828125), + Vec3fEq(0, 34.00000762939453125, 185.33331298828125), + Vec3fEq(0, 5.66667461395263671875, 185.33331298828125), + Vec3fEq(0, -22.6666584014892578125, 185.33331298828125), + Vec3fEq(0, -50.999988555908203125, 185.33331298828125), + Vec3fEq(0, -79.33332061767578125, 185.33331298828125), + Vec3fEq(0, -107.666656494140625, 185.33331298828125), + Vec3fEq(0, -135.9999847412109375, 185.33331298828125), + Vec3fEq(0, -164.33331298828125, 185.33331298828125), + Vec3fEq(0, -192.666656494140625, 185.33331298828125), + Vec3fEq(0, -204, 185.33331298828125) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_water_when_ground_cross_water_with_swim_and_walk_flags) @@ -516,25 +510,24 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mOut), Status::Success); - EXPECT_EQ(mPath, std::deque({ - osg::Vec3f(0, 215, -94.75363922119140625), - osg::Vec3f(0, 186.6666717529296875, -106.0000152587890625), - osg::Vec3f(0, 158.333343505859375, -115.85507965087890625), - osg::Vec3f(0, 130.0000152587890625, -125.71016693115234375), - osg::Vec3f(0, 101.66667938232421875, -135.5652313232421875), - osg::Vec3f(0, 73.333343505859375, -143.3333587646484375), - osg::Vec3f(0, 45.0000152587890625, -143.3333587646484375), - osg::Vec3f(0, 16.6666812896728515625, -143.3333587646484375), - osg::Vec3f(0, -11.66664981842041015625, -143.3333587646484375), - osg::Vec3f(0, -39.999980926513671875, -143.3333587646484375), - osg::Vec3f(0, -68.33331298828125, -143.3333587646484375), - osg::Vec3f(0, -96.66664886474609375, -137.3043670654296875), - osg::Vec3f(0, -124.99997711181640625, -127.44930267333984375), - osg::Vec3f(0, -153.33331298828125, -117.59423065185546875), - osg::Vec3f(0, -181.6666412353515625, -107.73915863037109375), - osg::Vec3f(0, -209.999969482421875, -97.7971343994140625), - osg::Vec3f(0, -215, -94.75363922119140625), - })) << mPath; + EXPECT_THAT(mPath, ElementsAre( + Vec3fEq(0, 204, -98.000030517578125), + Vec3fEq(0, 175.6666717529296875, -108.30306243896484375), + Vec3fEq(0, 147.3333282470703125, -118.6060791015625), + Vec3fEq(0, 119, -128.90911865234375), + Vec3fEq(0, 90.6666717529296875, -139.2121429443359375), + Vec3fEq(0, 62.333339691162109375, -143.3333587646484375), + Vec3fEq(0, 34.00000762939453125, -143.3333587646484375), + Vec3fEq(0, 5.66667461395263671875, -143.3333587646484375), + Vec3fEq(0, -22.6666584014892578125, -143.3333587646484375), + Vec3fEq(0, -50.999988555908203125, -143.3333587646484375), + Vec3fEq(0, -79.33332061767578125, -143.3333587646484375), + Vec3fEq(0, -107.666656494140625, -133.0303192138671875), + Vec3fEq(0, -135.9999847412109375, -122.72728729248046875), + Vec3fEq(0, -164.33331298828125, -112.4242706298828125), + Vec3fEq(0, -192.666656494140625, -102.12123870849609375), + Vec3fEq(0, -204, -98.00002288818359375) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_water_when_ground_cross_water_with_max_int_cells_size_and_swim_and_walk_flags) @@ -563,25 +556,24 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mOut), Status::Success); - EXPECT_EQ(mPath, std::deque({ - osg::Vec3f(0, 215, -94.75363922119140625), - osg::Vec3f(0, 186.6666717529296875, -106.0000152587890625), - osg::Vec3f(0, 158.333343505859375, -115.85507965087890625), - osg::Vec3f(0, 130.0000152587890625, -125.71016693115234375), - osg::Vec3f(0, 101.66667938232421875, -135.5652313232421875), - osg::Vec3f(0, 73.333343505859375, -143.3333587646484375), - osg::Vec3f(0, 45.0000152587890625, -143.3333587646484375), - osg::Vec3f(0, 16.6666812896728515625, -143.3333587646484375), - osg::Vec3f(0, -11.66664981842041015625, -143.3333587646484375), - osg::Vec3f(0, -39.999980926513671875, -143.3333587646484375), - osg::Vec3f(0, -68.33331298828125, -143.3333587646484375), - osg::Vec3f(0, -96.66664886474609375, -137.3043670654296875), - osg::Vec3f(0, -124.99997711181640625, -127.44930267333984375), - osg::Vec3f(0, -153.33331298828125, -117.59423065185546875), - osg::Vec3f(0, -181.6666412353515625, -107.73915863037109375), - osg::Vec3f(0, -209.999969482421875, -97.7971343994140625), - osg::Vec3f(0, -215, -94.75363922119140625), - })) << mPath; + EXPECT_THAT(mPath, ElementsAre( + Vec3fEq(0, 204, -98.000030517578125), + Vec3fEq(0, 175.6666717529296875, -108.30306243896484375), + Vec3fEq(0, 147.3333282470703125, -118.6060791015625), + Vec3fEq(0, 119, -128.90911865234375), + Vec3fEq(0, 90.6666717529296875, -139.2121429443359375), + Vec3fEq(0, 62.333339691162109375, -143.3333587646484375), + Vec3fEq(0, 34.00000762939453125, -143.3333587646484375), + Vec3fEq(0, 5.66667461395263671875, -143.3333587646484375), + Vec3fEq(0, -22.6666584014892578125, -143.3333587646484375), + Vec3fEq(0, -50.999988555908203125, -143.3333587646484375), + Vec3fEq(0, -79.33332061767578125, -143.3333587646484375), + Vec3fEq(0, -107.666656494140625, -133.0303192138671875), + Vec3fEq(0, -135.9999847412109375, -122.72728729248046875), + Vec3fEq(0, -164.33331298828125, -112.4242706298828125), + Vec3fEq(0, -192.666656494140625, -102.12123870849609375), + Vec3fEq(0, -204, -98.00002288818359375) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_ground_when_ground_cross_water_with_only_walk_flag) @@ -610,25 +602,24 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(0, 215, -94.75363922119140625), - Vec3fEq(9.8083515167236328125, 188.4185333251953125, -105.199951171875), - Vec3fEq(19.6167049407958984375, 161.837066650390625, -114.25495147705078125), - Vec3fEq(29.42505645751953125, 135.255615234375, -123.309967041015625), - Vec3fEq(39.23340606689453125, 108.674163818359375, -132.3649749755859375), - Vec3fEq(49.04175567626953125, 82.09270477294921875, -137.2874755859375), - Vec3fEq(58.8501129150390625, 55.5112457275390625, -139.2451171875), - Vec3fEq(68.6584625244140625, 28.9297885894775390625, -141.2027740478515625), - Vec3fEq(78.4668121337890625, 2.3483295440673828125, -143.1604156494140625), - Vec3fEq(88.27516937255859375, -24.233127593994140625, -141.3894805908203125), - Vec3fEq(83.73651885986328125, -52.2005767822265625, -142.3761444091796875), - Vec3fEq(79.19786834716796875, -80.16802978515625, -143.114837646484375), - Vec3fEq(64.8477935791015625, -104.598602294921875, -137.840911865234375), - Vec3fEq(50.497714996337890625, -129.0291748046875, -131.45831298828125), - Vec3fEq(36.147632598876953125, -153.459747314453125, -121.42321014404296875), - Vec3fEq(21.7975559234619140625, -177.8903350830078125, -111.38811492919921875), - Vec3fEq(7.44747829437255859375, -202.3209075927734375, -101.19382476806640625), - Vec3fEq(0, -215, -94.75363922119140625) - )); + Vec3fEq(0, 204, -98.000030517578125), + Vec3fEq(10.26930999755859375, 177.59320068359375, -107.4711456298828125), + Vec3fEq(20.5386199951171875, 151.1864166259765625, -116.9422607421875), + Vec3fEq(30.8079280853271484375, 124.77960968017578125, -126.41339111328125), + Vec3fEq(41.077239990234375, 98.37281036376953125, -135.8845062255859375), + Vec3fEq(51.346546173095703125, 71.96601104736328125, -138.2003936767578125), + Vec3fEq(61.615856170654296875, 45.559215545654296875, -140.0838470458984375), + Vec3fEq(71.88516998291015625, 19.1524181365966796875, -141.9673004150390625), + Vec3fEq(82.15447235107421875, -7.254379749298095703125, -142.3074798583984375), + Vec3fEq(81.04636383056640625, -35.56603240966796875, -142.7104339599609375), + Vec3fEq(79.93825531005859375, -63.877685546875, -143.1133880615234375), + Vec3fEq(78.83014678955078125, -92.18933868408203125, -138.7660675048828125), + Vec3fEq(62.50392913818359375, -115.3460235595703125, -130.237823486328125), + Vec3fEq(46.17771148681640625, -138.502716064453125, -121.8172149658203125), + Vec3fEq(29.85149383544921875, -161.6594085693359375, -113.39659881591796875), + Vec3fEq(13.52527523040771484375, -184.81610107421875, -104.97599029541015625), + Vec3fEq(0, -204, -98.00002288818359375) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, update_remove_and_update_then_find_path_should_return_path) @@ -659,30 +650,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.85963428020477294921875), - Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), - Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), - Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), - Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), - Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), - Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), - Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), - Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), - Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), - Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), - Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), - Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), - Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), - Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), - Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), - Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), - Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), - Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), - Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), - Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), - Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), - Vec3fEq(215, -215, 1.87718021869659423828125) - )); + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-183.965301513671875, 183.965301513671875, 1.99998819828033447265625), + Vec3fEq(-163.9306182861328125, 163.9306182861328125, 1.99999344348907470703125), + Vec3fEq(-143.89593505859375, 143.89593505859375, -2.7206256389617919921875), + Vec3fEq(-123.86124420166015625, 123.86124420166015625, -13.1089839935302734375), + Vec3fEq(-103.8265533447265625, 103.8265533447265625, -23.4973468780517578125), + Vec3fEq(-83.7918548583984375, 83.7918548583984375, -33.885707855224609375), + Vec3fEq(-63.75716400146484375, 63.75716400146484375, -44.27407073974609375), + Vec3fEq(-43.72247314453125, 43.72247314453125, -54.662433624267578125), + Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -65.0507965087890625), + Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -75.43915557861328125), + Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -69.749267578125), + Vec3fEq(36.416290283203125, -36.416290283203125, -60.4739532470703125), + Vec3fEq(56.450984954833984375, -56.450984954833984375, -51.1986236572265625), + Vec3fEq(76.4856719970703125, -76.4856719970703125, -41.92330169677734375), + Vec3fEq(96.52036285400390625, -96.52036285400390625, -31.46941375732421875), + Vec3fEq(116.5550537109375, -116.5550537109375, -19.597003936767578125), + Vec3fEq(136.5897369384765625, -136.5897369384765625, -7.724592685699462890625), + Vec3fEq(156.6244354248046875, -156.6244354248046875, 1.99999535083770751953125), + Vec3fEq(176.6591339111328125, -176.6591339111328125, 1.99999010562896728515625), + Vec3fEq(196.693817138671875, -196.693817138671875, 1.99998486042022705078125), + Vec3fEq(204, -204, 1.99998295307159423828125) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, update_then_find_random_point_around_circle_should_return_position) @@ -706,11 +696,12 @@ namespace const auto result = mNavigator->findRandomPointAroundCircle(mAgentHalfExtents, mStart, 100.0, Flag_walk); - ASSERT_THAT(result, Optional(Vec3fEq(-209.95985412597656, 129.89768981933594, -0.26253718137741089))); + ASSERT_THAT(result, Optional(Vec3fEq(-198.909332275390625, 123.06096649169921875, 1.99998414516448974609375))) + << (result ? *result : osg::Vec3f()); const auto distance = (*result - mStart).length(); - EXPECT_FLOAT_EQ(distance, 85.260780334472656); + EXPECT_FLOAT_EQ(distance, 81.105133056640625) << distance; } TEST_F(DetourNavigatorNavigatorTest, multiple_threads_should_lock_tiles) @@ -754,29 +745,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.8782780170440673828125), - Vec3fEq(-199.7968292236328125, 191.09100341796875, -3.54875946044921875), - Vec3fEq(-184.5936431884765625, 167.1819915771484375, -8.97846889495849609375), - Vec3fEq(-169.3904571533203125, 143.2729949951171875, -14.40818119049072265625), - Vec3fEq(-154.1872711181640625, 119.363983154296875, -19.837886810302734375), - Vec3fEq(-138.9840850830078125, 95.4549713134765625, -25.2675952911376953125), - Vec3fEq(-123.78090667724609375, 71.54595947265625, -30.6973056793212890625), - Vec3fEq(-108.57772064208984375, 47.63695526123046875, -36.12701416015625), - Vec3fEq(-93.3745269775390625, 23.72794342041015625, -40.754695892333984375), - Vec3fEq(-78.17134857177734375, -0.18106450140476226806640625, -37.128795623779296875), - Vec3fEq(-62.968158721923828125, -24.0900726318359375, -33.50289154052734375), - Vec3fEq(-47.764972686767578125, -47.99908447265625, -30.797946929931640625), - Vec3fEq(-23.8524494171142578125, -63.196746826171875, -33.97112274169921875), - Vec3fEq(0.0600722394883632659912109375, -78.3944091796875, -37.14543914794921875), - Vec3fEq(23.97259521484375, -93.592071533203125, -40.774089813232421875), - Vec3fEq(47.885120391845703125, -108.78974151611328125, -36.051296234130859375), - Vec3fEq(71.797637939453125, -123.98740386962890625, -30.62355804443359375), - Vec3fEq(95.71016693115234375, -139.18505859375, -25.195819854736328125), - Vec3fEq(119.6226806640625, -154.382720947265625, -19.768085479736328125), - Vec3fEq(143.5352020263671875, -169.5803680419921875, -14.34035015106201171875), - Vec3fEq(167.447723388671875, -184.7780303955078125, -8.912616729736328125), - Vec3fEq(191.3602294921875, -199.9756927490234375, -3.48488140106201171875), - Vec3fEq(215, -215, 1.8782813549041748046875) + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-189.9427337646484375, 179.3997802734375, 1.9999866485595703125), + Vec3fEq(-175.8854522705078125, 154.7995452880859375, 1.99999034404754638671875), + Vec3fEq(-161.82818603515625, 130.1993255615234375, -3.701923847198486328125), + Vec3fEq(-147.770904541015625, 105.5991058349609375, -15.67664432525634765625), + Vec3fEq(-133.7136383056640625, 80.99887847900390625, -27.6513614654541015625), + Vec3fEq(-119.65636444091796875, 56.39865875244140625, -20.1209163665771484375), + Vec3fEq(-105.59909820556640625, 31.798435211181640625, -25.0669879913330078125), + Vec3fEq(-91.54183197021484375, 7.1982135772705078125, -31.5624217987060546875), + Vec3fEq(-77.48455810546875, -17.402008056640625, -26.98972320556640625), + Vec3fEq(-63.427295684814453125, -42.00223541259765625, -19.9045581817626953125), + Vec3fEq(-42.193531036376953125, -60.761363983154296875, -20.4544773101806640625), + Vec3fEq(-20.9597682952880859375, -79.5204925537109375, -23.599918365478515625), + Vec3fEq(3.8312885761260986328125, -93.2384033203125, -30.7141361236572265625), + Vec3fEq(28.6223468780517578125, -106.95632171630859375, -24.1782474517822265625), + Vec3fEq(53.413402557373046875, -120.6742401123046875, -19.4096889495849609375), + Vec3fEq(78.20446014404296875, -134.39215087890625, -27.6632633209228515625), + Vec3fEq(102.99552154541015625, -148.110076904296875, -15.8613681793212890625), + Vec3fEq(127.7865753173828125, -161.827972412109375, -4.059485912322998046875), + Vec3fEq(152.57763671875, -175.5458984375, 1.9999904632568359375), + Vec3fEq(177.3686981201171875, -189.2638092041015625, 1.9999866485595703125), + Vec3fEq(202.1597442626953125, -202.9817047119140625, 1.9999830722808837890625), + Vec3fEq(204, -204, 1.99998295307159423828125) )) << mPath; } @@ -836,7 +827,8 @@ namespace const auto result = mNavigator->raycast(mAgentHalfExtents, mStart, mEnd, Flag_walk); - ASSERT_THAT(result, Optional(Vec3fEq(mEnd.x(), mEnd.y(), 1.87719))); + ASSERT_THAT(result, Optional(Vec3fEq(mEnd.x(), mEnd.y(), 1.99998295307159423828125))) + << (result ? *result : osg::Vec3f()); } TEST_F(DetourNavigatorNavigatorTest, update_for_oscillating_object_that_does_not_change_navmesh_should_not_trigger_navmesh_update) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index cfa04de03..6d7aa63fb 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -266,6 +266,7 @@ if (BUILD_OPENMW OR BUILD_OPENCS) raycast navmeshtileview oscillatingrecastmeshobject + offmeshconnectionsmanager ) endif() # End of tes3mp change (major) diff --git a/components/detournavigator/findsmoothpath.cpp b/components/detournavigator/findsmoothpath.cpp index 8974be532..659826339 100644 --- a/components/detournavigator/findsmoothpath.cpp +++ b/components/detournavigator/findsmoothpath.cpp @@ -1,5 +1,7 @@ #include "findsmoothpath.hpp" +#include + #include #include @@ -103,7 +105,7 @@ namespace DetourNavigator return result; } - std::optional getSteerTarget(const dtNavMeshQuery& navQuery, const osg::Vec3f& startPos, + std::optional getSteerTarget(const dtNavMeshQuery& navMeshQuery, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const float minTargetDist, const std::vector& path) { // Find steer target. @@ -113,8 +115,11 @@ namespace DetourNavigator std::array steerPathFlags; std::array steerPathPolys; int nsteerPath = 0; - navQuery.findStraightPath(startPos.ptr(), endPos.ptr(), path.data(), int(path.size()), steerPath.data(), - steerPathFlags.data(), steerPathPolys.data(), &nsteerPath, maxSteerPoints); + const dtStatus status = navMeshQuery.findStraightPath(startPos.ptr(), endPos.ptr(), path.data(), + static_cast(path.size()), steerPath.data(), steerPathFlags.data(), steerPathPolys.data(), + &nsteerPath, maxSteerPoints); + if (dtStatusFailed(status)) + return std::nullopt; assert(nsteerPath >= 0); if (!nsteerPath) return std::nullopt; @@ -125,7 +130,7 @@ namespace DetourNavigator { // Stop at Off-Mesh link or when point is further than slop away. if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || - !inRange(Misc::Convert::makeOsgVec3f(&steerPath[ns * 3]), startPos, minTargetDist, 1000.0f)) + !inRange(Misc::Convert::makeOsgVec3f(&steerPath[ns * 3]), startPos, minTargetDist)) break; ns++; } diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index 0a9b5bed8..db2219b2c 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -14,9 +14,8 @@ #include #include -#include - #include + #include #include @@ -26,10 +25,9 @@ namespace DetourNavigator { struct Settings; - inline bool inRange(const osg::Vec3f& v1, const osg::Vec3f& v2, const float r, const float h) + inline bool inRange(const osg::Vec3f& v1, const osg::Vec3f& v2, const float r) { - const auto d = v2 - v1; - return (d.x() * d.x() + d.z() * d.z()) < r * r && std::abs(d.y()) < h; + return (osg::Vec2f(v1.x(), v1.z()) - osg::Vec2f(v2.x(), v2.z())).length() < r; } std::vector fixupCorridor(const std::vector& path, const std::vector& visited); @@ -143,15 +141,6 @@ namespace DetourNavigator return {std::move(result)}; } - inline std::optional getPolyHeight(const dtNavMeshQuery& navMeshQuery, const dtPolyRef ref, const osg::Vec3f& pos) - { - float result = 0.0f; - const auto status = navMeshQuery.getPolyHeight(ref, pos.ptr(), &result); - if (!dtStatusSucceed(status)) - return {}; - return result; - } - template Status makeSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery, const dtQueryFilter& filter, const osg::Vec3f& start, const osg::Vec3f& end, const float stepSize, @@ -201,13 +190,8 @@ namespace DetourNavigator polygonPath = fixupCorridor(polygonPath, result->mVisited); polygonPath = fixupShortcuts(polygonPath, navMeshQuery); - float h = 0; - navMeshQuery.getPolyHeight(polygonPath.front(), result->mResultPos.ptr(), &h); - iterPos = result->mResultPos; - iterPos.y() = h; - // Handle end of path and off-mesh links when close enough. - if (endOfPath && inRange(iterPos, steerTarget->steerPos, slop, 1.0f)) + if (endOfPath && inRange(result->mResultPos, steerTarget->steerPos, slop)) { // Reached end of path. iterPos = targetPos; @@ -215,7 +199,7 @@ namespace DetourNavigator ++smoothPathSize; break; } - else if (offMeshConnection && inRange(iterPos, steerTarget->steerPos, slop, 1.0f)) + else if (offMeshConnection && inRange(result->mResultPos, steerTarget->steerPos, slop)) { // Advance the path up to and over the off-mesh connection. dtPolyRef prevRef = 0; @@ -249,16 +233,18 @@ namespace DetourNavigator } // Move position at the other side of the off-mesh link. - iterPos = endPos; - const auto height = getPolyHeight(navMeshQuery, polygonPath.front(), iterPos); - - if (!height) + if (dtStatusFailed(navMeshQuery.getPolyHeight(polygonPath.front(), endPos.ptr(), &iterPos.y()))) return Status::GetPolyHeightFailed; - - iterPos.y() = *height; + iterPos.x() = endPos.x(); + iterPos.z() = endPos.z(); } } + if (dtStatusFailed(navMeshQuery.getPolyHeight(polygonPath.front(), result->mResultPos.ptr(), &iterPos.y()))) + return Status::GetPolyHeightFailed; + iterPos.x() = result->mResultPos.x(); + iterPos.z() = result->mResultPos.z(); + // Store results. *out++ = iterPos; ++smoothPathSize; diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index bcfd1b22f..422fdffb1 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -389,7 +389,7 @@ namespace const auto offMeshConVerts = getOffMeshVerts(offMeshConnections); const std::vector offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents)); - const std::vector offMeshConDir(offMeshConnections.size(), DT_OFFMESH_CON_BIDIR); + const std::vector offMeshConDir(offMeshConnections.size(), 0); const std::vector offMeshConAreas = getOffMeshConAreas(offMeshConnections); const std::vector offMeshConFlags = getOffMeshFlags(offMeshConnections); diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index b7b3bbd58..1aa4768de 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -55,12 +55,10 @@ namespace DetourNavigator { if (addObject(id, static_cast(shapes), transform)) { - mNavMeshManager.addOffMeshConnection( - id, - toNavMeshCoordinates(mSettings, shapes.mConnectionStart), - toNavMeshCoordinates(mSettings, shapes.mConnectionEnd), - AreaType_door - ); + const osg::Vec3f start = toNavMeshCoordinates(mSettings, shapes.mConnectionStart); + const osg::Vec3f end = toNavMeshCoordinates(mSettings, shapes.mConnectionEnd); + mNavMeshManager.addOffMeshConnection(id, start, end, AreaType_door); + mNavMeshManager.addOffMeshConnection(id, end, start, AreaType_door); return true; } return false; diff --git a/components/detournavigator/offmeshconnectionsmanager.cpp b/components/detournavigator/offmeshconnectionsmanager.cpp new file mode 100644 index 000000000..a673ae3e6 --- /dev/null +++ b/components/detournavigator/offmeshconnectionsmanager.cpp @@ -0,0 +1,95 @@ +#include "offmeshconnectionsmanager.hpp" +#include "settings.hpp" +#include "settingsutils.hpp" +#include "tileposition.hpp" +#include "objectid.hpp" +#include "offmeshconnection.hpp" + +#include +#include +#include + +namespace DetourNavigator +{ + OffMeshConnectionsManager::OffMeshConnectionsManager(const Settings& settings) + : mSettings(settings) + {} + + void OffMeshConnectionsManager::add(const ObjectId id, const OffMeshConnection& value) + { + const auto values = mValues.lock(); + + values->mById.insert(std::make_pair(id, value)); + + const auto startTilePosition = getTilePosition(mSettings, value.mStart); + const auto endTilePosition = getTilePosition(mSettings, value.mEnd); + + values->mByTilePosition[startTilePosition].insert(id); + + if (startTilePosition != endTilePosition) + values->mByTilePosition[endTilePosition].insert(id); + } + + std::set OffMeshConnectionsManager::remove(const ObjectId id) + { + const auto values = mValues.lock(); + + const auto byId = values->mById.equal_range(id); + + if (byId.first == byId.second) + return {}; + + std::set removed; + + std::for_each(byId.first, byId.second, [&] (const auto& v) { + const auto startTilePosition = getTilePosition(mSettings, v.second.mStart); + const auto endTilePosition = getTilePosition(mSettings, v.second.mEnd); + + removed.emplace(startTilePosition); + if (startTilePosition != endTilePosition) + removed.emplace(endTilePosition); + }); + + for (const TilePosition& tilePosition : removed) + { + const auto it = values->mByTilePosition.find(tilePosition); + if (it == values->mByTilePosition.end()) + continue; + it->second.erase(id); + if (it->second.empty()) + values->mByTilePosition.erase(it); + } + + values->mById.erase(byId.first, byId.second); + + return removed; + } + + std::vector OffMeshConnectionsManager::get(const TilePosition& tilePosition) + { + std::vector result; + + const auto values = mValues.lock(); + + const auto itByTilePosition = values->mByTilePosition.find(tilePosition); + + if (itByTilePosition == values->mByTilePosition.end()) + return result; + + std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(), + [&] (const ObjectId v) + { + const auto byId = values->mById.equal_range(v); + std::for_each(byId.first, byId.second, [&] (const auto& v) + { + if (getTilePosition(mSettings, v.second.mStart) == tilePosition + || getTilePosition(mSettings, v.second.mEnd) == tilePosition) + result.push_back(v.second); + }); + }); + + std::sort(result.begin(), result.end()); + + return result; + } +} diff --git a/components/detournavigator/offmeshconnectionsmanager.hpp b/components/detournavigator/offmeshconnectionsmanager.hpp index 1ad96e3b9..20a6427cd 100644 --- a/components/detournavigator/offmeshconnectionsmanager.hpp +++ b/components/detournavigator/offmeshconnectionsmanager.hpp @@ -2,16 +2,12 @@ #define OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTIONSMANAGER_H #include "settings.hpp" -#include "settingsutils.hpp" #include "tileposition.hpp" #include "objectid.hpp" #include "offmeshconnection.hpp" #include -#include - -#include #include #include #include @@ -22,73 +18,13 @@ namespace DetourNavigator class OffMeshConnectionsManager { public: - OffMeshConnectionsManager(const Settings& settings) - : mSettings(settings) - {} - - void add(const ObjectId id, const OffMeshConnection& value) - { - const auto values = mValues.lock(); - - values->mById.insert(std::make_pair(id, value)); - - const auto startTilePosition = getTilePosition(mSettings, value.mStart); - const auto endTilePosition = getTilePosition(mSettings, value.mEnd); - - values->mByTilePosition[startTilePosition].insert(id); - - if (startTilePosition != endTilePosition) - values->mByTilePosition[endTilePosition].insert(id); - } - - std::set remove(const ObjectId id) - { - const auto values = mValues.lock(); - - const auto byId = values->mById.equal_range(id); - - if (byId.first == byId.second) { - return {}; - } - - std::set removed; + OffMeshConnectionsManager(const Settings& settings); - std::for_each(byId.first, byId.second, [&] (const auto& v) { - const auto startTilePosition = getTilePosition(mSettings, v.second.mStart); - const auto endTilePosition = getTilePosition(mSettings, v.second.mEnd); + void add(const ObjectId id, const OffMeshConnection& value); - removed.emplace(startTilePosition); - if (startTilePosition != endTilePosition) - removed.emplace(endTilePosition); - }); + std::set remove(const ObjectId id); - values->mById.erase(byId.first, byId.second); - - return removed; - } - - std::vector get(const TilePosition& tilePosition) - { - std::vector result; - - const auto values = mValues.lock(); - - const auto itByTilePosition = values->mByTilePosition.find(tilePosition); - - if (itByTilePosition == values->mByTilePosition.end()) - return result; - - std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(), - [&] (const ObjectId v) - { - const auto byId = values->mById.equal_range(v); - std::for_each(byId.first, byId.second, [&] (const auto& v) { result.push_back(v.second); }); - }); - - std::sort(result.begin(), result.end()); - - return result; - } + std::vector get(const TilePosition& tilePosition); private: struct Values @@ -99,14 +35,6 @@ namespace DetourNavigator const Settings& mSettings; Misc::ScopeGuarded mValues; - - void removeByTilePosition(std::map>& valuesByTilePosition, - const TilePosition& tilePosition, const ObjectId id) - { - const auto it = valuesByTilePosition.find(tilePosition); - if (it != valuesByTilePosition.end()) - it->second.erase(id); - } }; } diff --git a/components/detournavigator/settingsutils.hpp b/components/detournavigator/settingsutils.hpp index 8f1c96e28..245e4a7e5 100644 --- a/components/detournavigator/settingsutils.hpp +++ b/components/detournavigator/settingsutils.hpp @@ -12,7 +12,8 @@ #include #include -#include +#include +#include namespace DetourNavigator { @@ -28,7 +29,7 @@ namespace DetourNavigator inline float getRadius(const Settings& settings, const osg::Vec3f& agentHalfExtents) { - return agentHalfExtents.x() * settings.mRecastScaleFactor; + return std::max(agentHalfExtents.x(), agentHalfExtents.y()) * std::sqrt(2) * settings.mRecastScaleFactor; } inline float toNavMeshCoordinates(const Settings& settings, float value) diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 65af0fad8..067d34a59 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -69,6 +69,15 @@ float Manager::getFloat (const std::string& setting, const std::string& category return number; } +double Manager::getDouble (const std::string& setting, const std::string& category) +{ + const std::string& value = getString(setting, category); + std::stringstream stream(value); + double number = 0.0; + stream >> number; + return number; +} + int Manager::getInt (const std::string& setting, const std::string& category) { const std::string& value = getString(setting, category); @@ -136,6 +145,13 @@ void Manager::setFloat (const std::string &setting, const std::string &category, setString(setting, category, stream.str()); } +void Manager::setDouble (const std::string &setting, const std::string &category, const double value) +{ + std::ostringstream stream; + stream << value; + setString(setting, category, stream.str()); +} + void Manager::setBool(const std::string &setting, const std::string &category, const bool value) { setString(setting, category, value ? "true" : "false"); diff --git a/components/settings/settings.hpp b/components/settings/settings.hpp index b9cd7dcf6..967962c74 100644 --- a/components/settings/settings.hpp +++ b/components/settings/settings.hpp @@ -52,6 +52,7 @@ namespace Settings static int getInt (const std::string& setting, const std::string& category); static float getFloat (const std::string& setting, const std::string& category); + static double getDouble (const std::string& setting, const std::string& category); static std::string getString (const std::string& setting, const std::string& category); static bool getBool (const std::string& setting, const std::string& category); static osg::Vec2f getVector2 (const std::string& setting, const std::string& category); @@ -59,6 +60,7 @@ namespace Settings static void setInt (const std::string& setting, const std::string& category, const int value); static void setFloat (const std::string& setting, const std::string& category, const float value); + static void setDouble (const std::string& setting, const std::string& category, const double value); static void setString (const std::string& setting, const std::string& category, const std::string& value); static void setBool (const std::string& setting, const std::string& category, const bool value); static void setVector2 (const std::string& setting, const std::string& category, const osg::Vec2f value); diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index e8ac7d9c3..c21593f35 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -280,10 +280,12 @@ namespace Shader osg::StateSet::AttributeList removedAttributes; if (osg::ref_ptr removedState = getRemovedState(*stateset)) removedAttributes = removedState->getAttributeList(); - for (const auto& attributeMap : { attributes, removedAttributes }) + for (const auto* attributeMap : std::initializer_list{ &attributes, &removedAttributes }) { - for (osg::StateSet::AttributeList::const_iterator it = attributeMap.begin(); it != attributeMap.end(); ++it) + for (osg::StateSet::AttributeList::const_iterator it = attributeMap->begin(); it != attributeMap->end(); ++it) { + if (attributeMap != &removedAttributes && removedAttributes.count(it->first)) + continue; if (it->first.first == osg::StateAttribute::MATERIAL) { // This should probably be moved out of ShaderRequirements and be applied directly now it's a uniform instead of a define @@ -405,9 +407,12 @@ namespace Shader { writableStateSet->addUniform(new osg::Uniform("alphaRef", reqs.mAlphaRef)); - const auto* alphaFunc = writableStateSet->getAttributePair(osg::StateAttribute::ALPHAFUNC); - if (alphaFunc) - removedState->setAttribute(alphaFunc->first, alphaFunc->second); + if (!removedState->getAttributePair(osg::StateAttribute::ALPHAFUNC)) + { + const auto* alphaFunc = writableStateSet->getAttributePair(osg::StateAttribute::ALPHAFUNC); + if (alphaFunc) + removedState->setAttribute(alphaFunc->first, alphaFunc->second); + } // This prevents redundant glAlphaFunc calls while letting the shadows bin still see the test writableStateSet->setAttribute(RemovedAlphaFunc::getInstance(reqs.mAlphaFunc), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); diff --git a/docs/source/reference/modding/index.rst b/docs/source/reference/modding/index.rst index 90491d34d..440db96d8 100644 --- a/docs/source/reference/modding/index.rst +++ b/docs/source/reference/modding/index.rst @@ -20,6 +20,7 @@ about creating new content for OpenMW, please refer to foreword differences mod-install + openmw-game-template settings/index texture-modding/index custom-models/index diff --git a/docs/source/reference/modding/openmw-game-template.rst b/docs/source/reference/modding/openmw-game-template.rst new file mode 100644 index 000000000..68fa66791 --- /dev/null +++ b/docs/source/reference/modding/openmw-game-template.rst @@ -0,0 +1,122 @@ +#################### +OpenMW Game Template +#################### + +OpenMW Game Template, or simply, the Template, is a set of base assets required +for OpenMW to run. These include ``template.omwgame`` along with models, textures, +fonts, and UI content. The Template can be used as a foundation for a standalone +game in OpenMW, without requiring any of the original, copyrighted Morrowind assets. +With the exception of ``Pelagiad.ttf`` font file, the Template is released as +`public domain `_. + + +Installation +************ + +The Template is installed the same way you would install a mod, with general +instructions available at :doc:`mod-install`. It can be downloaded from +`its repository `_ and requires +OpenMW 0.47 or later. + +After getting the Template, extract its ``/data`` folder to somewhere on your disk. + +.. note:: + + It's adviseable to not put the Template files in the same folder as your + Morrowind files. This is especially valid when you don't wish to mix the two games + and use the Template as a foundation for a standalone game. + + +Define paths to .omwgame and data files +======================================= + +OpenMW needs to be told where to look for the Template files. This is done in +``openmw.cfg`` file where ``content=`` tells OpenMW which .omwgame file to use +and ``data=`` tells OpenMW what folders to look for meshes, textures, audio, +and other assets. The required lines would look like this, but with the paths +of course different on your system. + +.. code:: + + content=template.omwgame + data="/home/someuser/example-suite/data" + data="/home/someuser/example-suite" + + +Remove references to Morrowind files +==================================== + +In case you have Morrowind installed and have run OpenMW's installation wizard, +you need to remove or comment out the following lines from ``openmw.cfg``. +Not doing so will either produce errors or load Morrowind content, which you +probably do not want when you are making your own game. + +.. code:: + + fallback-archive=Morrowind.bsa + fallback-archive=Tribunal.bsa + fallback-archive=Bloodmoon.bsa + content=Morrowind.esm + content=Tribunal.esm + content=Bloodmoon.esm + data="/home/someuser/.wine/dosdevices/c:/Morrowind/Data Files" + + +Define paths to essential models +================================ + +Certain models, essential to OpenMW, cannot be assigned through OpenMW-CS but +are instead assigned through ``settings.cfg``. These models are player and NPC +animations, and meshes for the sky. In ``settings.cfg`` used by your OpenMW +install, add the following lines under the ``[Models]`` section. + +.. code:: + + xbaseanim = meshes/BasicPlayer.dae + baseanim = meshes/BasicPlayer.dae + xbaseanim1st = meshes/BasicPlayer.dae + baseanimkna = meshes/BasicPlayer.dae + baseanimkna1st = meshes/BasicPlayer.dae + xbaseanimfemale = meshes/BasicPlayer.dae + baseanimfemale = meshes/BasicPlayer.dae + baseanimfemale1st = meshes/BasicPlayer.dae + xargonianswimkna = meshes/BasicPlayer.dae + xbaseanimkf = meshes/BasicPlayer.dae + xbaseanim1stkf = meshes/BasicPlayer.dae + xbaseanimfemalekf = meshes/BasicPlayer.dae + xargonianswimknakf = meshes/BasicPlayer.dae + skyatmosphere = meshes/sky_atmosphere.dae + skyclouds = meshes/sky_clouds_01.osgt + skynight01 = meshes/sky_night_01.osgt + + +As a convenience the Template repository includes a ``settings.cfg`` containing +these same lines which can be copied and pasted. However, do not use the file +to simply overwrite the ``settings.cfg`` used by your OpenMW installation. + + +Copying the UI files +==================== + +The Template includes a ``resources/mygui`` folder. The contents of this folder +need to be copied to ``resources/mygui`` folder found in your OpenMW installation +folder. Overwrite any files aready in this folder. These files provide the +UI font, its definition, and some minor UI tweaks. + +.. code:: + + openmw_box.skin.xml + openmw_button.skin.xml + openmw_font.xml + openmw_windows.skin.xml + Pelagiad.ttf + + +Run OpenMW Launcher +******************* + +After completing all the steps, run OpenMW Launcher and make sure ``template.omwgame`` +is selected in *Data Files* tab. Then, run the game and enjoy an empty island. It is not +empty though! It is full of potential to start making your very own game on the +OpenMW engine. Good luck! + diff --git a/extern/osg-ffmpeg-videoplayer/audiodecoder.cpp b/extern/osg-ffmpeg-videoplayer/audiodecoder.cpp index b5b3b8a3e..decf57e4d 100644 --- a/extern/osg-ffmpeg-videoplayer/audiodecoder.cpp +++ b/extern/osg-ffmpeg-videoplayer/audiodecoder.cpp @@ -71,7 +71,7 @@ MovieAudioDecoder::MovieAudioDecoder(VideoState* videoState) { mAudioResampler.reset(new AudioResampler()); - AVCodec *codec = avcodec_find_decoder(mAVStream->codecpar->codec_id); + const AVCodec *codec = avcodec_find_decoder(mAVStream->codecpar->codec_id); if(!codec) { std::string ss = "No codec found for id " + diff --git a/extern/osg-ffmpeg-videoplayer/videostate.cpp b/extern/osg-ffmpeg-videoplayer/videostate.cpp index c3cb412e9..7b4060753 100644 --- a/extern/osg-ffmpeg-videoplayer/videostate.cpp +++ b/extern/osg-ffmpeg-videoplayer/videostate.cpp @@ -632,7 +632,7 @@ bool VideoState::update() int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx) { - AVCodec *codec; + const AVCodec *codec; if(stream_index < 0 || stream_index >= static_cast(pFormatCtx->nb_streams)) return -1; diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index b9d5c7ef5..8abe8f59a 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -478,6 +478,36 @@ + + + + + <html><head/><body><p>Controls how large an object must be to be visible in the scene. The object’s size is divided by its distance to the camera and the result of the division is compared with this value. The smaller this value is, the more objects you will see in the scene.</p></body></html> + + + Object paging min size + + + + + + + 3 + + + 0.000000000000000 + + + 0.250000000000000 + + + 0.005000000000000 + + + + + + <html><head/><body><p>If true, use paging and LOD algorithms to display the entire terrain. If false, only display terrain of the loaded cells.</p></body></html> @@ -487,7 +517,7 @@ - + 20