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:
parent
ba3aad31c1
commit
18e38d8810
5 changed files with 35 additions and 10 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue