mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 20:29:57 +00:00
Ignore player when checking whether AiTravel destination is occupied by other actor
This commit is contained in:
parent
fd6899e91d
commit
39da3bfef8
10 changed files with 79 additions and 21 deletions
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <components/esm3/cellid.hpp>
|
#include <components/esm3/cellid.hpp>
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
#include <components/misc/span.hpp>
|
||||||
|
|
||||||
#include <osg/Timer>
|
#include <osg/Timer>
|
||||||
|
|
||||||
|
@ -658,7 +659,7 @@ namespace MWBase
|
||||||
virtual bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const = 0;
|
virtual bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const = 0;
|
||||||
|
|
||||||
virtual bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
virtual bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
||||||
const MWWorld::ConstPtr& ignore, std::vector<MWWorld::Ptr>* occupyingActors = nullptr) const = 0;
|
const Misc::Span<const MWWorld::ConstPtr>& ignore, std::vector<MWWorld::Ptr>* occupyingActors = nullptr) const = 0;
|
||||||
|
|
||||||
virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const = 0;
|
virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const = 0;
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace MWMechanics
|
||||||
if (mDestinationCheck.update(duration) == Misc::TimerStatus::Elapsed)
|
if (mDestinationCheck.update(duration) == Misc::TimerStatus::Elapsed)
|
||||||
{
|
{
|
||||||
std::vector<MWWorld::Ptr> occupyingActors;
|
std::vector<MWWorld::Ptr> occupyingActors;
|
||||||
if (isAreaOccupiedByOtherActor(actor, targetPos, &occupyingActors))
|
if (isAreaOccupiedByOtherActor(actor, targetPos, true, &occupyingActors))
|
||||||
{
|
{
|
||||||
const float actorRadius = getActorRadius(actor);
|
const float actorRadius = getActorRadius(actor);
|
||||||
const float distanceToTarget = distance(actorPos, targetPos);
|
const float distanceToTarget = distance(actorPos, targetPos);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "obstacle.hpp"
|
#include "obstacle.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -74,13 +76,19 @@ namespace MWMechanics
|
||||||
return MWWorld::Ptr(); // none found
|
return MWWorld::Ptr(); // none found
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAreaOccupiedByOtherActor(const MWWorld::ConstPtr& actor, const osg::Vec3f& destination,
|
bool isAreaOccupiedByOtherActor(const MWWorld::ConstPtr& actor, const osg::Vec3f& destination, bool ignorePlayer,
|
||||||
std::vector<MWWorld::Ptr>* occupyingActors)
|
std::vector<MWWorld::Ptr>* occupyingActors)
|
||||||
{
|
{
|
||||||
const auto world = MWBase::Environment::get().getWorld();
|
const auto world = MWBase::Environment::get().getWorld();
|
||||||
const osg::Vec3f halfExtents = world->getPathfindingHalfExtents(actor);
|
const osg::Vec3f halfExtents = world->getPathfindingHalfExtents(actor);
|
||||||
const auto maxHalfExtent = std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z()));
|
const auto maxHalfExtent = std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z()));
|
||||||
return world->isAreaOccupiedByOtherActor(destination, 2 * maxHalfExtent, actor, occupyingActors);
|
if (ignorePlayer)
|
||||||
|
{
|
||||||
|
const std::array ignore {actor, world->getPlayerConstPtr()};
|
||||||
|
return world->isAreaOccupiedByOtherActor(destination, 2 * maxHalfExtent, ignore, occupyingActors);
|
||||||
|
}
|
||||||
|
const std::array ignore {actor};
|
||||||
|
return world->isAreaOccupiedByOtherActor(destination, 2 * maxHalfExtent, ignore, occupyingActors);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObstacleCheck::ObstacleCheck()
|
ObstacleCheck::ObstacleCheck()
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace MWMechanics
|
||||||
/** \return Pointer to the door, or empty pointer if none exists **/
|
/** \return Pointer to the door, or empty pointer if none exists **/
|
||||||
const MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minDist);
|
const MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minDist);
|
||||||
|
|
||||||
bool isAreaOccupiedByOtherActor(const MWWorld::ConstPtr& actor, const osg::Vec3f& destination,
|
bool isAreaOccupiedByOtherActor(const MWWorld::ConstPtr& actor, const osg::Vec3f& destination, bool ignorePlayer = false,
|
||||||
std::vector<MWWorld::Ptr>* occupyingActors = nullptr);
|
std::vector<MWWorld::Ptr>* occupyingActors = nullptr);
|
||||||
|
|
||||||
class ObstacleCheck
|
class ObstacleCheck
|
||||||
|
|
|
@ -22,15 +22,15 @@ namespace MWPhysics
|
||||||
return nearest.distance(position) < radius;
|
return nearest.distance(position) < radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class OnCollision>
|
template <class Ignore, class OnCollision>
|
||||||
class HasSphereCollisionCallback final : public btBroadphaseAabbCallback
|
class HasSphereCollisionCallback final : public btBroadphaseAabbCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HasSphereCollisionCallback(const btVector3& position, const btScalar radius, btCollisionObject* object,
|
HasSphereCollisionCallback(const btVector3& position, const btScalar radius, const int mask, const int group,
|
||||||
const int mask, const int group, OnCollision* onCollision)
|
const Ignore& ignore, OnCollision* onCollision)
|
||||||
: mPosition(position),
|
: mPosition(position),
|
||||||
mRadius(radius),
|
mRadius(radius),
|
||||||
mCollisionObject(object),
|
mIgnore(ignore),
|
||||||
mCollisionFilterMask(mask),
|
mCollisionFilterMask(mask),
|
||||||
mCollisionFilterGroup(group),
|
mCollisionFilterGroup(group),
|
||||||
mOnCollision(onCollision)
|
mOnCollision(onCollision)
|
||||||
|
@ -42,7 +42,7 @@ namespace MWPhysics
|
||||||
if (mResult && mOnCollision == nullptr)
|
if (mResult && mOnCollision == nullptr)
|
||||||
return false;
|
return false;
|
||||||
const auto collisionObject = static_cast<btCollisionObject*>(proxy->m_clientObject);
|
const auto collisionObject = static_cast<btCollisionObject*>(proxy->m_clientObject);
|
||||||
if (collisionObject == mCollisionObject
|
if (mIgnore(collisionObject)
|
||||||
|| !needsCollision(*proxy)
|
|| !needsCollision(*proxy)
|
||||||
|| !testAabbAgainstSphere(proxy->m_aabbMin, proxy->m_aabbMax, mPosition, mRadius))
|
|| !testAabbAgainstSphere(proxy->m_aabbMin, proxy->m_aabbMax, mPosition, mRadius))
|
||||||
return true;
|
return true;
|
||||||
|
@ -63,7 +63,7 @@ namespace MWPhysics
|
||||||
private:
|
private:
|
||||||
btVector3 mPosition;
|
btVector3 mPosition;
|
||||||
btScalar mRadius;
|
btScalar mRadius;
|
||||||
btCollisionObject* mCollisionObject;
|
Ignore mIgnore;
|
||||||
int mCollisionFilterMask;
|
int mCollisionFilterMask;
|
||||||
int mCollisionFilterGroup;
|
int mCollisionFilterGroup;
|
||||||
OnCollision* mOnCollision;
|
OnCollision* mOnCollision;
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
|
|
||||||
#include <LinearMath/btIDebugDraw.h>
|
#include <LinearMath/btIDebugDraw.h>
|
||||||
#include <LinearMath/btVector3.h>
|
#include <LinearMath/btVector3.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
#include <osg/Stats>
|
#include <osg/Stats>
|
||||||
#include <osg/Timer>
|
#include <osg/Timer>
|
||||||
|
@ -884,12 +888,19 @@ namespace MWPhysics
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsSystem::isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
bool PhysicsSystem::isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
||||||
const MWWorld::ConstPtr& ignore, std::vector<MWWorld::Ptr>* occupyingActors) const
|
const Misc::Span<const MWWorld::ConstPtr>& ignore, std::vector<MWWorld::Ptr>* occupyingActors) const
|
||||||
{
|
{
|
||||||
btCollisionObject* object = nullptr;
|
std::vector<const btCollisionObject*> ignoredObjects;
|
||||||
const auto it = mActors.find(ignore.mRef);
|
ignoredObjects.reserve(ignore.size());
|
||||||
if (it != mActors.end())
|
for (const auto& v : ignore)
|
||||||
object = it->second->getCollisionObject();
|
if (const auto it = mActors.find(v.mRef); it != mActors.end())
|
||||||
|
ignoredObjects.push_back(it->second->getCollisionObject());
|
||||||
|
std::sort(ignoredObjects.begin(), ignoredObjects.end());
|
||||||
|
ignoredObjects.erase(std::unique(ignoredObjects.begin(), ignoredObjects.end()), ignoredObjects.end());
|
||||||
|
const auto ignoreFilter = [&] (const btCollisionObject* v)
|
||||||
|
{
|
||||||
|
return std::binary_search(ignoredObjects.begin(), ignoredObjects.end(), v);
|
||||||
|
};
|
||||||
const auto bulletPosition = Misc::Convert::toBullet(position);
|
const auto bulletPosition = Misc::Convert::toBullet(position);
|
||||||
const auto aabbMin = bulletPosition - btVector3(radius, radius, radius);
|
const auto aabbMin = bulletPosition - btVector3(radius, radius, radius);
|
||||||
const auto aabbMax = bulletPosition + btVector3(radius, radius, radius);
|
const auto aabbMax = bulletPosition + btVector3(radius, radius, radius);
|
||||||
|
@ -897,7 +908,7 @@ namespace MWPhysics
|
||||||
const int group = 0xff;
|
const int group = 0xff;
|
||||||
if (occupyingActors == nullptr)
|
if (occupyingActors == nullptr)
|
||||||
{
|
{
|
||||||
HasSphereCollisionCallback callback(bulletPosition, radius, object, mask, group,
|
HasSphereCollisionCallback callback(bulletPosition, radius, mask, group, ignoreFilter,
|
||||||
static_cast<void (*)(const btCollisionObject*)>(nullptr));
|
static_cast<void (*)(const btCollisionObject*)>(nullptr));
|
||||||
mTaskScheduler->aabbTest(aabbMin, aabbMax, callback);
|
mTaskScheduler->aabbTest(aabbMin, aabbMax, callback);
|
||||||
return callback.getResult();
|
return callback.getResult();
|
||||||
|
@ -907,7 +918,7 @@ namespace MWPhysics
|
||||||
if (PtrHolder* holder = static_cast<PtrHolder*>(object->getUserPointer()))
|
if (PtrHolder* holder = static_cast<PtrHolder*>(object->getUserPointer()))
|
||||||
occupyingActors->push_back(holder->getPtr());
|
occupyingActors->push_back(holder->getPtr());
|
||||||
};
|
};
|
||||||
HasSphereCollisionCallback callback(bulletPosition, radius, object, mask, group, &onCollision);
|
HasSphereCollisionCallback callback(bulletPosition, radius, mask, group, ignoreFilter, &onCollision);
|
||||||
mTaskScheduler->aabbTest(aabbMin, aabbMax, callback);
|
mTaskScheduler->aabbTest(aabbMin, aabbMax, callback);
|
||||||
return callback.getResult();
|
return callback.getResult();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
#include <osg/Timer>
|
#include <osg/Timer>
|
||||||
|
|
||||||
|
#include <components/misc/span.hpp>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
#include "collisiontype.hpp"
|
#include "collisiontype.hpp"
|
||||||
|
@ -277,7 +279,7 @@ namespace MWPhysics
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
||||||
const MWWorld::ConstPtr& ignore, std::vector<MWWorld::Ptr>* occupyingActors) const;
|
const Misc::Span<const MWWorld::ConstPtr>& ignore, std::vector<MWWorld::Ptr>* occupyingActors) const;
|
||||||
|
|
||||||
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
||||||
void reportCollision(const btVector3& position, const btVector3& normal);
|
void reportCollision(const btVector3& position, const btVector3& normal);
|
||||||
|
|
|
@ -3997,7 +3997,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
bool World::isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
||||||
const MWWorld::ConstPtr& ignore, std::vector<MWWorld::Ptr>* occupyingActors) const
|
const Misc::Span<const MWWorld::ConstPtr>& ignore, std::vector<MWWorld::Ptr>* occupyingActors) const
|
||||||
{
|
{
|
||||||
return mPhysics->isAreaOccupiedByOtherActor(position, radius, ignore, occupyingActors);
|
return mPhysics->isAreaOccupiedByOtherActor(position, radius, ignore, occupyingActors);
|
||||||
}
|
}
|
||||||
|
|
|
@ -736,7 +736,7 @@ namespace MWWorld
|
||||||
bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const override;
|
bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const override;
|
||||||
|
|
||||||
bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
||||||
const MWWorld::ConstPtr& ignore, std::vector<MWWorld::Ptr>* occupyingActors) const override;
|
const Misc::Span<const MWWorld::ConstPtr>& ignore, std::vector<MWWorld::Ptr>* occupyingActors) const override;
|
||||||
|
|
||||||
void reportStats(unsigned int frameNumber, osg::Stats& stats) const override;
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const override;
|
||||||
|
|
||||||
|
|
36
components/misc/span.hpp
Normal file
36
components/misc/span.hpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_MISC_SPAN_H
|
||||||
|
#define OPENMW_COMPONENTS_MISC_SPAN_H
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace Misc
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
class Span
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr Span() = default;
|
||||||
|
|
||||||
|
constexpr Span(T* pointer, std::size_t size)
|
||||||
|
: mPointer(pointer)
|
||||||
|
, mSize(size)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <class Range>
|
||||||
|
constexpr Span(Range& range)
|
||||||
|
: Span(range.data(), range.size())
|
||||||
|
{}
|
||||||
|
|
||||||
|
constexpr T* begin() const { return mPointer; }
|
||||||
|
|
||||||
|
constexpr T* end() const { return mPointer + mSize; }
|
||||||
|
|
||||||
|
constexpr std::size_t size() const { return mSize; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* mPointer = nullptr;
|
||||||
|
std::size_t mSize = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue