mirror of
https://github.com/OpenMW/openmw.git
synced 2025-11-08 21:16:40 +00:00
Merge branch 'killmutex' into 'master'
Remove mutex from PtrHolder See merge request OpenMW/openmw!1110
This commit is contained in:
commit
cb7a4d20dd
14 changed files with 98 additions and 120 deletions
|
|
@ -21,7 +21,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler, bool canWaterWalk)
|
Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler, bool canWaterWalk)
|
||||||
: mStandingOnPtr(nullptr), mCanWaterWalk(canWaterWalk), mWalkingOnWater(false)
|
: mStandingOnPtr(nullptr), mCanWaterWalk(canWaterWalk), mWalkingOnWater(false)
|
||||||
, mCollisionObject(nullptr), mMeshTranslation(shape->mCollisionBox.center), mOriginalHalfExtents(shape->mCollisionBox.extents)
|
, mMeshTranslation(shape->mCollisionBox.center), mOriginalHalfExtents(shape->mCollisionBox.extents)
|
||||||
, mVelocity(0,0,0), mStuckFrames(0), mLastStuckPosition{0, 0, 0}
|
, mVelocity(0,0,0), mStuckFrames(0), mLastStuckPosition{0, 0, 0}
|
||||||
, mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false)
|
, mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false)
|
||||||
, mInternalCollisionMode(true)
|
, mInternalCollisionMode(true)
|
||||||
|
|
|
||||||
|
|
@ -132,11 +132,6 @@ namespace MWPhysics
|
||||||
return mInternalCollisionMode && mOnSlope;
|
return mInternalCollisionMode && mOnSlope;
|
||||||
}
|
}
|
||||||
|
|
||||||
btCollisionObject* getCollisionObject() const
|
|
||||||
{
|
|
||||||
return mCollisionObject.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets whether this actor should be able to collide with the water surface
|
/// Sets whether this actor should be able to collide with the water surface
|
||||||
void setCanWaterWalk(bool waterWalk);
|
void setCanWaterWalk(bool waterWalk);
|
||||||
|
|
||||||
|
|
@ -188,8 +183,6 @@ namespace MWPhysics
|
||||||
std::unique_ptr<btCollisionShape> mShape;
|
std::unique_ptr<btCollisionShape> mShape;
|
||||||
btConvexShape* mConvexShape;
|
btConvexShape* mConvexShape;
|
||||||
|
|
||||||
std::unique_ptr<btCollisionObject> mCollisionObject;
|
|
||||||
|
|
||||||
osg::Vec3f mMeshTranslation;
|
osg::Vec3f mMeshTranslation;
|
||||||
osg::Vec3f mOriginalHalfExtents;
|
osg::Vec3f mOriginalHalfExtents;
|
||||||
osg::Vec3f mHalfExtents;
|
osg::Vec3f mHalfExtents;
|
||||||
|
|
|
||||||
|
|
@ -77,10 +77,8 @@ namespace MWPhysics
|
||||||
auto* projectileHolder = static_cast<Projectile*>(convexResult.m_hitCollisionObject->getUserPointer());
|
auto* projectileHolder = static_cast<Projectile*>(convexResult.m_hitCollisionObject->getUserPointer());
|
||||||
if (!projectileHolder->isActive())
|
if (!projectileHolder->isActive())
|
||||||
return btScalar(1);
|
return btScalar(1);
|
||||||
auto* targetHolder = static_cast<PtrHolder*>(mMe->getUserPointer());
|
if (projectileHolder->isValidTarget(mMe))
|
||||||
const MWWorld::Ptr target = targetHolder->getPtr();
|
projectileHolder->hit(mMe, convexResult.m_hitPointLocal, convexResult.m_hitNormalLocal);
|
||||||
if (projectileHolder->isValidTarget(target))
|
|
||||||
projectileHolder->hit(target, convexResult.m_hitPointLocal, convexResult.m_hitNormalLocal);
|
|
||||||
return btScalar(1);
|
return btScalar(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
#include "collisiontype.hpp"
|
||||||
#include "ptrholder.hpp"
|
#include "ptrholder.hpp"
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
|
|
@ -19,17 +20,14 @@ namespace MWPhysics
|
||||||
|
|
||||||
btScalar ClosestNotMeRayResultCallback::addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
|
btScalar ClosestNotMeRayResultCallback::addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
|
||||||
{
|
{
|
||||||
if (rayResult.m_collisionObject == mMe)
|
const auto* hitObject = rayResult.m_collisionObject;
|
||||||
|
if (hitObject == mMe)
|
||||||
return 1.f;
|
return 1.f;
|
||||||
|
|
||||||
if (!mTargets.empty())
|
if (hitObject->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor && !mTargets.empty())
|
||||||
{
|
{
|
||||||
if ((std::find(mTargets.begin(), mTargets.end(), rayResult.m_collisionObject) == mTargets.end()))
|
if ((std::find(mTargets.begin(), mTargets.end(), hitObject) == mTargets.end()))
|
||||||
{
|
return 1.f;
|
||||||
auto* holder = static_cast<PtrHolder*>(rayResult.m_collisionObject->getUserPointer());
|
|
||||||
if (holder && !holder->getPtr().isEmpty() && holder->getPtr().getClass().isActor())
|
|
||||||
return 1.f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
|
return btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
#include "collisiontype.hpp"
|
||||||
#include "ptrholder.hpp"
|
#include "ptrholder.hpp"
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
|
|
@ -23,14 +24,10 @@ namespace MWPhysics
|
||||||
const btCollisionObject* collisionObject = col1Wrap->m_collisionObject;
|
const btCollisionObject* collisionObject = col1Wrap->m_collisionObject;
|
||||||
if (collisionObject != mMe)
|
if (collisionObject != mMe)
|
||||||
{
|
{
|
||||||
if (!mTargets.empty())
|
if (collisionObject->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor && !mTargets.empty())
|
||||||
{
|
{
|
||||||
if ((std::find(mTargets.begin(), mTargets.end(), collisionObject) == mTargets.end()))
|
if ((std::find(mTargets.begin(), mTargets.end(), collisionObject) == mTargets.end()))
|
||||||
{
|
return 0.f;
|
||||||
PtrHolder* holder = static_cast<PtrHolder*>(collisionObject->getUserPointer());
|
|
||||||
if (holder && !holder->getPtr().isEmpty() && holder->getPtr().getClass().isActor())
|
|
||||||
return 0.f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
btScalar distsqr = mOrigin.distance2(cp.getPositionWorldOnA());
|
btScalar distsqr = mOrigin.distance2(cp.getPositionWorldOnA());
|
||||||
|
|
|
||||||
|
|
@ -83,16 +83,6 @@ namespace MWPhysics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btCollisionObject* Object::getCollisionObject()
|
|
||||||
{
|
|
||||||
return mCollisionObject.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
const btCollisionObject* Object::getCollisionObject() const
|
|
||||||
{
|
|
||||||
return mCollisionObject.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
btTransform Object::getTransform() const
|
btTransform Object::getTransform() const
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mPositionMutex);
|
std::unique_lock<std::mutex> lock(mPositionMutex);
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,6 @@ namespace MWPhysics
|
||||||
void setRotation(osg::Quat quat);
|
void setRotation(osg::Quat quat);
|
||||||
void updatePosition();
|
void updatePosition();
|
||||||
void commitPositionChange();
|
void commitPositionChange();
|
||||||
btCollisionObject* getCollisionObject();
|
|
||||||
const btCollisionObject* getCollisionObject() const;
|
|
||||||
btTransform getTransform() const;
|
btTransform getTransform() const;
|
||||||
/// Return solid flag. Not used by the object itself, true by default.
|
/// Return solid flag. Not used by the object itself, true by default.
|
||||||
bool isSolid() const;
|
bool isSolid() const;
|
||||||
|
|
@ -45,7 +43,6 @@ namespace MWPhysics
|
||||||
bool animateCollisionShapes();
|
bool animateCollisionShapes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<btCollisionObject> mCollisionObject;
|
|
||||||
osg::ref_ptr<Resource::BulletShapeInstance> mShapeInstance;
|
osg::ref_ptr<Resource::BulletShapeInstance> mShapeInstance;
|
||||||
std::map<int, osg::NodePath> mRecIndexToNodePath;
|
std::map<int, osg::NodePath> mRecIndexToNodePath;
|
||||||
bool mSolid;
|
bool mSolid;
|
||||||
|
|
|
||||||
|
|
@ -635,19 +635,7 @@ namespace MWPhysics
|
||||||
if (btFrom == btTo)
|
if (btFrom == btTo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto casterPtr = projectile->getCaster();
|
ProjectileConvexCallback resultCallback(projectile->getCasterCollisionObject(), projectile->getCollisionObject(), btFrom, btTo, projectile);
|
||||||
const auto* caster = [this,&casterPtr]() -> const btCollisionObject*
|
|
||||||
{
|
|
||||||
const Actor* actor = getActor(casterPtr);
|
|
||||||
if (actor)
|
|
||||||
return actor->getCollisionObject();
|
|
||||||
const Object* object = getObject(casterPtr);
|
|
||||||
if (object)
|
|
||||||
return object->getCollisionObject();
|
|
||||||
return nullptr;
|
|
||||||
}();
|
|
||||||
|
|
||||||
ProjectileConvexCallback resultCallback(caster, btFrom, btTo, projectile);
|
|
||||||
resultCallback.m_collisionFilterMask = 0xff;
|
resultCallback.m_collisionFilterMask = 0xff;
|
||||||
resultCallback.m_collisionFilterGroup = CollisionType_Projectile;
|
resultCallback.m_collisionFilterGroup = CollisionType_Projectile;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,10 @@
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
#include "actor.hpp"
|
||||||
#include "collisiontype.hpp"
|
#include "collisiontype.hpp"
|
||||||
#include "mtphysics.hpp"
|
#include "mtphysics.hpp"
|
||||||
|
#include "object.hpp"
|
||||||
#include "projectile.hpp"
|
#include "projectile.hpp"
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
|
|
@ -17,7 +19,7 @@ Projectile::Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, f
|
||||||
: mCanCrossWaterSurface(canCrossWaterSurface)
|
: mCanCrossWaterSurface(canCrossWaterSurface)
|
||||||
, mCrossedWaterSurface(false)
|
, mCrossedWaterSurface(false)
|
||||||
, mActive(true)
|
, mActive(true)
|
||||||
, mCaster(caster)
|
, mHitTarget(nullptr)
|
||||||
, mWaterHitPosition(std::nullopt)
|
, mWaterHitPosition(std::nullopt)
|
||||||
, mPhysics(physicssystem)
|
, mPhysics(physicssystem)
|
||||||
, mTaskScheduler(scheduler)
|
, mTaskScheduler(scheduler)
|
||||||
|
|
@ -32,6 +34,7 @@ Projectile::Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, f
|
||||||
mCollisionObject->setUserPointer(this);
|
mCollisionObject->setUserPointer(this);
|
||||||
|
|
||||||
setPosition(position);
|
setPosition(position);
|
||||||
|
setCaster(caster);
|
||||||
|
|
||||||
const int collisionMask = CollisionType_World | CollisionType_HeightMap |
|
const int collisionMask = CollisionType_World | CollisionType_HeightMap |
|
||||||
CollisionType_Actor | CollisionType_Door | CollisionType_Water | CollisionType_Projectile;
|
CollisionType_Actor | CollisionType_Door | CollisionType_Water | CollisionType_Projectile;
|
||||||
|
|
@ -77,54 +80,67 @@ bool Projectile::canTraverseWater() const
|
||||||
return mCanCrossWaterSurface;
|
return mCanCrossWaterSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Projectile::hit(const MWWorld::Ptr& target, btVector3 pos, btVector3 normal)
|
void Projectile::hit(const btCollisionObject* target, btVector3 pos, btVector3 normal)
|
||||||
{
|
{
|
||||||
if (!mActive.load(std::memory_order_acquire))
|
bool active = true;
|
||||||
|
if (!mActive.compare_exchange_strong(active, false, std::memory_order_relaxed) || !active)
|
||||||
return;
|
return;
|
||||||
std::scoped_lock lock(mMutex);
|
|
||||||
mHitTarget = target;
|
mHitTarget = target;
|
||||||
mHitPosition = pos;
|
mHitPosition = pos;
|
||||||
mHitNormal = normal;
|
mHitNormal = normal;
|
||||||
mActive.store(false, std::memory_order_release);
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr Projectile::getTarget() const
|
||||||
|
{
|
||||||
|
assert(!mActive);
|
||||||
|
auto* target = static_cast<PtrHolder*>(mHitTarget->getUserPointer());
|
||||||
|
return target ? target->getPtr() : MWWorld::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr Projectile::getCaster() const
|
MWWorld::Ptr Projectile::getCaster() const
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mMutex);
|
|
||||||
return mCaster;
|
return mCaster;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Projectile::setCaster(const MWWorld::Ptr& caster)
|
void Projectile::setCaster(const MWWorld::Ptr& caster)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mMutex);
|
|
||||||
mCaster = caster;
|
mCaster = caster;
|
||||||
|
mCasterColObj = [this,&caster]() -> const btCollisionObject*
|
||||||
|
{
|
||||||
|
const Actor* actor = mPhysics->getActor(caster);
|
||||||
|
if (actor)
|
||||||
|
return actor->getCollisionObject();
|
||||||
|
const Object* object = mPhysics->getObject(caster);
|
||||||
|
if (object)
|
||||||
|
return object->getCollisionObject();
|
||||||
|
return nullptr;
|
||||||
|
}();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Projectile::setValidTargets(const std::vector<MWWorld::Ptr>& targets)
|
void Projectile::setValidTargets(const std::vector<MWWorld::Ptr>& targets)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mMutex);
|
std::scoped_lock lock(mMutex);
|
||||||
mValidTargets = targets;
|
mValidTargets.clear();
|
||||||
|
for (const auto& ptr : targets)
|
||||||
|
{
|
||||||
|
const auto* physicActor = mPhysics->getActor(ptr);
|
||||||
|
if (physicActor)
|
||||||
|
mValidTargets.push_back(physicActor->getCollisionObject());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Projectile::isValidTarget(const MWWorld::Ptr& target) const
|
bool Projectile::isValidTarget(const btCollisionObject* target) const
|
||||||
{
|
{
|
||||||
|
assert(target);
|
||||||
std::scoped_lock lock(mMutex);
|
std::scoped_lock lock(mMutex);
|
||||||
if (mCaster == target)
|
if (mCasterColObj == target)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (target.isEmpty() || mValidTargets.empty())
|
if (mValidTargets.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bool validTarget = false;
|
return std::any_of(mValidTargets.begin(), mValidTargets.end(),
|
||||||
for (const auto& targetActor : mValidTargets)
|
[target](const btCollisionObject* actor) { return target == actor; });
|
||||||
{
|
|
||||||
if (targetActor == target)
|
|
||||||
{
|
|
||||||
validTarget = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return validTarget;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<btVector3> Projectile::getWaterHitPosition()
|
std::optional<btVector3> Projectile::getWaterHitPosition()
|
||||||
|
|
|
||||||
|
|
@ -42,31 +42,26 @@ namespace MWPhysics
|
||||||
void setPosition(const osg::Vec3f& position);
|
void setPosition(const osg::Vec3f& position);
|
||||||
osg::Vec3f getPosition() const;
|
osg::Vec3f getPosition() const;
|
||||||
|
|
||||||
btCollisionObject* getCollisionObject() const
|
|
||||||
{
|
|
||||||
return mCollisionObject.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isActive() const
|
bool isActive() const
|
||||||
{
|
{
|
||||||
return mActive.load(std::memory_order_acquire);
|
return mActive.load(std::memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr getTarget() const
|
MWWorld::Ptr getTarget() const;
|
||||||
{
|
|
||||||
assert(!mActive);
|
|
||||||
return mHitTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
MWWorld::Ptr getCaster() const;
|
MWWorld::Ptr getCaster() const;
|
||||||
void setCaster(const MWWorld::Ptr& caster);
|
void setCaster(const MWWorld::Ptr& caster);
|
||||||
|
const btCollisionObject* getCasterCollisionObject() const
|
||||||
|
{
|
||||||
|
return mCasterColObj;
|
||||||
|
}
|
||||||
|
|
||||||
bool canTraverseWater() const;
|
bool canTraverseWater() const;
|
||||||
|
|
||||||
void hit(const MWWorld::Ptr& target, btVector3 pos, btVector3 normal);
|
void hit(const btCollisionObject* target, btVector3 pos, btVector3 normal);
|
||||||
|
|
||||||
void setValidTargets(const std::vector<MWWorld::Ptr>& targets);
|
void setValidTargets(const std::vector<MWWorld::Ptr>& targets);
|
||||||
bool isValidTarget(const MWWorld::Ptr& target) const;
|
bool isValidTarget(const btCollisionObject* target) const;
|
||||||
|
|
||||||
std::optional<btVector3> getWaterHitPosition();
|
std::optional<btVector3> getWaterHitPosition();
|
||||||
void setWaterHitPosition(btVector3 pos);
|
void setWaterHitPosition(btVector3 pos);
|
||||||
|
|
@ -76,19 +71,19 @@ namespace MWPhysics
|
||||||
std::unique_ptr<btCollisionShape> mShape;
|
std::unique_ptr<btCollisionShape> mShape;
|
||||||
btConvexShape* mConvexShape;
|
btConvexShape* mConvexShape;
|
||||||
|
|
||||||
std::unique_ptr<btCollisionObject> mCollisionObject;
|
|
||||||
bool mTransformUpdatePending;
|
bool mTransformUpdatePending;
|
||||||
bool mCanCrossWaterSurface;
|
bool mCanCrossWaterSurface;
|
||||||
bool mCrossedWaterSurface;
|
bool mCrossedWaterSurface;
|
||||||
std::atomic<bool> mActive;
|
std::atomic<bool> mActive;
|
||||||
MWWorld::Ptr mCaster;
|
MWWorld::Ptr mCaster;
|
||||||
MWWorld::Ptr mHitTarget;
|
const btCollisionObject* mCasterColObj;
|
||||||
|
const btCollisionObject* mHitTarget;
|
||||||
std::optional<btVector3> mWaterHitPosition;
|
std::optional<btVector3> mWaterHitPosition;
|
||||||
osg::Vec3f mPosition;
|
osg::Vec3f mPosition;
|
||||||
btVector3 mHitPosition;
|
btVector3 mHitPosition;
|
||||||
btVector3 mHitNormal;
|
btVector3 mHitNormal;
|
||||||
|
|
||||||
std::vector<MWWorld::Ptr> mValidTargets;
|
std::vector<const btCollisionObject*> mValidTargets;
|
||||||
|
|
||||||
mutable std::mutex mMutex;
|
mutable std::mutex mMutex;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
#include "actor.hpp"
|
#include "actor.hpp"
|
||||||
|
|
@ -8,41 +10,41 @@
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
{
|
{
|
||||||
ProjectileConvexCallback::ProjectileConvexCallback(const btCollisionObject* me, const btVector3& from, const btVector3& to, Projectile* proj)
|
ProjectileConvexCallback::ProjectileConvexCallback(const btCollisionObject* caster, const btCollisionObject* me, const btVector3& from, const btVector3& to, Projectile* proj)
|
||||||
: btCollisionWorld::ClosestConvexResultCallback(from, to)
|
: btCollisionWorld::ClosestConvexResultCallback(from, to)
|
||||||
, mMe(me), mProjectile(proj)
|
, mCaster(caster)
|
||||||
|
, mMe(me)
|
||||||
|
, mProjectile(proj)
|
||||||
{
|
{
|
||||||
assert(mProjectile);
|
assert(mProjectile);
|
||||||
}
|
}
|
||||||
|
|
||||||
btScalar ProjectileConvexCallback::addSingleResult(btCollisionWorld::LocalConvexResult& result, bool normalInWorldSpace)
|
btScalar ProjectileConvexCallback::addSingleResult(btCollisionWorld::LocalConvexResult& result, bool normalInWorldSpace)
|
||||||
{
|
{
|
||||||
|
const auto* hitObject = result.m_hitCollisionObject;
|
||||||
// don't hit the caster
|
// don't hit the caster
|
||||||
if (result.m_hitCollisionObject == mMe)
|
if (hitObject == mCaster)
|
||||||
return 1.f;
|
return 1.f;
|
||||||
|
|
||||||
// don't hit the projectile
|
// don't hit the projectile
|
||||||
if (result.m_hitCollisionObject == mProjectile->getCollisionObject())
|
if (hitObject == mMe)
|
||||||
return 1.f;
|
return 1.f;
|
||||||
|
|
||||||
btCollisionWorld::ClosestConvexResultCallback::addSingleResult(result, normalInWorldSpace);
|
btCollisionWorld::ClosestConvexResultCallback::addSingleResult(result, normalInWorldSpace);
|
||||||
switch (result.m_hitCollisionObject->getBroadphaseHandle()->m_collisionFilterGroup)
|
switch (hitObject->getBroadphaseHandle()->m_collisionFilterGroup)
|
||||||
{
|
{
|
||||||
case CollisionType_Actor:
|
case CollisionType_Actor:
|
||||||
{
|
{
|
||||||
auto* target = static_cast<Actor*>(result.m_hitCollisionObject->getUserPointer());
|
if (!mProjectile->isValidTarget(hitObject))
|
||||||
if (!mProjectile->isValidTarget(target->getPtr()))
|
|
||||||
return 1.f;
|
return 1.f;
|
||||||
mProjectile->hit(target->getPtr(), result.m_hitPointLocal, result.m_hitNormalLocal);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CollisionType_Projectile:
|
case CollisionType_Projectile:
|
||||||
{
|
{
|
||||||
auto* target = static_cast<Projectile*>(result.m_hitCollisionObject->getUserPointer());
|
auto* target = static_cast<Projectile*>(hitObject->getUserPointer());
|
||||||
if (!mProjectile->isValidTarget(target->getCaster()))
|
if (!mProjectile->isValidTarget(target->getCasterCollisionObject()))
|
||||||
return 1.f;
|
return 1.f;
|
||||||
target->hit(mProjectile->getPtr(), m_hitPointWorld, m_hitNormalWorld);
|
target->hit(mMe, m_hitPointWorld, m_hitNormalWorld);
|
||||||
mProjectile->hit(target->getPtr(), m_hitPointWorld, m_hitNormalWorld);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CollisionType_Water:
|
case CollisionType_Water:
|
||||||
|
|
@ -50,17 +52,10 @@ namespace MWPhysics
|
||||||
mProjectile->setWaterHitPosition(m_hitPointWorld);
|
mProjectile->setWaterHitPosition(m_hitPointWorld);
|
||||||
if (mProjectile->canTraverseWater())
|
if (mProjectile->canTraverseWater())
|
||||||
return 1.f;
|
return 1.f;
|
||||||
mProjectile->hit(MWWorld::Ptr(), m_hitPointWorld, m_hitNormalWorld);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
auto* target = static_cast<PtrHolder*>(result.m_hitCollisionObject->getUserPointer());
|
|
||||||
auto ptr = target ? target->getPtr() : MWWorld::Ptr();
|
|
||||||
mProjectile->hit(ptr, m_hitPointWorld, m_hitNormalWorld);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mProjectile->hit(hitObject, m_hitPointWorld, m_hitNormalWorld);
|
||||||
|
|
||||||
return result.m_hitFraction;
|
return result.m_hitFraction;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,12 @@ namespace MWPhysics
|
||||||
class ProjectileConvexCallback : public btCollisionWorld::ClosestConvexResultCallback
|
class ProjectileConvexCallback : public btCollisionWorld::ClosestConvexResultCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProjectileConvexCallback(const btCollisionObject* me, const btVector3& from, const btVector3& to, Projectile* proj);
|
ProjectileConvexCallback(const btCollisionObject* caster, const btCollisionObject* me, const btVector3& from, const btVector3& to, Projectile* proj);
|
||||||
|
|
||||||
btScalar addSingleResult(btCollisionWorld::LocalConvexResult& result, bool normalInWorldSpace) override;
|
btScalar addSingleResult(btCollisionWorld::LocalConvexResult& result, bool normalInWorldSpace) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const btCollisionObject* mCaster;
|
||||||
const btCollisionObject* mMe;
|
const btCollisionObject* mMe;
|
||||||
Projectile* mProjectile;
|
Projectile* mProjectile;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
#define OPENMW_MWPHYSICS_PTRHOLDER_H
|
#define OPENMW_MWPHYSICS_PTRHOLDER_H
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
|
@ -10,31 +13,26 @@ namespace MWPhysics
|
||||||
class PtrHolder
|
class PtrHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~PtrHolder() {}
|
virtual ~PtrHolder() = default;
|
||||||
|
|
||||||
void updatePtr(const MWWorld::Ptr& updated)
|
void updatePtr(const MWWorld::Ptr& updated)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mMutex);
|
|
||||||
mPtr = updated;
|
mPtr = updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr getPtr()
|
MWWorld::Ptr getPtr()
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mMutex);
|
|
||||||
return mPtr;
|
return mPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::ConstPtr getPtr() const
|
btCollisionObject* getCollisionObject() const
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mMutex);
|
return mCollisionObject.get();
|
||||||
return mPtr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MWWorld::Ptr mPtr;
|
MWWorld::Ptr mPtr;
|
||||||
|
std::unique_ptr<btCollisionObject> mCollisionObject;
|
||||||
private:
|
|
||||||
mutable std::mutex mMutex;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -521,7 +521,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::projectileHit(caster, target, bow, projectileRef.getPtr(), pos, projectileState.mAttackStrength);
|
MWMechanics::projectileHit(caster, target, bow, projectileRef.getPtr(), pos, projectileState.mAttackStrength);
|
||||||
cleanupProjectile(projectileState);
|
projectileState.mToDelete = true;
|
||||||
}
|
}
|
||||||
for (auto& magicBoltState : mMagicBolts)
|
for (auto& magicBoltState : mMagicBolts)
|
||||||
{
|
{
|
||||||
|
|
@ -550,7 +550,19 @@ namespace MWWorld
|
||||||
cast.inflict(target, caster, magicBoltState.mEffects, ESM::RT_Target, false, true);
|
cast.inflict(target, caster, magicBoltState.mEffects, ESM::RT_Target, false, true);
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->explodeSpell(pos, magicBoltState.mEffects, caster, target, ESM::RT_Target, magicBoltState.mSpellId, magicBoltState.mSourceName);
|
MWBase::Environment::get().getWorld()->explodeSpell(pos, magicBoltState.mEffects, caster, target, ESM::RT_Target, magicBoltState.mSpellId, magicBoltState.mSourceName);
|
||||||
cleanupMagicBolt(magicBoltState);
|
magicBoltState.mToDelete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& projectileState : mProjectiles)
|
||||||
|
{
|
||||||
|
if (projectileState.mToDelete)
|
||||||
|
cleanupProjectile(projectileState);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& magicBoltState : mMagicBolts)
|
||||||
|
{
|
||||||
|
if (magicBoltState.mToDelete)
|
||||||
|
cleanupMagicBolt(magicBoltState);
|
||||||
}
|
}
|
||||||
mProjectiles.erase(std::remove_if(mProjectiles.begin(), mProjectiles.end(), [](const State& state) { return state.mToDelete; }),
|
mProjectiles.erase(std::remove_if(mProjectiles.begin(), mProjectiles.end(), [](const State& state) { return state.mToDelete; }),
|
||||||
mProjectiles.end());
|
mProjectiles.end());
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue