From c32872fb16fe826c5409e31111bd50466595abf5 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 15 Aug 2019 19:19:04 +0200 Subject: [PATCH 1/5] Open door when it is on the way to a next path point --- apps/openmw/mwbase/world.hpp | 2 ++ apps/openmw/mwmechanics/aipackage.cpp | 18 ++++++++++++++++++ apps/openmw/mwmechanics/aipackage.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 9 +++++++-- apps/openmw/mwworld/worldimp.hpp | 2 ++ 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 256c8b1d5..08642eb7f 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -306,6 +306,8 @@ namespace MWBase virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2) = 0; + virtual MWWorld::Ptr castRay(const osg::Vec3f& from, const osg::Vec3f& to, int mask) const = 0; + virtual void setActorCollisionMode(const MWWorld::Ptr& ptr, bool internal, bool external) = 0; virtual bool isActorCollisionEnabled(const MWWorld::Ptr& ptr) = 0; diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 598292fc3..4395f1e4b 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -13,6 +13,8 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwphysics/collisiontype.hpp" + #include "pathgrid.hpp" #include "creaturestats.hpp" #include "movement.hpp" @@ -234,6 +236,9 @@ void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor) // note: AiWander currently does not open doors if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == 0) { + if (!isDoorOnTheWay(actor, door)) + return; + if ((door.getCellRef().getTrap().empty() && door.getCellRef().getLockLevel() <= 0 )) { world->activate(door, actor); @@ -402,3 +407,16 @@ DetourNavigator::Flags MWMechanics::AiPackage::getNavigatorFlags(const MWWorld:: return result; } + +bool MWMechanics::AiPackage::isDoorOnTheWay(const MWWorld::Ptr& actor, const MWWorld::Ptr& door) const +{ + if (mPathFinder.getPathSize() == 0) + return false; + + const auto world = MWBase::Environment::get().getWorld(); + const auto halfExtents = world->getHalfExtents(actor); + const auto position = actor.getRefData().getPosition().asVec3() + osg::Vec3f(0, 0, halfExtents.z()); + const auto destination = mPathFinder.getPath().front() + osg::Vec3f(0, 0, halfExtents.z()); + + return world->castRay(position, destination, MWPhysics::CollisionType_Door) == door; +} diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 6bb12342a..0f7b5cf1d 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -147,6 +147,8 @@ namespace MWMechanics private: bool isNearInactiveCell(osg::Vec3f position); + + bool isDoorOnTheWay(const MWWorld::Ptr& actor, const MWWorld::Ptr& door) const; }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ce253b8ba..d285d04ca 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1610,8 +1610,13 @@ namespace MWWorld osg::Vec3f a(x1,y1,z1); osg::Vec3f b(x2,y2,z2); - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(a, b, MWWorld::Ptr(), std::vector(), mask); - return result.mHit; + return !castRay(a, b, mask).isEmpty(); + } + + MWWorld::Ptr World::castRay(const osg::Vec3f& from, const osg::Vec3f& to, int mask) const + { + const auto result = mPhysics->castRay(from, to, MWWorld::Ptr(), std::vector(), mask); + return result.mHit ? result.mHitObject : MWWorld::Ptr(); } void World::processDoors(float duration) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index dd915c8bd..0acbc5926 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -420,6 +420,8 @@ namespace MWWorld bool castRay (float x1, float y1, float z1, float x2, float y2, float z2) override; + MWWorld::Ptr castRay (const osg::Vec3f& from, const osg::Vec3f& to, int mask) const override; + void setActorCollisionMode(const Ptr& ptr, bool internal, bool external) override; bool isActorCollisionEnabled(const Ptr& ptr) override; From 69b4fe8545264efeeedf5925e10b10f0f7faf236 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 27 Aug 2019 20:49:07 +0200 Subject: [PATCH 2/5] Revert "Open door when it is on the way to a next path point" This reverts commit c32872fb16fe826c5409e31111bd50466595abf5. --- apps/openmw/mwbase/world.hpp | 2 -- apps/openmw/mwmechanics/aipackage.cpp | 18 ------------------ apps/openmw/mwmechanics/aipackage.hpp | 2 -- apps/openmw/mwworld/worldimp.cpp | 9 ++------- apps/openmw/mwworld/worldimp.hpp | 2 -- 5 files changed, 2 insertions(+), 31 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 08642eb7f..256c8b1d5 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -306,8 +306,6 @@ namespace MWBase virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2) = 0; - virtual MWWorld::Ptr castRay(const osg::Vec3f& from, const osg::Vec3f& to, int mask) const = 0; - virtual void setActorCollisionMode(const MWWorld::Ptr& ptr, bool internal, bool external) = 0; virtual bool isActorCollisionEnabled(const MWWorld::Ptr& ptr) = 0; diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 4395f1e4b..598292fc3 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -13,8 +13,6 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/inventorystore.hpp" -#include "../mwphysics/collisiontype.hpp" - #include "pathgrid.hpp" #include "creaturestats.hpp" #include "movement.hpp" @@ -236,9 +234,6 @@ void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor) // note: AiWander currently does not open doors if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == 0) { - if (!isDoorOnTheWay(actor, door)) - return; - if ((door.getCellRef().getTrap().empty() && door.getCellRef().getLockLevel() <= 0 )) { world->activate(door, actor); @@ -407,16 +402,3 @@ DetourNavigator::Flags MWMechanics::AiPackage::getNavigatorFlags(const MWWorld:: return result; } - -bool MWMechanics::AiPackage::isDoorOnTheWay(const MWWorld::Ptr& actor, const MWWorld::Ptr& door) const -{ - if (mPathFinder.getPathSize() == 0) - return false; - - const auto world = MWBase::Environment::get().getWorld(); - const auto halfExtents = world->getHalfExtents(actor); - const auto position = actor.getRefData().getPosition().asVec3() + osg::Vec3f(0, 0, halfExtents.z()); - const auto destination = mPathFinder.getPath().front() + osg::Vec3f(0, 0, halfExtents.z()); - - return world->castRay(position, destination, MWPhysics::CollisionType_Door) == door; -} diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 0f7b5cf1d..6bb12342a 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -147,8 +147,6 @@ namespace MWMechanics private: bool isNearInactiveCell(osg::Vec3f position); - - bool isDoorOnTheWay(const MWWorld::Ptr& actor, const MWWorld::Ptr& door) const; }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d285d04ca..ce253b8ba 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1610,13 +1610,8 @@ namespace MWWorld osg::Vec3f a(x1,y1,z1); osg::Vec3f b(x2,y2,z2); - return !castRay(a, b, mask).isEmpty(); - } - - MWWorld::Ptr World::castRay(const osg::Vec3f& from, const osg::Vec3f& to, int mask) const - { - const auto result = mPhysics->castRay(from, to, MWWorld::Ptr(), std::vector(), mask); - return result.mHit ? result.mHitObject : MWWorld::Ptr(); + MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(a, b, MWWorld::Ptr(), std::vector(), mask); + return result.mHit; } void World::processDoors(float duration) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 0acbc5926..dd915c8bd 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -420,8 +420,6 @@ namespace MWWorld bool castRay (float x1, float y1, float z1, float x2, float y2, float z2) override; - MWWorld::Ptr castRay (const osg::Vec3f& from, const osg::Vec3f& to, int mask) const override; - void setActorCollisionMode(const Ptr& ptr, bool internal, bool external) override; bool isActorCollisionEnabled(const Ptr& ptr) override; From 389f5dfb9b834e012d464abf41c578d1c03ffe7d Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 25 Aug 2019 18:11:13 +0200 Subject: [PATCH 3/5] Check for AiPackage type before find nearby door --- apps/openmw/mwmechanics/aipackage.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 646b37669..97523f2d6 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -224,6 +224,10 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor) void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor) { + // note: AiWander currently does not open doors + if (getTypeId() == TypeIdWander) + return; + MWBase::World* world = MWBase::Environment::get().getWorld(); static float distance = world->getMaxActivationDistance(); @@ -231,8 +235,7 @@ void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor) if (door == MWWorld::Ptr()) return; - // note: AiWander currently does not open doors - if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == MWWorld::DoorState::Idle) + if (!door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == MWWorld::DoorState::Idle) { if ((door.getCellRef().getTrap().empty() && door.getCellRef().getLockLevel() <= 0 )) { From 97cd9d434a8cbcf689dd046afb0fb216451d29f8 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 25 Aug 2019 13:49:04 +0200 Subject: [PATCH 4/5] Do not open doors when actor has no path When actor is not going anywhere it doesn't require to go through doors so there is no need to open them. --- apps/openmw/mwmechanics/aipackage.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 97523f2d6..ef22d986a 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -228,6 +228,9 @@ void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor) if (getTypeId() == TypeIdWander) return; + if (mPathFinder.getPathSize() == 0) + return; + MWBase::World* world = MWBase::Environment::get().getWorld(); static float distance = world->getMaxActivationDistance(); From b4ec4440573979b222a5c8be5296e8fb80772282 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 15 Aug 2019 19:19:04 +0200 Subject: [PATCH 5/5] Open door when it is on the way to a next path point --- apps/openmw/mwbase/world.hpp | 2 ++ apps/openmw/mwmechanics/aipackage.cpp | 15 +++++++++++++++ apps/openmw/mwmechanics/aipackage.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 20 ++++++++++++++++++++ apps/openmw/mwworld/worldimp.hpp | 2 ++ 5 files changed, 41 insertions(+) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 955e77168..8c6829eb3 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -614,6 +614,8 @@ namespace MWBase /// Return physical half extents of the given actor to be used in pathfinding virtual osg::Vec3f getPathfindingHalfExtents(const MWWorld::ConstPtr& actor) const = 0; + + virtual bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const = 0; }; } diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index ef22d986a..c834f6984 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -13,6 +13,8 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwphysics/collisiontype.hpp" + #include "pathgrid.hpp" #include "creaturestats.hpp" #include "movement.hpp" @@ -240,6 +242,9 @@ void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor) if (!door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == MWWorld::DoorState::Idle) { + if (!isDoorOnTheWay(actor, door)) + return; + if ((door.getCellRef().getTrap().empty() && door.getCellRef().getLockLevel() <= 0 )) { world->activate(door, actor); @@ -408,3 +413,13 @@ DetourNavigator::Flags MWMechanics::AiPackage::getNavigatorFlags(const MWWorld:: return result; } + +bool MWMechanics::AiPackage::isDoorOnTheWay(const MWWorld::Ptr& actor, const MWWorld::Ptr& door) const +{ + const auto world = MWBase::Environment::get().getWorld(); + const auto halfExtents = world->getHalfExtents(actor); + const auto position = actor.getRefData().getPosition().asVec3() + osg::Vec3f(0, 0, halfExtents.z()); + const auto destination = mPathFinder.getPath().front() + osg::Vec3f(0, 0, halfExtents.z()); + + return world->hasCollisionWithDoor(door, position, destination); +} diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 6bb12342a..0f7b5cf1d 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -147,6 +147,8 @@ namespace MWMechanics private: bool isNearInactiveCell(osg::Vec3f position); + + bool isDoorOnTheWay(const MWWorld::Ptr& actor, const MWWorld::Ptr& door) const; }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3ea994683..908e5c052 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -3829,4 +3830,23 @@ namespace MWWorld return getHalfExtents(actor); } + bool World::hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const + { + const auto object = mPhysics->getObject(door); + + if (!object) + return false; + + btVector3 aabbMin; + btVector3 aabbMax; + object->getShapeInstance()->getCollisionShape()->getAabb(btTransform::getIdentity(), aabbMin, aabbMax); + + const auto toLocal = object->getCollisionObject()->getWorldTransform().inverse(); + const auto localFrom = toLocal(Misc::Convert::toBullet(position)); + const auto localTo = toLocal(Misc::Convert::toBullet(destination)); + + btScalar hitDistance = 1; + btVector3 hitNormal; + return btRayAabb(localFrom, localTo, aabbMin, aabbMax, hitDistance, hitNormal); + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 76d015477..bd34087ac 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -719,6 +719,8 @@ namespace MWWorld /// Return physical half extents of the given actor to be used in pathfinding osg::Vec3f getPathfindingHalfExtents(const MWWorld::ConstPtr& actor) const override; + + bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const override; }; }