Add OpenMW 0.47 commits up to 1 Jul 2021

# Conflicts:
#   components/CMakeLists.txt
pull/593/head
David Cernat 4 years ago
commit 6b45a48116

@ -7,7 +7,6 @@
Bug #2069: Fireflies in Fireflies invade Morrowind look wrong Bug #2069: Fireflies in Fireflies invade Morrowind look wrong
Bug #2311: Targeted scripts are not properly supported on non-unique RefIDs Bug #2311: Targeted scripts are not properly supported on non-unique RefIDs
Bug #2473: Unable to overstock merchants 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 #2976: [reopened]: Issues combining settings from the command line and both config files
Bug #3137: Walking into a wall prevents jumping Bug #3137: Walking into a wall prevents jumping
Bug #3372: Projectiles and magic bolts go through moving targets 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 #4039: Multiple followers should have the same following distance
Bug #4055: Local scripts don't inherit variables from their base record Bug #4055: Local scripts don't inherit variables from their base record
Bug #4083: Door animation freezes when colliding with actors Bug #4083: Door animation freezes when colliding with actors
Bug #4201: Projectile-projectile collision
Bug #4247: Cannot walk up stairs in Ebonheart docks Bug #4247: Cannot walk up stairs in Ebonheart docks
Bug #4357: OpenMW-CS: TopicInfos index sorting and rearranging isn't fully functional 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 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 #5644: Summon effects running on the player during game initialization cause crashes
Bug #5656: Sneaking characters block hits while standing Bug #5656: Sneaking characters block hits while standing
Bug #5661: Region sounds don't play at the right interval 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 #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 #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 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 #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 #5758: Paralyzed actors behavior is inconsistent with vanilla
Bug #5762: Movement solver is insufficiently robust 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 #5807: Video decoding crash on ARM
Bug #5821: NPCs from mods getting removed if mod order was changed 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 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 #390: 3rd person look "over the shoulder"
Feature #832: OpenMW-CS: Handle deleted references Feature #832: OpenMW-CS: Handle deleted references
Feature #1536: Show more information about level on menu 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 #2386: Distant Statics in the form of Object Paging
Feature #2404: Levelled List can not be placed into a container Feature #2404: Levelled List can not be placed into a container
Feature #2686: Timestamps in openmw.log Feature #2686: Timestamps in openmw.log
Feature #2798: Mutable ESM records
Feature #3171: OpenMW-CS: Instance drag selection Feature #3171: OpenMW-CS: Instance drag selection
Feature #3983: Wizard: Add link to buy Morrowind 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 #4894: Consider actors as obstacles for pathfinding
Feature #4899: Alpha-To-Coverage Anti-Aliasing for alpha testing Feature #4899: Alpha-To-Coverage Anti-Aliasing for alpha testing
Feature #4917: Do not trigger NavMesh update when RecastMesh update should not change NavMesh 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 Feature #6034: Find path based on area cost depending on NPC stats
Task #5480: Drop Qt4 support Task #5480: Drop Qt4 support
Task #5520: Improve cell name autocompleter implementation Task #5520: Improve cell name autocompleter implementation
Task #5844: Update 'toggle sneak' documentation
0.46.0 0.46.0
------ ------
@ -186,7 +187,7 @@
Bug #2395: Duplicated plugins in the launcher when multiple data directories provide the same plugin 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 #2679: Unable to map mouse wheel under control settings
Bug #2969: Scripted items can stack 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 #2987: Editor: some chance and AI data fields can overflow
Bug #3006: 'else if' operator breaks script compilation Bug #3006: 'else if' operator breaks script compilation
Bug #3109: SetPos/Position handles actors differently 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 #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 #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 #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 #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect
Bug #4262: Rain settings are hardcoded Bug #4262: Rain settings are hardcoded
Bug #4270: Closing doors while they are obstructed desyncs closing sfx 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 #4964: Multiple effect spell projectile sounds play louder than vanilla
Bug #4965: Global light attenuation settings setup is lacking Bug #4965: Global light attenuation settings setup is lacking
Bug #4969: "Miss" sound plays for any actor 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 #4972: Player is able to use quickkeys while disableplayerfighting is active
Bug #4979: AiTravel maximum range depends on "actors processing range" setting Bug #4979: AiTravel maximum range depends on "actors processing range" setting
Bug #4980: Drowning mechanics is applied for actors indifferently from distance to player 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 #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 Bug #5352: Light source items' duration is decremented while they aren't visible
Feature #1724: Handle AvoidNode Feature #1724: Handle AvoidNode
Feature #2159: "Graying out" exhausted dialogue topics
Feature #2229: Improve pathfinding AI Feature #2229: Improve pathfinding AI
Feature #3025: Analogue gamepad movement controls Feature #3025: Analogue gamepad movement controls
Feature #3442: Default values for fallbacks from ini file Feature #3442: Default values for fallbacks from ini file
@ -405,6 +403,7 @@
Feature #4001: Toggle sneak controller shortcut Feature #4001: Toggle sneak controller shortcut
Feature #4068: OpenMW-CS: Add a button to reset key bindings to defaults Feature #4068: OpenMW-CS: Add a button to reset key bindings to defaults
Feature #4129: Beta Comment to File 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 #4209: Editor: Faction rank sub-table
Feature #4255: Handle broken RepairedOnMe script function Feature #4255: Handle broken RepairedOnMe script function
Feature #4316: Implement RaiseRank/LowerRank functions properly Feature #4316: Implement RaiseRank/LowerRank functions properly
@ -427,6 +426,7 @@
Feature #4958: Support eight blood types Feature #4958: Support eight blood types
Feature #4962: Add casting animations for magic items Feature #4962: Add casting animations for magic items
Feature #4968: Scalable UI widget skins 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 #4994: Persistent pinnable windows hiding
Feature #5000: Compressed BSA format support Feature #5000: Compressed BSA format support
Feature #5005: Editor: Instance window via Scene window Feature #5005: Editor: Instance window via Scene window

@ -136,6 +136,7 @@ bool Launcher::AdvancedPage::loadSettings()
loadSettingBool(activeGridObjectPagingCheckBox, "object paging active grid", "Terrain"); loadSettingBool(activeGridObjectPagingCheckBox, "object paging active grid", "Terrain");
viewingDistanceComboBox->setValue(convertToCells(Settings::Manager::getInt("viewing distance", "Camera"))); viewingDistanceComboBox->setValue(convertToCells(Settings::Manager::getInt("viewing distance", "Camera")));
objectPagingMinSizeComboBox->setValue(Settings::Manager::getDouble("object paging min size", "Terrain"));
} }
// Audio // Audio
@ -287,6 +288,9 @@ void Launcher::AdvancedPage::saveSettings()
{ {
Settings::Manager::setInt("viewing distance", "Camera", convertToUnits(viewingDistance)); 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 // Audio

@ -144,13 +144,15 @@ namespace MWClass
MWBase::Environment::get().getWorld()->getMaxActivationDistance()) MWBase::Environment::get().getWorld()->getMaxActivationDistance())
{ {
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr); MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr);
if(animation)
{
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
int index = ESM::MagicEffect::effectStringToId("sEffectTelekinesis"); int index = ESM::MagicEffect::effectStringToId("sEffectTelekinesis");
const ESM::MagicEffect *effect = store.get<ESM::MagicEffect>().find(index); const ESM::MagicEffect *effect = store.get<ESM::MagicEffect>().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(); const std::string keyId = ptr.getCellRef().getKey();
if (!keyId.empty()) if (!keyId.empty())

@ -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"); static const bool smoothMovement = Settings::Manager::getBool("smooth movement", "Game");
mPathFinder.update(position, pointTolerance, DEFAULT_TOLERANCE, mPathFinder.update(position, pointTolerance, DEFAULT_TOLERANCE,
/*shortenIfAlmostStraight=*/smoothMovement, actorCanMoveByZ); /*shortenIfAlmostStraight=*/smoothMovement, actorCanMoveByZ,
halfExtents, getNavigatorFlags(actor));
if (isDestReached || mPathFinder.checkPathCompleted()) // if path is finished 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 float MWMechanics::AiPackage::getNextPathPointTolerance(float speed, float duration, const osg::Vec3f& halfExtents) const
{ {
if (mPathFinder.getPathSize() <= 1) if (mPathFinder.getPathSize() <= 1)
return mLastDestinationTolerance; return std::max(DEFAULT_TOLERANCE, mLastDestinationTolerance);
return getPointTolerance(speed, duration, halfExtents); return getPointTolerance(speed, duration, halfExtents);
} }

@ -105,6 +105,19 @@ namespace
return checkAngle && checkDist; 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 namespace MWMechanics
@ -296,7 +309,8 @@ namespace MWMechanics
} }
void PathFinder::update(const osg::Vec3f& position, float pointTolerance, float destinationTolerance, 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()) if (mPath.empty())
return; return;
@ -306,9 +320,15 @@ namespace MWMechanics
if (shortenIfAlmostStraight) 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); 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(); mPath.pop_front();
} }
@ -349,7 +369,13 @@ namespace MWMechanics
mPath.clear(); mPath.clear();
// If it's not possible to build path over navmesh due to disabled navmesh generation fallback to straight path // 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); mPath.push_back(endPoint);
mConstructed = !mPath.empty(); mConstructed = !mPath.empty();
@ -362,25 +388,33 @@ namespace MWMechanics
mPath.clear(); mPath.clear();
mCell = cell; mCell = cell;
bool hasNavMesh = false; DetourNavigator::Status status = DetourNavigator::Status::NavMeshNotFound;
if (!actor.getClass().isPureWaterCreature(actor) && !actor.getClass().isPureFlyingCreature(actor)) 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()) if (status != DetourNavigator::Status::NavMeshNotFound && mPath.empty())
buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, {
status = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents,
flags | DetourNavigator::Flag_usePathgrid, areaCosts, std::back_inserter(mPath)); flags | DetourNavigator::Flag_usePathgrid, areaCosts, std::back_inserter(mPath));
if (status != DetourNavigator::Status::Success)
mPath.clear();
}
if (mPath.empty()) if (mPath.empty())
buildPathByPathgridImpl(startPoint, endPoint, pathgridGraph, std::back_inserter(mPath)); buildPathByPathgridImpl(startPoint, endPoint, pathgridGraph, std::back_inserter(mPath));
if (!hasNavMesh && mPath.empty()) if (status == DetourNavigator::Status::NavMeshNotFound && mPath.empty())
mPath.push_back(endPoint); mPath.push_back(endPoint);
mConstructed = !mPath.empty(); 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 osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags,
const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator<std::deque<osg::Vec3f>> out) const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator<std::deque<osg::Vec3f>> out)
{ {
@ -389,9 +423,6 @@ namespace MWMechanics
const auto navigator = world->getNavigator(); const auto navigator = world->getNavigator();
const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, areaCosts, out); const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, areaCosts, out);
if (status == DetourNavigator::Status::NavMeshNotFound)
return false;
if (status != DetourNavigator::Status::Success) if (status != DetourNavigator::Status::Success)
{ {
Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status) Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status)
@ -400,7 +431,7 @@ namespace MWMechanics
<< DetourNavigator::WriteFlags {flags} << ")"; << DetourNavigator::WriteFlags {flags} << ")";
} }
return true; return status;
} }
void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents, void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,

@ -7,6 +7,7 @@
#include <components/detournavigator/flags.hpp> #include <components/detournavigator/flags.hpp>
#include <components/detournavigator/areatype.hpp> #include <components/detournavigator/areatype.hpp>
#include <components/detournavigator/status.hpp>
#include <components/esm/defs.hpp> #include <components/esm/defs.hpp>
#include <components/esm/loadpgrd.hpp> #include <components/esm/loadpgrd.hpp>
@ -107,7 +108,8 @@ namespace MWMechanics
/// Remove front point if exist and within tolerance /// Remove front point if exist and within tolerance
void update(const osg::Vec3f& position, float pointTolerance, float destinationTolerance, 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 bool checkPathCompleted() const
{ {
@ -208,9 +210,10 @@ namespace MWMechanics
void buildPathByPathgridImpl(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, void buildPathByPathgridImpl(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint,
const PathgridGraph& pathgridGraph, std::back_insert_iterator<std::deque<osg::Vec3f>> out); const PathgridGraph& pathgridGraph, std::back_insert_iterator<std::deque<osg::Vec3f>> out);
bool buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, [[nodiscard]] DetourNavigator::Status buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor,
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags, const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents,
const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator<std::deque<osg::Vec3f>> out); const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts,
std::back_insert_iterator<std::deque<osg::Vec3f>> out);
}; };
} }

@ -221,7 +221,7 @@ void FFmpeg_Decoder::open(const std::string &fname)
if(!mStream) if(!mStream)
throw std::runtime_error("No audio streams in "+fname); 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) if(!codec)
{ {
std::string ss = "No codec found for id " + std::string ss = "No codec found for id " +

@ -2829,7 +2829,14 @@ namespace MWWorld
MWRender::Animation* World::getAnimation(const MWWorld::Ptr &ptr) 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 const MWRender::Animation* World::getAnimation(const MWWorld::ConstPtr &ptr) const

@ -42,8 +42,8 @@ namespace
DetourNavigatorNavigatorTest() DetourNavigatorNavigatorTest()
: mPlayerPosition(0, 0, 0) : mPlayerPosition(0, 0, 0)
, mAgentHalfExtents(29, 29, 66) , mAgentHalfExtents(29, 29, 66)
, mStart(-215, 215, 1) , mStart(-204, 204, 1)
, mEnd(215, -215, 1) , mEnd(204, -204, 1)
, mOut(mPath) , mOut(mPath)
, mStepSize(28.333332061767578125f) , mStepSize(28.333332061767578125f)
{ {
@ -133,30 +133,29 @@ namespace
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
EXPECT_THAT(mPath, ElementsAre( EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(-215, 215, 1.85963428020477294921875), Vec3fEq(-204.0000152587890625, 204, 1.99998295307159423828125),
Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), Vec3fEq(-183.96533203125, 183.9653167724609375, 1.99998819828033447265625),
Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), Vec3fEq(-163.930633544921875, 163.9306182861328125, 1.99999344348907470703125),
Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), Vec3fEq(-143.8959503173828125, 143.89593505859375, -2.720611572265625),
Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), Vec3fEq(-123.86126708984375, 123.86124420166015625, -13.1089687347412109375),
Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), Vec3fEq(-103.82657623291015625, 103.8265533447265625, -23.497333526611328125),
Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), Vec3fEq(-83.7918853759765625, 83.7918548583984375, -33.885692596435546875),
Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), Vec3fEq(-63.757190704345703125, 63.757171630859375, -44.274051666259765625),
Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), Vec3fEq(-43.722503662109375, 43.72248077392578125, -54.66241455078125),
Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), Vec3fEq(-23.687808990478515625, 23.6877918243408203125, -65.05077362060546875),
Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), Vec3fEq(-3.6531188488006591796875, 3.6531002521514892578125, -75.43914031982421875),
Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), Vec3fEq(16.3815746307373046875, -16.381591796875, -69.74927520751953125),
Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), Vec3fEq(36.416263580322265625, -36.416286468505859375, -60.4739532470703125),
Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), Vec3fEq(56.450958251953125, -56.450977325439453125, -51.1986236572265625),
Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), Vec3fEq(76.48564910888671875, -76.4856719970703125, -41.92330169677734375),
Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), Vec3fEq(96.5203399658203125, -96.52036285400390625, -31.46941375732421875),
Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), Vec3fEq(116.55503082275390625, -116.5550537109375, -19.597003936767578125),
Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), Vec3fEq(136.5897216796875, -136.5897369384765625, -7.724592685699462890625),
Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), Vec3fEq(156.624420166015625, -156.624420166015625, 1.99999535083770751953125),
Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), Vec3fEq(176.6591033935546875, -176.65911865234375, 1.99999010562896728515625),
Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), Vec3fEq(196.69378662109375, -196.6938018798828125, 1.99998486042022705078125),
Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), Vec3fEq(204, -204.0000152587890625, 1.99998295307159423828125)
Vec3fEq(215, -215, 1.87718021869659423828125) )) << mPath;
));
} }
TEST_F(DetourNavigatorNavigatorTest, add_object_should_change_navmesh) 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_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
EXPECT_THAT(mPath, ElementsAre( EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(-215, 215, 1.85963428020477294921875), Vec3fEq(-204, 204, 1.99998295307159423828125),
Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), Vec3fEq(-183.965301513671875, 183.965301513671875, 1.99998819828033447265625),
Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), Vec3fEq(-163.9306182861328125, 163.9306182861328125, 1.99999344348907470703125),
Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), Vec3fEq(-143.89593505859375, 143.89593505859375, -2.7206256389617919921875),
Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), Vec3fEq(-123.86124420166015625, 123.86124420166015625, -13.1089839935302734375),
Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), Vec3fEq(-103.8265533447265625, 103.8265533447265625, -23.4973468780517578125),
Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), Vec3fEq(-83.7918548583984375, 83.7918548583984375, -33.885707855224609375),
Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), Vec3fEq(-63.75716400146484375, 63.75716400146484375, -44.27407073974609375),
Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), Vec3fEq(-43.72247314453125, 43.72247314453125, -54.662433624267578125),
Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -65.0507965087890625),
Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -75.43915557861328125),
Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -69.749267578125),
Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), Vec3fEq(36.416290283203125, -36.416290283203125, -60.4739532470703125),
Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), Vec3fEq(56.450984954833984375, -56.450984954833984375, -51.1986236572265625),
Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), Vec3fEq(76.4856719970703125, -76.4856719970703125, -41.92330169677734375),
Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), Vec3fEq(96.52036285400390625, -96.52036285400390625, -31.46941375732421875),
Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), Vec3fEq(116.5550537109375, -116.5550537109375, -19.597003936767578125),
Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), Vec3fEq(136.5897369384765625, -136.5897369384765625, -7.724592685699462890625),
Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), Vec3fEq(156.6244354248046875, -156.6244354248046875, 1.99999535083770751953125),
Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), Vec3fEq(176.6591339111328125, -176.6591339111328125, 1.99999010562896728515625),
Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), Vec3fEq(196.693817138671875, -196.693817138671875, 1.99998486042022705078125),
Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), Vec3fEq(204, -204, 1.99998295307159423828125)
Vec3fEq(215, -215, 1.87718021869659423828125) )) << mPath;
));
mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity()); mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity());
mNavigator->update(mPlayerPosition); mNavigator->update(mPlayerPosition);
@ -217,30 +215,30 @@ namespace
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
EXPECT_THAT(mPath, ElementsAre( EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(-215, 215, 1.87826788425445556640625), Vec3fEq(-204, 204, 1.99998295307159423828125),
Vec3fEq(-199.7968292236328125, 191.09100341796875, -3.54876613616943359375), Vec3fEq(-189.9427337646484375, 179.3997802734375, -3.622931003570556640625),
Vec3fEq(-184.5936431884765625, 167.1819915771484375, -8.97847843170166015625), Vec3fEq(-175.8854522705078125, 154.7995452880859375, -9.24583911895751953125),
Vec3fEq(-169.3904571533203125, 143.2729949951171875, -14.408184051513671875), Vec3fEq(-161.82818603515625, 130.1993255615234375, -14.86874866485595703125),
Vec3fEq(-154.1872711181640625, 119.36397552490234375, -19.837890625), Vec3fEq(-147.770904541015625, 105.5991058349609375, -20.4916591644287109375),
Vec3fEq(-138.9840850830078125, 95.45496368408203125, -25.2675991058349609375), Vec3fEq(-133.7136383056640625, 80.99887847900390625, -26.1145648956298828125),
Vec3fEq(-123.78090667724609375, 71.54595184326171875, -30.6973056793212890625), Vec3fEq(-119.65636444091796875, 56.39865875244140625, -31.7374725341796875),
Vec3fEq(-108.57772064208984375, 47.636936187744140625, -36.12701416015625), Vec3fEq(-105.59909820556640625, 31.798435211181640625, -26.133396148681640625),
Vec3fEq(-93.3745269775390625, 23.7279262542724609375, -40.754688262939453125), Vec3fEq(-91.54183197021484375, 7.1982135772705078125, -31.5624217987060546875),
Vec3fEq(-78.17134857177734375, -0.18108306825160980224609375, -37.128787994384765625), Vec3fEq(-77.48455810546875, -17.402008056640625, -26.98972320556640625),
Vec3fEq(-62.968158721923828125, -24.0900936126708984375, -33.50289154052734375), Vec3fEq(-63.427295684814453125, -42.00223541259765625, -19.9045581817626953125),
Vec3fEq(-47.764972686767578125, -47.999103546142578125, -30.797946929931640625), Vec3fEq(-42.193531036376953125, -60.761363983154296875, -20.4544773101806640625),
Vec3fEq(-23.852447509765625, -63.196765899658203125, -33.97112274169921875), Vec3fEq(-20.9597682952880859375, -79.5204925537109375, -23.599918365478515625),
Vec3fEq(0.0600789971649646759033203125, -78.39443206787109375, -37.14543914794921875), Vec3fEq(3.8312885761260986328125, -93.2384033203125, -30.7141361236572265625),
Vec3fEq(23.97260284423828125, -93.5920867919921875, -40.774089813232421875), Vec3fEq(28.6223468780517578125, -106.95632171630859375, -24.8243885040283203125),
Vec3fEq(47.885128021240234375, -108.78974151611328125, -36.05129241943359375), Vec3fEq(53.413402557373046875, -120.6742401123046875, -31.3303241729736328125),
Vec3fEq(71.7976531982421875, -123.98740386962890625, -30.6235561370849609375), Vec3fEq(78.20446014404296875, -134.39215087890625, -25.8431549072265625),
Vec3fEq(95.71018218994140625, -139.18505859375, -25.1958255767822265625), Vec3fEq(102.99552154541015625, -148.110076904296875, -20.3559894561767578125),
Vec3fEq(119.6226959228515625, -154.382720947265625, -19.7680912017822265625), Vec3fEq(127.7865753173828125, -161.827972412109375, -14.868824005126953125),
Vec3fEq(143.53521728515625, -169.58038330078125, -14.34035205841064453125), Vec3fEq(152.57763671875, -175.5458984375, -9.3816623687744140625),
Vec3fEq(167.4477386474609375, -184.778045654296875, -8.9126186370849609375), Vec3fEq(177.3686981201171875, -189.2638092041015625, -3.894496917724609375),
Vec3fEq(191.360260009765625, -199.9757080078125, -3.4848802089691162109375), Vec3fEq(202.1597442626953125, -202.9817047119140625, 1.59266507625579833984375),
Vec3fEq(215, -215, 1.87826788425445556640625) Vec3fEq(204, -204, 1.99998295307159423828125)
)); )) << mPath;
} }
TEST_F(DetourNavigatorNavigatorTest, update_changed_object_should_change_navmesh) 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_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
EXPECT_THAT(mPath, ElementsAre( EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(-215, 215, 1.87826788425445556640625), Vec3fEq(-204, 204, 1.99998295307159423828125),
Vec3fEq(-199.7968292236328125, 191.09100341796875, -3.54876613616943359375), Vec3fEq(-189.9427337646484375, 179.3997802734375, -3.622931003570556640625),
Vec3fEq(-184.5936431884765625, 167.1819915771484375, -8.97847843170166015625), Vec3fEq(-175.8854522705078125, 154.7995452880859375, -9.24583911895751953125),
Vec3fEq(-169.3904571533203125, 143.2729949951171875, -14.408184051513671875), Vec3fEq(-161.82818603515625, 130.1993255615234375, -14.86874866485595703125),
Vec3fEq(-154.1872711181640625, 119.36397552490234375, -19.837890625), Vec3fEq(-147.770904541015625, 105.5991058349609375, -20.4916591644287109375),
Vec3fEq(-138.9840850830078125, 95.45496368408203125, -25.2675991058349609375), Vec3fEq(-133.7136383056640625, 80.99887847900390625, -26.1145648956298828125),
Vec3fEq(-123.78090667724609375, 71.54595184326171875, -30.6973056793212890625), Vec3fEq(-119.65636444091796875, 56.39865875244140625, -31.7374725341796875),
Vec3fEq(-108.57772064208984375, 47.636936187744140625, -36.12701416015625), Vec3fEq(-105.59909820556640625, 31.798435211181640625, -26.133396148681640625),
Vec3fEq(-93.3745269775390625, 23.7279262542724609375, -40.754688262939453125), Vec3fEq(-91.54183197021484375, 7.1982135772705078125, -31.5624217987060546875),
Vec3fEq(-78.17134857177734375, -0.18108306825160980224609375, -37.128787994384765625), Vec3fEq(-77.48455810546875, -17.402008056640625, -26.98972320556640625),
Vec3fEq(-62.968158721923828125, -24.0900936126708984375, -33.50289154052734375), Vec3fEq(-63.427295684814453125, -42.00223541259765625, -19.9045581817626953125),
Vec3fEq(-47.764972686767578125, -47.999103546142578125, -30.797946929931640625), Vec3fEq(-42.193531036376953125, -60.761363983154296875, -20.4544773101806640625),
Vec3fEq(-23.852447509765625, -63.196765899658203125, -33.97112274169921875), Vec3fEq(-20.9597682952880859375, -79.5204925537109375, -23.599918365478515625),
Vec3fEq(0.0600789971649646759033203125, -78.39443206787109375, -37.14543914794921875), Vec3fEq(3.8312885761260986328125, -93.2384033203125, -30.7141361236572265625),
Vec3fEq(23.97260284423828125, -93.5920867919921875, -40.774089813232421875), Vec3fEq(28.6223468780517578125, -106.95632171630859375, -24.8243885040283203125),
Vec3fEq(47.885128021240234375, -108.78974151611328125, -36.05129241943359375), Vec3fEq(53.413402557373046875, -120.6742401123046875, -31.3303241729736328125),
Vec3fEq(71.7976531982421875, -123.98740386962890625, -30.6235561370849609375), Vec3fEq(78.20446014404296875, -134.39215087890625, -25.8431549072265625),
Vec3fEq(95.71018218994140625, -139.18505859375, -25.1958255767822265625), Vec3fEq(102.99552154541015625, -148.110076904296875, -20.3559894561767578125),
Vec3fEq(119.6226959228515625, -154.382720947265625, -19.7680912017822265625), Vec3fEq(127.7865753173828125, -161.827972412109375, -14.868824005126953125),
Vec3fEq(143.53521728515625, -169.58038330078125, -14.34035205841064453125), Vec3fEq(152.57763671875, -175.5458984375, -9.3816623687744140625),
Vec3fEq(167.4477386474609375, -184.778045654296875, -8.9126186370849609375), Vec3fEq(177.3686981201171875, -189.2638092041015625, -3.894496917724609375),
Vec3fEq(191.360260009765625, -199.9757080078125, -3.4848802089691162109375), Vec3fEq(202.1597442626953125, -202.9817047119140625, 1.59266507625579833984375),
Vec3fEq(215, -215, 1.87826788425445556640625) Vec3fEq(204, -204, 1.99998295307159423828125)
)); )) << mPath;
compoundShape.updateChildTransform(0, btTransform(btMatrix3x3::getIdentity(), btVector3(1000, 0, 0))); 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_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
EXPECT_THAT(mPath, ElementsAre( EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(-215, 215, 1.85963428020477294921875), Vec3fEq(-204, 204, 1.99998295307159423828125),
Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), Vec3fEq(-183.965301513671875, 183.965301513671875, 1.99998819828033447265625),
Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), Vec3fEq(-163.9306182861328125, 163.9306182861328125, 1.99999344348907470703125),
Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), Vec3fEq(-143.89593505859375, 143.89593505859375, -2.7206256389617919921875),
Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), Vec3fEq(-123.86124420166015625, 123.86124420166015625, -13.1089839935302734375),
Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), Vec3fEq(-103.8265533447265625, 103.8265533447265625, -23.4973468780517578125),
Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), Vec3fEq(-83.7918548583984375, 83.7918548583984375, -33.885707855224609375),
Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), Vec3fEq(-63.75716400146484375, 63.75716400146484375, -44.27407073974609375),
Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), Vec3fEq(-43.72247314453125, 43.72247314453125, -54.662433624267578125),
Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -65.0507965087890625),
Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -75.43915557861328125),
Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -69.749267578125),
Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), Vec3fEq(36.416290283203125, -36.416290283203125, -60.4739532470703125),
Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), Vec3fEq(56.450984954833984375, -56.450984954833984375, -51.1986236572265625),
Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), Vec3fEq(76.4856719970703125, -76.4856719970703125, -41.92330169677734375),
Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), Vec3fEq(96.52036285400390625, -96.52036285400390625, -31.46941375732421875),
Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), Vec3fEq(116.5550537109375, -116.5550537109375, -19.597003936767578125),
Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), Vec3fEq(136.5897369384765625, -136.5897369384765625, -7.724592685699462890625),
Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), Vec3fEq(156.6244354248046875, -156.6244354248046875, 1.99999535083770751953125),
Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), Vec3fEq(176.6591339111328125, -176.6591339111328125, 1.99999010562896728515625),
Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), Vec3fEq(196.693817138671875, -196.693817138671875, 1.99998486042022705078125),
Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), Vec3fEq(204, -204, 1.99998295307159423828125)
Vec3fEq(215, -215, 1.87718021869659423828125) )) << mPath;
));
} }
TEST_F(DetourNavigatorNavigatorTest, for_overlapping_heightfields_should_use_higher) 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_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
EXPECT_THAT(mPath, ElementsAre( EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(-215, 215, 1.96328866481781005859375), Vec3fEq(-204, 204, 1.999981403350830078125),
Vec3fEq(-194.9653167724609375, 194.9653167724609375, -0.242215454578399658203125), Vec3fEq(-183.965301513671875, 183.965301513671875, -0.428465187549591064453125),
Vec3fEq(-174.930633544921875, 174.930633544921875, -2.447719097137451171875), Vec3fEq(-163.9306182861328125, 163.9306182861328125, -2.8569104671478271484375),
Vec3fEq(-154.8959503173828125, 154.8959503173828125, -4.65322399139404296875), Vec3fEq(-143.89593505859375, 143.89593505859375, -5.28535556793212890625),
Vec3fEq(-134.86126708984375, 134.86126708984375, -6.858726978302001953125), Vec3fEq(-123.86124420166015625, 123.86124420166015625, -7.7138004302978515625),
Vec3fEq(-114.82657623291015625, 114.82657623291015625, -9.06423282623291015625), Vec3fEq(-103.8265533447265625, 103.8265533447265625, -10.142246246337890625),
Vec3fEq(-94.7918853759765625, 94.7918853759765625, -11.26973628997802734375), Vec3fEq(-83.7918548583984375, 83.7918548583984375, -12.3704509735107421875),
Vec3fEq(-74.75719451904296875, 74.75719451904296875, -13.26497173309326171875), Vec3fEq(-63.75716400146484375, 63.75716400146484375, -14.354084014892578125),
Vec3fEq(-54.722499847412109375, 54.722499847412109375, -15.24860477447509765625), Vec3fEq(-43.72247314453125, 43.72247314453125, -16.3377170562744140625),
Vec3fEq(-34.68780517578125, 34.68780517578125, -17.23223876953125), Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -18.32135009765625),
Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -19.215869903564453125), Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -20.3049831390380859375),
Vec3fEq(5.3815765380859375, -5.3815765380859375, -20.1338443756103515625), Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -19.044734954833984375),
Vec3fEq(25.41626739501953125, -25.41626739501953125, -18.1502132415771484375), Vec3fEq(36.416290283203125, -36.416290283203125, -17.061100006103515625),
Vec3fEq(45.450958251953125, -45.450958251953125, -16.1665802001953125), Vec3fEq(56.450984954833984375, -56.450984954833984375, -15.0774688720703125),
Vec3fEq(65.48564910888671875, -65.48564910888671875, -14.18294620513916015625), Vec3fEq(76.4856719970703125, -76.4856719970703125, -13.0938358306884765625),
Vec3fEq(85.5203399658203125, -85.5203399658203125, -12.199314117431640625), Vec3fEq(96.52036285400390625, -96.52036285400390625, -11.02784252166748046875),
Vec3fEq(105.55503082275390625, -105.55503082275390625, -10.08488368988037109375), Vec3fEq(116.5550537109375, -116.5550537109375, -8.5993976593017578125),
Vec3fEq(125.5897216796875, -125.5897216796875, -7.87938022613525390625), Vec3fEq(136.5897369384765625, -136.5897369384765625, -6.170953273773193359375),
Vec3fEq(145.6244049072265625, -145.6244049072265625, -5.673875331878662109375), Vec3fEq(156.6244354248046875, -156.6244354248046875, -3.74250507354736328125),
Vec3fEq(165.659088134765625, -165.659088134765625, -3.468370914459228515625), Vec3fEq(176.6591339111328125, -176.6591339111328125, -1.314060688018798828125),
Vec3fEq(185.6937713623046875, -185.6937713623046875, -1.26286637783050537109375), Vec3fEq(196.693817138671875, -196.693817138671875, 1.1143856048583984375),
Vec3fEq(205.7284698486328125, -205.7284698486328125, 0.942641556262969970703125), Vec3fEq(204, -204, 1.9999811649322509765625)
Vec3fEq(215, -215, 1.96328866481781005859375) )) << mPath;
));
} }
TEST_F(DetourNavigatorNavigatorTest, path_should_be_around_avoid_shape) 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_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
EXPECT_THAT(mPath, ElementsAre( EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(-215, 215, 1.9393787384033203125), Vec3fEq(-204, 204, 1.99997997283935546875),
Vec3fEq(-200.8159637451171875, 190.47265625, -0.639537751674652099609375), Vec3fEq(-191.328948974609375, 178.65789794921875, -0.815807759761810302734375),
Vec3fEq(-186.6319427490234375, 165.9453125, -3.2184507846832275390625), Vec3fEq(-178.65789794921875, 153.3157806396484375, -3.6315968036651611328125),
Vec3fEq(-172.447906494140625, 141.41796875, -5.797363758087158203125), Vec3fEq(-165.986846923828125, 127.9736785888671875, -6.4473857879638671875),
Vec3fEq(-158.263885498046875, 116.8906097412109375, -8.37627696990966796875), Vec3fEq(-153.3157806396484375, 102.6315765380859375, -9.26317310333251953125),
Vec3fEq(-144.079864501953125, 92.3632659912109375, -10.9551906585693359375), Vec3fEq(-140.6447296142578125, 77.28946685791015625, -12.07896137237548828125),
Vec3fEq(-129.89581298828125, 67.83591461181640625, -13.53410625457763671875), Vec3fEq(-127.9736785888671875, 51.947368621826171875, -14.894748687744140625),
Vec3fEq(-115.7117919921875, 43.308563232421875, -16.1130199432373046875), Vec3fEq(-115.3026275634765625, 26.6052646636962890625, -17.7105388641357421875),
Vec3fEq(-101.5277557373046875, 18.7812137603759765625, -18.6919345855712890625), Vec3fEq(-102.63158416748046875, 1.2631585597991943359375, -20.5263233184814453125),
Vec3fEq(-87.34372711181640625, -5.7461376190185546875, -20.4680538177490234375), Vec3fEq(-89.9605712890625, -24.0789661407470703125, -19.591716766357421875),
Vec3fEq(-67.02922821044921875, -25.4970550537109375, -20.514247894287109375), Vec3fEq(-68.54410552978515625, -42.629238128662109375, -19.847625732421875),
Vec3fEq(-46.714717864990234375, -45.2479705810546875, -20.560443878173828125), Vec3fEq(-47.127635955810546875, -61.17951202392578125, -20.1035366058349609375),
Vec3fEq(-26.40021514892578125, -64.99889373779296875, -20.6066417694091796875), Vec3fEq(-25.711170196533203125, -79.72978973388671875, -20.359447479248046875),
Vec3fEq(-6.085712432861328125, -84.74980926513671875, -20.652835845947265625), Vec3fEq(-4.294706821441650390625, -98.280059814453125, -20.6153545379638671875),
Vec3fEq(14.22879505157470703125, -104.50072479248046875, -18.151397705078125), Vec3fEq(17.121753692626953125, -116.83034515380859375, -17.3710460662841796875),
Vec3fEq(39.05098724365234375, -118.16222381591796875, -15.66748714447021484375), Vec3fEq(42.7990570068359375, -128.80755615234375, -14.7094440460205078125),
Vec3fEq(63.87317657470703125, -131.82373046875, -13.18358135223388671875), Vec3fEq(68.4763641357421875, -140.7847747802734375, -12.0478420257568359375),
Vec3fEq(88.69537353515625, -145.4852142333984375, -10.699672698974609375), Vec3fEq(94.15366363525390625, -152.761993408203125, -9.3862361907958984375),
Vec3fEq(113.51757049560546875, -159.146697998046875, -8.21576786041259765625), Vec3fEq(119.83097076416015625, -164.7392120361328125, -6.724635601043701171875),
Vec3fEq(138.3397674560546875, -172.808197021484375, -5.731859683990478515625), Vec3fEq(145.508270263671875, -176.7164306640625, -4.06303119659423828125),
Vec3fEq(163.1619720458984375, -186.469696044921875, -3.2479507923126220703125), Vec3fEq(171.185577392578125, -188.69366455078125, -1.40142619609832763671875),
Vec3fEq(187.984161376953125, -200.1311798095703125, -0.764044821262359619140625), Vec3fEq(196.862884521484375, -200.6708831787109375, 1.2601754665374755859375),
Vec3fEq(212.8063507080078125, -213.7926788330078125, 1.719865322113037109375), Vec3fEq(204, -204, 1.999979496002197265625)
Vec3fEq(215, -215, 1.9393787384033203125) )) << mPath;
));
} }
TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_water_ground_lower_than_water_with_only_swim_flag) 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(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mAreaCosts, mOut), Status::Success);
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({ EXPECT_THAT(mPath, ElementsAre(
osg::Vec3f(0, 215, 185.33331298828125), Vec3fEq(0, 204, 185.33331298828125),
osg::Vec3f(0, 186.6666717529296875, 185.33331298828125), Vec3fEq(0, 175.6666717529296875, 185.33331298828125),
osg::Vec3f(0, 158.333343505859375, 185.33331298828125), Vec3fEq(0, 147.3333282470703125, 185.33331298828125),
osg::Vec3f(0, 130.0000152587890625, 185.33331298828125), Vec3fEq(0, 119, 185.33331298828125),
osg::Vec3f(0, 101.66667938232421875, 185.33331298828125), Vec3fEq(0, 90.6666717529296875, 185.33331298828125),
osg::Vec3f(0, 73.333343505859375, 185.33331298828125), Vec3fEq(0, 62.333339691162109375, 185.33331298828125),
osg::Vec3f(0, 45.0000152587890625, 185.33331298828125), Vec3fEq(0, 34.00000762939453125, 185.33331298828125),
osg::Vec3f(0, 16.6666812896728515625, 185.33331298828125), Vec3fEq(0, 5.66667461395263671875, 185.33331298828125),
osg::Vec3f(0, -11.66664981842041015625, 185.33331298828125), Vec3fEq(0, -22.6666584014892578125, 185.33331298828125),
osg::Vec3f(0, -39.999980926513671875, 185.33331298828125), Vec3fEq(0, -50.999988555908203125, 185.33331298828125),
osg::Vec3f(0, -68.33331298828125, 185.33331298828125), Vec3fEq(0, -79.33332061767578125, 185.33331298828125),
osg::Vec3f(0, -96.66664886474609375, 185.33331298828125), Vec3fEq(0, -107.666656494140625, 185.33331298828125),
osg::Vec3f(0, -124.99997711181640625, 185.33331298828125), Vec3fEq(0, -135.9999847412109375, 185.33331298828125),
osg::Vec3f(0, -153.33331298828125, 185.33331298828125), Vec3fEq(0, -164.33331298828125, 185.33331298828125),
osg::Vec3f(0, -181.6666412353515625, 185.33331298828125), Vec3fEq(0, -192.666656494140625, 185.33331298828125),
osg::Vec3f(0, -209.999969482421875, 185.33331298828125), Vec3fEq(0, -204, 185.33331298828125)
osg::Vec3f(0, -215, 185.33331298828125), )) << mPath;
})) << mPath;
} }
TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_water_when_ground_cross_water_with_swim_and_walk_flags) 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), EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mOut),
Status::Success); Status::Success);
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({ EXPECT_THAT(mPath, ElementsAre(
osg::Vec3f(0, 215, -94.75363922119140625), Vec3fEq(0, 204, -98.000030517578125),
osg::Vec3f(0, 186.6666717529296875, -106.0000152587890625), Vec3fEq(0, 175.6666717529296875, -108.30306243896484375),
osg::Vec3f(0, 158.333343505859375, -115.85507965087890625), Vec3fEq(0, 147.3333282470703125, -118.6060791015625),
osg::Vec3f(0, 130.0000152587890625, -125.71016693115234375), Vec3fEq(0, 119, -128.90911865234375),
osg::Vec3f(0, 101.66667938232421875, -135.5652313232421875), Vec3fEq(0, 90.6666717529296875, -139.2121429443359375),
osg::Vec3f(0, 73.333343505859375, -143.3333587646484375), Vec3fEq(0, 62.333339691162109375, -143.3333587646484375),
osg::Vec3f(0, 45.0000152587890625, -143.3333587646484375), Vec3fEq(0, 34.00000762939453125, -143.3333587646484375),
osg::Vec3f(0, 16.6666812896728515625, -143.3333587646484375), Vec3fEq(0, 5.66667461395263671875, -143.3333587646484375),
osg::Vec3f(0, -11.66664981842041015625, -143.3333587646484375), Vec3fEq(0, -22.6666584014892578125, -143.3333587646484375),
osg::Vec3f(0, -39.999980926513671875, -143.3333587646484375), Vec3fEq(0, -50.999988555908203125, -143.3333587646484375),
osg::Vec3f(0, -68.33331298828125, -143.3333587646484375), Vec3fEq(0, -79.33332061767578125, -143.3333587646484375),
osg::Vec3f(0, -96.66664886474609375, -137.3043670654296875), Vec3fEq(0, -107.666656494140625, -133.0303192138671875),
osg::Vec3f(0, -124.99997711181640625, -127.44930267333984375), Vec3fEq(0, -135.9999847412109375, -122.72728729248046875),
osg::Vec3f(0, -153.33331298828125, -117.59423065185546875), Vec3fEq(0, -164.33331298828125, -112.4242706298828125),
osg::Vec3f(0, -181.6666412353515625, -107.73915863037109375), Vec3fEq(0, -192.666656494140625, -102.12123870849609375),
osg::Vec3f(0, -209.999969482421875, -97.7971343994140625), Vec3fEq(0, -204, -98.00002288818359375)
osg::Vec3f(0, -215, -94.75363922119140625), )) << mPath;
})) << mPath;
} }
TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_water_when_ground_cross_water_with_max_int_cells_size_and_swim_and_walk_flags) 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), EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mOut),
Status::Success); Status::Success);
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({ EXPECT_THAT(mPath, ElementsAre(
osg::Vec3f(0, 215, -94.75363922119140625), Vec3fEq(0, 204, -98.000030517578125),
osg::Vec3f(0, 186.6666717529296875, -106.0000152587890625), Vec3fEq(0, 175.6666717529296875, -108.30306243896484375),
osg::Vec3f(0, 158.333343505859375, -115.85507965087890625), Vec3fEq(0, 147.3333282470703125, -118.6060791015625),
osg::Vec3f(0, 130.0000152587890625, -125.71016693115234375), Vec3fEq(0, 119, -128.90911865234375),
osg::Vec3f(0, 101.66667938232421875, -135.5652313232421875), Vec3fEq(0, 90.6666717529296875, -139.2121429443359375),
osg::Vec3f(0, 73.333343505859375, -143.3333587646484375), Vec3fEq(0, 62.333339691162109375, -143.3333587646484375),
osg::Vec3f(0, 45.0000152587890625, -143.3333587646484375), Vec3fEq(0, 34.00000762939453125, -143.3333587646484375),
osg::Vec3f(0, 16.6666812896728515625, -143.3333587646484375), Vec3fEq(0, 5.66667461395263671875, -143.3333587646484375),
osg::Vec3f(0, -11.66664981842041015625, -143.3333587646484375), Vec3fEq(0, -22.6666584014892578125, -143.3333587646484375),
osg::Vec3f(0, -39.999980926513671875, -143.3333587646484375), Vec3fEq(0, -50.999988555908203125, -143.3333587646484375),
osg::Vec3f(0, -68.33331298828125, -143.3333587646484375), Vec3fEq(0, -79.33332061767578125, -143.3333587646484375),
osg::Vec3f(0, -96.66664886474609375, -137.3043670654296875), Vec3fEq(0, -107.666656494140625, -133.0303192138671875),
osg::Vec3f(0, -124.99997711181640625, -127.44930267333984375), Vec3fEq(0, -135.9999847412109375, -122.72728729248046875),
osg::Vec3f(0, -153.33331298828125, -117.59423065185546875), Vec3fEq(0, -164.33331298828125, -112.4242706298828125),
osg::Vec3f(0, -181.6666412353515625, -107.73915863037109375), Vec3fEq(0, -192.666656494140625, -102.12123870849609375),
osg::Vec3f(0, -209.999969482421875, -97.7971343994140625), Vec3fEq(0, -204, -98.00002288818359375)
osg::Vec3f(0, -215, -94.75363922119140625), )) << mPath;
})) << mPath;
} }
TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_ground_when_ground_cross_water_with_only_walk_flag) 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_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
EXPECT_THAT(mPath, ElementsAre( EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(0, 215, -94.75363922119140625), Vec3fEq(0, 204, -98.000030517578125),
Vec3fEq(9.8083515167236328125, 188.4185333251953125, -105.199951171875), Vec3fEq(10.26930999755859375, 177.59320068359375, -107.4711456298828125),
Vec3fEq(19.6167049407958984375, 161.837066650390625, -114.25495147705078125), Vec3fEq(20.5386199951171875, 151.1864166259765625, -116.9422607421875),
Vec3fEq(29.42505645751953125, 135.255615234375, -123.309967041015625), Vec3fEq(30.8079280853271484375, 124.77960968017578125, -126.41339111328125),
Vec3fEq(39.23340606689453125, 108.674163818359375, -132.3649749755859375), Vec3fEq(41.077239990234375, 98.37281036376953125, -135.8845062255859375),
Vec3fEq(49.04175567626953125, 82.09270477294921875, -137.2874755859375), Vec3fEq(51.346546173095703125, 71.96601104736328125, -138.2003936767578125),
Vec3fEq(58.8501129150390625, 55.5112457275390625, -139.2451171875), Vec3fEq(61.615856170654296875, 45.559215545654296875, -140.0838470458984375),
Vec3fEq(68.6584625244140625, 28.9297885894775390625, -141.2027740478515625), Vec3fEq(71.88516998291015625, 19.1524181365966796875, -141.9673004150390625),
Vec3fEq(78.4668121337890625, 2.3483295440673828125, -143.1604156494140625), Vec3fEq(82.15447235107421875, -7.254379749298095703125, -142.3074798583984375),
Vec3fEq(88.27516937255859375, -24.233127593994140625, -141.3894805908203125), Vec3fEq(81.04636383056640625, -35.56603240966796875, -142.7104339599609375),
Vec3fEq(83.73651885986328125, -52.2005767822265625, -142.3761444091796875), Vec3fEq(79.93825531005859375, -63.877685546875, -143.1133880615234375),
Vec3fEq(79.19786834716796875, -80.16802978515625, -143.114837646484375), Vec3fEq(78.83014678955078125, -92.18933868408203125, -138.7660675048828125),
Vec3fEq(64.8477935791015625, -104.598602294921875, -137.840911865234375), Vec3fEq(62.50392913818359375, -115.3460235595703125, -130.237823486328125),
Vec3fEq(50.497714996337890625, -129.0291748046875, -131.45831298828125), Vec3fEq(46.17771148681640625, -138.502716064453125, -121.8172149658203125),
Vec3fEq(36.147632598876953125, -153.459747314453125, -121.42321014404296875), Vec3fEq(29.85149383544921875, -161.6594085693359375, -113.39659881591796875),
Vec3fEq(21.7975559234619140625, -177.8903350830078125, -111.38811492919921875), Vec3fEq(13.52527523040771484375, -184.81610107421875, -104.97599029541015625),
Vec3fEq(7.44747829437255859375, -202.3209075927734375, -101.19382476806640625), Vec3fEq(0, -204, -98.00002288818359375)
Vec3fEq(0, -215, -94.75363922119140625) )) << mPath;
));
} }
TEST_F(DetourNavigatorNavigatorTest, update_remove_and_update_then_find_path_should_return_path) 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_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
EXPECT_THAT(mPath, ElementsAre( EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(-215, 215, 1.85963428020477294921875), Vec3fEq(-204, 204, 1.99998295307159423828125),
Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), Vec3fEq(-183.965301513671875, 183.965301513671875, 1.99998819828033447265625),
Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), Vec3fEq(-163.9306182861328125, 163.9306182861328125, 1.99999344348907470703125),
Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), Vec3fEq(-143.89593505859375, 143.89593505859375, -2.7206256389617919921875),
Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), Vec3fEq(-123.86124420166015625, 123.86124420166015625, -13.1089839935302734375),
Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), Vec3fEq(-103.8265533447265625, 103.8265533447265625, -23.4973468780517578125),
Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), Vec3fEq(-83.7918548583984375, 83.7918548583984375, -33.885707855224609375),
Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), Vec3fEq(-63.75716400146484375, 63.75716400146484375, -44.27407073974609375),
Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), Vec3fEq(-43.72247314453125, 43.72247314453125, -54.662433624267578125),
Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -65.0507965087890625),
Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -75.43915557861328125),
Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -69.749267578125),
Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), Vec3fEq(36.416290283203125, -36.416290283203125, -60.4739532470703125),
Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), Vec3fEq(56.450984954833984375, -56.450984954833984375, -51.1986236572265625),
Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), Vec3fEq(76.4856719970703125, -76.4856719970703125, -41.92330169677734375),
Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), Vec3fEq(96.52036285400390625, -96.52036285400390625, -31.46941375732421875),
Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), Vec3fEq(116.5550537109375, -116.5550537109375, -19.597003936767578125),
Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), Vec3fEq(136.5897369384765625, -136.5897369384765625, -7.724592685699462890625),
Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), Vec3fEq(156.6244354248046875, -156.6244354248046875, 1.99999535083770751953125),
Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), Vec3fEq(176.6591339111328125, -176.6591339111328125, 1.99999010562896728515625),
Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), Vec3fEq(196.693817138671875, -196.693817138671875, 1.99998486042022705078125),
Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), Vec3fEq(204, -204, 1.99998295307159423828125)
Vec3fEq(215, -215, 1.87718021869659423828125) )) << mPath;
));
} }
TEST_F(DetourNavigatorNavigatorTest, update_then_find_random_point_around_circle_should_return_position) 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); 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(); 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) 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_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success);
EXPECT_THAT(mPath, ElementsAre( EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(-215, 215, 1.8782780170440673828125), Vec3fEq(-204, 204, 1.99998295307159423828125),
Vec3fEq(-199.7968292236328125, 191.09100341796875, -3.54875946044921875), Vec3fEq(-189.9427337646484375, 179.3997802734375, 1.9999866485595703125),
Vec3fEq(-184.5936431884765625, 167.1819915771484375, -8.97846889495849609375), Vec3fEq(-175.8854522705078125, 154.7995452880859375, 1.99999034404754638671875),
Vec3fEq(-169.3904571533203125, 143.2729949951171875, -14.40818119049072265625), Vec3fEq(-161.82818603515625, 130.1993255615234375, -3.701923847198486328125),
Vec3fEq(-154.1872711181640625, 119.363983154296875, -19.837886810302734375), Vec3fEq(-147.770904541015625, 105.5991058349609375, -15.67664432525634765625),
Vec3fEq(-138.9840850830078125, 95.4549713134765625, -25.2675952911376953125), Vec3fEq(-133.7136383056640625, 80.99887847900390625, -27.6513614654541015625),
Vec3fEq(-123.78090667724609375, 71.54595947265625, -30.6973056793212890625), Vec3fEq(-119.65636444091796875, 56.39865875244140625, -20.1209163665771484375),
Vec3fEq(-108.57772064208984375, 47.63695526123046875, -36.12701416015625), Vec3fEq(-105.59909820556640625, 31.798435211181640625, -25.0669879913330078125),
Vec3fEq(-93.3745269775390625, 23.72794342041015625, -40.754695892333984375), Vec3fEq(-91.54183197021484375, 7.1982135772705078125, -31.5624217987060546875),
Vec3fEq(-78.17134857177734375, -0.18106450140476226806640625, -37.128795623779296875), Vec3fEq(-77.48455810546875, -17.402008056640625, -26.98972320556640625),
Vec3fEq(-62.968158721923828125, -24.0900726318359375, -33.50289154052734375), Vec3fEq(-63.427295684814453125, -42.00223541259765625, -19.9045581817626953125),
Vec3fEq(-47.764972686767578125, -47.99908447265625, -30.797946929931640625), Vec3fEq(-42.193531036376953125, -60.761363983154296875, -20.4544773101806640625),
Vec3fEq(-23.8524494171142578125, -63.196746826171875, -33.97112274169921875), Vec3fEq(-20.9597682952880859375, -79.5204925537109375, -23.599918365478515625),
Vec3fEq(0.0600722394883632659912109375, -78.3944091796875, -37.14543914794921875), Vec3fEq(3.8312885761260986328125, -93.2384033203125, -30.7141361236572265625),
Vec3fEq(23.97259521484375, -93.592071533203125, -40.774089813232421875), Vec3fEq(28.6223468780517578125, -106.95632171630859375, -24.1782474517822265625),
Vec3fEq(47.885120391845703125, -108.78974151611328125, -36.051296234130859375), Vec3fEq(53.413402557373046875, -120.6742401123046875, -19.4096889495849609375),
Vec3fEq(71.797637939453125, -123.98740386962890625, -30.62355804443359375), Vec3fEq(78.20446014404296875, -134.39215087890625, -27.6632633209228515625),
Vec3fEq(95.71016693115234375, -139.18505859375, -25.195819854736328125), Vec3fEq(102.99552154541015625, -148.110076904296875, -15.8613681793212890625),
Vec3fEq(119.6226806640625, -154.382720947265625, -19.768085479736328125), Vec3fEq(127.7865753173828125, -161.827972412109375, -4.059485912322998046875),
Vec3fEq(143.5352020263671875, -169.5803680419921875, -14.34035015106201171875), Vec3fEq(152.57763671875, -175.5458984375, 1.9999904632568359375),
Vec3fEq(167.447723388671875, -184.7780303955078125, -8.912616729736328125), Vec3fEq(177.3686981201171875, -189.2638092041015625, 1.9999866485595703125),
Vec3fEq(191.3602294921875, -199.9756927490234375, -3.48488140106201171875), Vec3fEq(202.1597442626953125, -202.9817047119140625, 1.9999830722808837890625),
Vec3fEq(215, -215, 1.8782813549041748046875) Vec3fEq(204, -204, 1.99998295307159423828125)
)) << mPath; )) << mPath;
} }
@ -836,7 +827,8 @@ namespace
const auto result = mNavigator->raycast(mAgentHalfExtents, mStart, mEnd, Flag_walk); 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) TEST_F(DetourNavigatorNavigatorTest, update_for_oscillating_object_that_does_not_change_navmesh_should_not_trigger_navmesh_update)

