mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-21 09:39:56 +00:00
Do not block a door when it turns away.
This commit is contained in:
parent
ba3aad31c1
commit
18e38d8810
@ -2,6 +2,8 @@
|
||||
|
||||
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
|
||||
|
||||
#include "components/misc/convert.hpp"
|
||||
|
||||
#include "ptrholder.hpp"
|
||||
|
||||
namespace MWPhysics
|
||||
@ -20,7 +22,7 @@ namespace MWPhysics
|
||||
collisionObject = col1Wrap->m_collisionObject;
|
||||
PtrHolder* holder = static_cast<PtrHolder*>(collisionObject->getUserPointer());
|
||||
if (holder)
|
||||
mResult.push_back(holder->getPtr());
|
||||
mResult.emplace_back(ContactPoint{holder->getPtr(), Misc::Convert::toOsg(cp.m_positionWorldOnB), Misc::Convert::toOsg(cp.m_normalWorldOnB)});
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
#include "physicssystem.hpp"
|
||||
|
||||
class btCollisionObject;
|
||||
struct btCollisionObjectWrapper;
|
||||
|
||||
@ -23,7 +25,7 @@ namespace MWPhysics
|
||||
const btCollisionObjectWrapper* col0Wrap,int partId0,int index0,
|
||||
const btCollisionObjectWrapper* col1Wrap,int partId1,int index1) override;
|
||||
|
||||
std::vector<MWWorld::Ptr> mResult;
|
||||
std::vector<ContactPoint> mResult;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -403,15 +403,15 @@ namespace MWPhysics
|
||||
return osg::Vec3f();
|
||||
}
|
||||
|
||||
std::vector<MWWorld::Ptr> PhysicsSystem::getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const
|
||||
std::vector<ContactPoint> PhysicsSystem::getCollisionsPoints(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const
|
||||
{
|
||||
btCollisionObject* me = nullptr;
|
||||
|
||||
ObjectMap::const_iterator found = mObjects.find(ptr);
|
||||
auto found = mObjects.find(ptr);
|
||||
if (found != mObjects.end())
|
||||
me = found->second->getCollisionObject();
|
||||
else
|
||||
return std::vector<MWWorld::Ptr>();
|
||||
return {};
|
||||
|
||||
ContactTestResultCallback resultCallback (me);
|
||||
resultCallback.m_collisionFilterGroup = collisionGroup;
|
||||
@ -420,6 +420,14 @@ namespace MWPhysics
|
||||
return resultCallback.mResult;
|
||||
}
|
||||
|
||||
std::vector<MWWorld::Ptr> PhysicsSystem::getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const
|
||||
{
|
||||
std::vector<MWWorld::Ptr> actors;
|
||||
for (auto& [actor, point, normal] : getCollisionsPoints(ptr, collisionGroup, collisionMask))
|
||||
actors.emplace_back(actor);
|
||||
return actors;
|
||||
}
|
||||
|
||||
osg::Vec3f PhysicsSystem::traceDown(const MWWorld::Ptr &ptr, const osg::Vec3f& position, float maxHeight)
|
||||
{
|
||||
ActorMap::iterator found = mActors.find(ptr);
|
||||
|
@ -57,6 +57,13 @@ namespace MWPhysics
|
||||
class Actor;
|
||||
class PhysicsTaskScheduler;
|
||||
|
||||
struct ContactPoint
|
||||
{
|
||||
MWWorld::Ptr mObject;
|
||||
osg::Vec3f mPoint;
|
||||
osg::Vec3f mNormal;
|
||||
};
|
||||
|
||||
struct LOSRequest
|
||||
{
|
||||
LOSRequest(const std::weak_ptr<Actor>& a1, const std::weak_ptr<Actor>& a2);
|
||||
@ -145,6 +152,7 @@ namespace MWPhysics
|
||||
void debugDraw();
|
||||
|
||||
std::vector<MWWorld::Ptr> getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const; ///< get handles this object collides with
|
||||
std::vector<ContactPoint> getCollisionsPoints(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const;
|
||||
osg::Vec3f traceDown(const MWWorld::Ptr &ptr, const osg::Vec3f& position, float maxHeight);
|
||||
|
||||
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::ConstPtr& actor,
|
||||
|
@ -1577,21 +1577,26 @@ namespace MWWorld
|
||||
float minRot = door.getCellRef().getPosition().rot[2];
|
||||
float maxRot = minRot + osg::DegreesToRadians(90.f);
|
||||
|
||||
float diff = duration * osg::DegreesToRadians(90.f);
|
||||
float targetRot = std::min(std::max(minRot, oldRot + diff * (state == MWWorld::DoorState::Opening ? 1 : -1)), maxRot);
|
||||
float diff = duration * osg::DegreesToRadians(90.f) * (state == MWWorld::DoorState::Opening ? 1 : -1);
|
||||
float targetRot = std::min(std::max(minRot, oldRot + diff), maxRot);
|
||||
rotateObject(door, objPos.rot[0], objPos.rot[1], targetRot, MWBase::RotationFlag_none);
|
||||
|
||||
bool reached = (targetRot == maxRot && state != MWWorld::DoorState::Idle) || targetRot == minRot;
|
||||
|
||||
/// \todo should use convexSweepTest here
|
||||
bool collisionWithActor = false;
|
||||
std::vector<MWWorld::Ptr> collisions = mPhysics->getCollisions(door, MWPhysics::CollisionType_Door, MWPhysics::CollisionType_Actor);
|
||||
for (MWWorld::Ptr& ptr : collisions)
|
||||
for (auto& [ptr, point, normal] : mPhysics->getCollisionsPoints(door, MWPhysics::CollisionType_Door, MWPhysics::CollisionType_Actor))
|
||||
{
|
||||
|
||||
if (ptr.getClass().isActor())
|
||||
{
|
||||
osg::Vec3f direction = osg::Quat(diff, osg::Vec3f(0, 0, 1)) * point - point;
|
||||
direction.normalize();
|
||||
if (direction * normal < 0) // door is turning away from actor
|
||||
continue;
|
||||
|
||||
collisionWithActor = true;
|
||||
|
||||
|
||||
// Collided with actor, ask actor to try to avoid door
|
||||
if(ptr != getPlayerPtr() )
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user