1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-01 19:49:40 +00:00

Do not block a door when it turns away.

This commit is contained in:
fredzio 2020-11-01 22:30:48 +01:00
parent ba3aad31c1
commit 18e38d8810
5 changed files with 35 additions and 10 deletions

View file

@ -2,6 +2,8 @@
#include <BulletCollision/CollisionDispatch/btCollisionObject.h> #include <BulletCollision/CollisionDispatch/btCollisionObject.h>
#include "components/misc/convert.hpp"
#include "ptrholder.hpp" #include "ptrholder.hpp"
namespace MWPhysics namespace MWPhysics
@ -20,7 +22,7 @@ namespace MWPhysics
collisionObject = col1Wrap->m_collisionObject; collisionObject = col1Wrap->m_collisionObject;
PtrHolder* holder = static_cast<PtrHolder*>(collisionObject->getUserPointer()); PtrHolder* holder = static_cast<PtrHolder*>(collisionObject->getUserPointer());
if (holder) 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; return 0.f;
} }

View file

@ -7,6 +7,8 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "physicssystem.hpp"
class btCollisionObject; class btCollisionObject;
struct btCollisionObjectWrapper; struct btCollisionObjectWrapper;
@ -23,7 +25,7 @@ namespace MWPhysics
const btCollisionObjectWrapper* col0Wrap,int partId0,int index0, const btCollisionObjectWrapper* col0Wrap,int partId0,int index0,
const btCollisionObjectWrapper* col1Wrap,int partId1,int index1) override; const btCollisionObjectWrapper* col1Wrap,int partId1,int index1) override;
std::vector<MWWorld::Ptr> mResult; std::vector<ContactPoint> mResult;
}; };
} }

View file

@ -403,15 +403,15 @@ namespace MWPhysics
return osg::Vec3f(); 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; btCollisionObject* me = nullptr;
ObjectMap::const_iterator found = mObjects.find(ptr); auto found = mObjects.find(ptr);
if (found != mObjects.end()) if (found != mObjects.end())
me = found->second->getCollisionObject(); me = found->second->getCollisionObject();
else else
return std::vector<MWWorld::Ptr>(); return {};
ContactTestResultCallback resultCallback (me); ContactTestResultCallback resultCallback (me);
resultCallback.m_collisionFilterGroup = collisionGroup; resultCallback.m_collisionFilterGroup = collisionGroup;
@ -420,6 +420,14 @@ namespace MWPhysics
return resultCallback.mResult; 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) osg::Vec3f PhysicsSystem::traceDown(const MWWorld::Ptr &ptr, const osg::Vec3f& position, float maxHeight)
{ {
ActorMap::iterator found = mActors.find(ptr); ActorMap::iterator found = mActors.find(ptr);

View file

@ -57,6 +57,13 @@ namespace MWPhysics
class Actor; class Actor;
class PhysicsTaskScheduler; class PhysicsTaskScheduler;
struct ContactPoint
{
MWWorld::Ptr mObject;
osg::Vec3f mPoint;
osg::Vec3f mNormal;
};
struct LOSRequest struct LOSRequest
{ {
LOSRequest(const std::weak_ptr<Actor>& a1, const std::weak_ptr<Actor>& a2); LOSRequest(const std::weak_ptr<Actor>& a1, const std::weak_ptr<Actor>& a2);
@ -145,6 +152,7 @@ namespace MWPhysics
void debugDraw(); void debugDraw();
std::vector<MWWorld::Ptr> getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const; ///< get handles this object collides with 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); osg::Vec3f traceDown(const MWWorld::Ptr &ptr, const osg::Vec3f& position, float maxHeight);
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::ConstPtr& actor, std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::ConstPtr& actor,

View file

@ -1577,19 +1577,24 @@ namespace MWWorld
float minRot = door.getCellRef().getPosition().rot[2]; float minRot = door.getCellRef().getPosition().rot[2];
float maxRot = minRot + osg::DegreesToRadians(90.f); float maxRot = minRot + osg::DegreesToRadians(90.f);
float diff = duration * osg::DegreesToRadians(90.f); float diff = duration * osg::DegreesToRadians(90.f) * (state == MWWorld::DoorState::Opening ? 1 : -1);
float targetRot = std::min(std::max(minRot, oldRot + diff * (state == MWWorld::DoorState::Opening ? 1 : -1)), maxRot); float targetRot = std::min(std::max(minRot, oldRot + diff), maxRot);
rotateObject(door, objPos.rot[0], objPos.rot[1], targetRot, MWBase::RotationFlag_none); rotateObject(door, objPos.rot[0], objPos.rot[1], targetRot, MWBase::RotationFlag_none);
bool reached = (targetRot == maxRot && state != MWWorld::DoorState::Idle) || targetRot == minRot; bool reached = (targetRot == maxRot && state != MWWorld::DoorState::Idle) || targetRot == minRot;
/// \todo should use convexSweepTest here /// \todo should use convexSweepTest here
bool collisionWithActor = false; bool collisionWithActor = false;
std::vector<MWWorld::Ptr> collisions = mPhysics->getCollisions(door, MWPhysics::CollisionType_Door, MWPhysics::CollisionType_Actor); for (auto& [ptr, point, normal] : mPhysics->getCollisionsPoints(door, MWPhysics::CollisionType_Door, MWPhysics::CollisionType_Actor))
for (MWWorld::Ptr& ptr : collisions)
{ {
if (ptr.getClass().isActor()) 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; collisionWithActor = true;
// Collided with actor, ask actor to try to avoid door // Collided with actor, ask actor to try to avoid door