@ -266,6 +266,7 @@ if (BUILD_OPENMW OR BUILD_OPENCS)
raycast raycast
navmeshtileview navmeshtileview
oscillatingrecastmeshobject oscillatingrecastmeshobject
offmeshconnectionsmanager
) )
endif() endif()
# End of tes3mp change (major) # End of tes3mp change (major)

@ -1,5 +1,7 @@
#include "findsmoothpath.hpp" #include "findsmoothpath.hpp"
#include <components/misc/convert.hpp>
#include <algorithm> #include <algorithm>
#include <array> #include <array>
@ -103,7 +105,7 @@ namespace DetourNavigator
return result; return result;
} }
std::optional<SteerTarget> getSteerTarget(const dtNavMeshQuery& navQuery, const osg::Vec3f& startPos, std::optional<SteerTarget> getSteerTarget(const dtNavMeshQuery& navMeshQuery, const osg::Vec3f& startPos,
const osg::Vec3f& endPos, const float minTargetDist, const std::vector<dtPolyRef>& path) const osg::Vec3f& endPos, const float minTargetDist, const std::vector<dtPolyRef>& path)
{ {
// Find steer target. // Find steer target.
@ -113,8 +115,11 @@ namespace DetourNavigator
std::array<unsigned char, maxSteerPoints> steerPathFlags; std::array<unsigned char, maxSteerPoints> steerPathFlags;
std::array<dtPolyRef, maxSteerPoints> steerPathPolys; std::array<dtPolyRef, maxSteerPoints> steerPathPolys;
int nsteerPath = 0; int nsteerPath = 0;
navQuery.findStraightPath(startPos.ptr(), endPos.ptr(), path.data(), int(path.size()), steerPath.data(), const dtStatus status = navMeshQuery.findStraightPath(startPos.ptr(), endPos.ptr(), path.data(),
steerPathFlags.data(), steerPathPolys.data(), &nsteerPath, maxSteerPoints); static_cast<int>(path.size()), steerPath.data(), steerPathFlags.data(), steerPathPolys.data(),
&nsteerPath, maxSteerPoints);
if (dtStatusFailed(status))
return std::nullopt;
assert(nsteerPath >= 0); assert(nsteerPath >= 0);
if (!nsteerPath) if (!nsteerPath)
return std::nullopt; return std::nullopt;
@ -125,7 +130,7 @@ namespace DetourNavigator
{ {
// Stop at Off-Mesh link or when point is further than slop away. // Stop at Off-Mesh link or when point is further than slop away.
if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || 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; break;
ns++; ns++;
} }

@ -14,9 +14,8 @@
#include <DetourNavMesh.h> #include <DetourNavMesh.h>
#include <DetourNavMeshQuery.h> #include <DetourNavMeshQuery.h>
#include <components/misc/convert.hpp>
#include <osg/Vec3f> #include <osg/Vec3f>
#include <cassert> #include <cassert>
#include <vector> #include <vector>
@ -26,10 +25,9 @@ namespace DetourNavigator
{ {
struct Settings; 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 (osg::Vec2f(v1.x(), v1.z()) - osg::Vec2f(v2.x(), v2.z())).length() < r;
return (d.x() * d.x() + d.z() * d.z()) < r * r && std::abs(d.y()) < h;
} }
std::vector<dtPolyRef> fixupCorridor(const std::vector<dtPolyRef>& path, const std::vector<dtPolyRef>& visited); std::vector<dtPolyRef> fixupCorridor(const std::vector<dtPolyRef>& path, const std::vector<dtPolyRef>& visited);
@ -143,15 +141,6 @@ namespace DetourNavigator
return {std::move(result)}; return {std::move(result)};
} }
inline std::optional<float> 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 <class OutputIterator> template <class OutputIterator>
Status makeSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery, Status makeSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery,
const dtQueryFilter& filter, const osg::Vec3f& start, const osg::Vec3f& end, const float stepSize, 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 = fixupCorridor(polygonPath, result->mVisited);
polygonPath = fixupShortcuts(polygonPath, navMeshQuery); 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. // 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. // Reached end of path.
iterPos = targetPos; iterPos = targetPos;
@ -215,7 +199,7 @@ namespace DetourNavigator
++smoothPathSize; ++smoothPathSize;
break; 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. // Advance the path up to and over the off-mesh connection.
dtPolyRef prevRef = 0; dtPolyRef prevRef = 0;
@ -249,16 +233,18 @@ namespace DetourNavigator
} }
// Move position at the other side of the off-mesh link. // Move position at the other side of the off-mesh link.
iterPos = endPos; if (dtStatusFailed(navMeshQuery.getPolyHeight(polygonPath.front(), endPos.ptr(), &iterPos.y())))
const auto height = getPolyHeight(navMeshQuery, polygonPath.front(), iterPos);
if (!height)
return Status::GetPolyHeightFailed; return Status::GetPolyHeightFailed;
iterPos.x() = endPos.x();
iterPos.y() = *height; 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. // Store results.
*out++ = iterPos; *out++ = iterPos;
++smoothPathSize; ++smoothPathSize;

@ -389,7 +389,7 @@ namespace
const auto offMeshConVerts = getOffMeshVerts(offMeshConnections); const auto offMeshConVerts = getOffMeshVerts(offMeshConnections);
const std::vector<float> offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents)); const std::vector<float> offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents));
const std::vector<unsigned char> offMeshConDir(offMeshConnections.size(), DT_OFFMESH_CON_BIDIR); const std::vector<unsigned char> offMeshConDir(offMeshConnections.size(), 0);
const std::vector<unsigned char> offMeshConAreas = getOffMeshConAreas(offMeshConnections); const std::vector<unsigned char> offMeshConAreas = getOffMeshConAreas(offMeshConnections);
const std::vector<unsigned short> offMeshConFlags = getOffMeshFlags(offMeshConnections); const std::vector<unsigned short> offMeshConFlags = getOffMeshFlags(offMeshConnections);

@ -55,12 +55,10 @@ namespace DetourNavigator
{ {
if (addObject(id, static_cast<const ObjectShapes&>(shapes), transform)) if (addObject(id, static_cast<const ObjectShapes&>(shapes), transform))
{ {
mNavMeshManager.addOffMeshConnection( const osg::Vec3f start = toNavMeshCoordinates(mSettings, shapes.mConnectionStart);
id, const osg::Vec3f end = toNavMeshCoordinates(mSettings, shapes.mConnectionEnd);
toNavMeshCoordinates(mSettings, shapes.mConnectionStart), mNavMeshManager.addOffMeshConnection(id, start, end, AreaType_door);
toNavMeshCoordinates(mSettings, shapes.mConnectionEnd), mNavMeshManager.addOffMeshConnection(id, end, start, AreaType_door);
AreaType_door
);
return true; return true;
} }
return false; return false;

@ -0,0 +1,95 @@
#include "offmeshconnectionsmanager.hpp"
#include "settings.hpp"
#include "settingsutils.hpp"
#include "tileposition.hpp"
#include "objectid.hpp"
#include "offmeshconnection.hpp"
#include <algorithm>
#include <vector>
#include <set>
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<TilePosition> 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<TilePosition> 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<OffMeshConnection> OffMeshConnectionsManager::get(const TilePosition& tilePosition)
{
std::vector<OffMeshConnection> 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;
}
}

@ -2,16 +2,12 @@
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTIONSMANAGER_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTIONSMANAGER_H
#include "settings.hpp" #include "settings.hpp"
#include "settingsutils.hpp"
#include "tileposition.hpp" #include "tileposition.hpp"
#include "objectid.hpp" #include "objectid.hpp"
#include "offmeshconnection.hpp" #include "offmeshconnection.hpp"
#include <components/misc/guarded.hpp> #include <components/misc/guarded.hpp>
#include <osg/Vec3f>
#include <algorithm>
#include <map> #include <map>
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
@ -22,73 +18,13 @@ namespace DetourNavigator
class OffMeshConnectionsManager class OffMeshConnectionsManager
{ {
public: public:
OffMeshConnectionsManager(const Settings& settings) 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); void add(const ObjectId id, const OffMeshConnection& value);
const auto endTilePosition = getTilePosition(mSettings, value.mEnd);
values->mByTilePosition[startTilePosition].insert(id); std::set<TilePosition> remove(const ObjectId id);
if (startTilePosition != endTilePosition)
values->mByTilePosition[endTilePosition].insert(id);
}
std::set<TilePosition> remove(const ObjectId id)
{
const auto values = mValues.lock();
const auto byId = values->mById.equal_range(id); std::vector<OffMeshConnection> get(const TilePosition& tilePosition);
if (byId.first == byId.second) {
return {};
}
std::set<TilePosition> 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);
});
values->mById.erase(byId.first, byId.second);
return removed;
}
std::vector<OffMeshConnection> get(const TilePosition& tilePosition)
{
std::vector<OffMeshConnection> 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;
}
private: private:
struct Values struct Values
@ -99,14 +35,6 @@ namespace DetourNavigator
const Settings& mSettings; const Settings& mSettings;
Misc::ScopeGuarded<Values> mValues; Misc::ScopeGuarded<Values> mValues;
void removeByTilePosition(std::map<TilePosition, std::unordered_set<ObjectId>>& valuesByTilePosition,
const TilePosition& tilePosition, const ObjectId id)
{
const auto it = valuesByTilePosition.find(tilePosition);
if (it != valuesByTilePosition.end())
it->second.erase(id);
}
}; };
} }

@ -12,7 +12,8 @@
#include <osg/Vec2i> #include <osg/Vec2i>
#include <osg/Vec3f> #include <osg/Vec3f>
#include <utility> #include <algorithm>
#include <cmath>
namespace DetourNavigator namespace DetourNavigator
{ {
@ -28,7 +29,7 @@ namespace DetourNavigator
inline float getRadius(const Settings& settings, const osg::Vec3f& agentHalfExtents) 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) inline float toNavMeshCoordinates(const Settings& settings, float value)

@ -69,6 +69,15 @@ float Manager::getFloat (const std::string& setting, const std::string& category
return number; 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) int Manager::getInt (const std::string& setting, const std::string& category)
{ {
const std::string& value = getString(setting, 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()); 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) void Manager::setBool(const std::string &setting, const std::string &category, const bool value)
{ {
setString(setting, category, value ? "true" : "false"); setString(setting, category, value ? "true" : "false");

@ -52,6 +52,7 @@ namespace Settings
static int getInt (const std::string& setting, const std::string& category); static int getInt (const std::string& setting, const std::string& category);
static float getFloat (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 std::string getString (const std::string& setting, const std::string& category);
static bool getBool (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); 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 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 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 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 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); static void setVector2 (const std::string& setting, const std::string& category, const osg::Vec2f value);

@ -280,10 +280,12 @@ namespace Shader
osg::StateSet::AttributeList removedAttributes; osg::StateSet::AttributeList removedAttributes;
if (osg::ref_ptr<osg::StateSet> removedState = getRemovedState(*stateset)) if (osg::ref_ptr<osg::StateSet> removedState = getRemovedState(*stateset))
removedAttributes = removedState->getAttributeList(); removedAttributes = removedState->getAttributeList();
for (const auto& attributeMap : { attributes, removedAttributes }) for (const auto* attributeMap : std::initializer_list<const osg::StateSet::AttributeList*>{ &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) 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 // 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)); writableStateSet->addUniform(new osg::Uniform("alphaRef", reqs.mAlphaRef));
if (!removedState->getAttributePair(osg::StateAttribute::ALPHAFUNC))
{
const auto* alphaFunc = writableStateSet->getAttributePair(osg::StateAttribute::ALPHAFUNC); const auto* alphaFunc = writableStateSet->getAttributePair(osg::StateAttribute::ALPHAFUNC);
if (alphaFunc) if (alphaFunc)
removedState->setAttribute(alphaFunc->first, alphaFunc->second); removedState->setAttribute(alphaFunc->first, alphaFunc->second);
}
// This prevents redundant glAlphaFunc calls while letting the shadows bin still see the test // 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); writableStateSet->setAttribute(RemovedAlphaFunc::getInstance(reqs.mAlphaFunc), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

@ -20,6 +20,7 @@ about creating new content for OpenMW, please refer to
foreword foreword
differences differences
mod-install mod-install
openmw-game-template
settings/index settings/index
texture-modding/index texture-modding/index
custom-models/index custom-models/index

@ -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 <https://creativecommons.org/publicdomain/zero/1.0/>`_.
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 <https://gitlab.com/OpenMW/example-suite>`_ 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!

@ -71,7 +71,7 @@ MovieAudioDecoder::MovieAudioDecoder(VideoState* videoState)
{ {
mAudioResampler.reset(new AudioResampler()); 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) if(!codec)
{ {
std::string ss = "No codec found for id " + std::string ss = "No codec found for id " +

@ -632,7 +632,7 @@ bool VideoState::update()
int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx) int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx)
{ {
AVCodec *codec; const AVCodec *codec;
if(stream_index < 0 || stream_index >= static_cast<int>(pFormatCtx->nb_streams)) if(stream_index < 0 || stream_index >= static_cast<int>(pFormatCtx->nb_streams))
return -1; return -1;

@ -478,6 +478,36 @@
</layout> </layout>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<layout class="QHBoxLayout" name="objectPagingMinSizeLayout">
<item>
<widget class="QLabel" name="objectPagingMinSizeLabel">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Controls how large an object must be to be visible in the scene. The objects 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.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Object paging min size</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="objectPagingMinSizeComboBox">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>0.250000000000000</double>
</property>
<property name="singleStep">
<double>0.005000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="distantLandCheckBox"> <widget class="QCheckBox" name="distantLandCheckBox">
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If true, use paging and LOD algorithms to display the entire terrain. If false, only display terrain of the loaded cells.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If true, use paging and LOD algorithms to display the entire terrain. If false, only display terrain of the loaded cells.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -487,7 +517,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<layout class="QVBoxLayout" name="distantLandLayout"> <layout class="QVBoxLayout" name="distantLandLayout">
<property name="leftMargin"> <property name="leftMargin">
<number>20</number> <number>20</number>

Loading…
Cancel
Save