diff --git a/apps/openmw/mwphysics/closestnotmeconvexresultcallback.cpp b/apps/openmw/mwphysics/closestnotmeconvexresultcallback.cpp index b709811f41..bbffe16a8e 100644 --- a/apps/openmw/mwphysics/closestnotmeconvexresultcallback.cpp +++ b/apps/openmw/mwphysics/closestnotmeconvexresultcallback.cpp @@ -30,9 +30,7 @@ namespace MWPhysics return btScalar(1); PtrHolder* targetHolder = static_cast(mMe->getUserPointer()); const MWWorld::Ptr target = targetHolder->getPtr(); - - osg::Vec3f pos = Misc::Convert::makeOsgVec3f(convexResult.m_hitPointLocal); - projectileHolder->hit(target, pos); + projectileHolder->hit(target, convexResult.m_hitPointLocal, convexResult.m_hitNormalLocal); return btScalar(1); } diff --git a/apps/openmw/mwphysics/closestnotmerayresultcallback.cpp b/apps/openmw/mwphysics/closestnotmerayresultcallback.cpp index 43e1d5c628..422ca78bd5 100644 --- a/apps/openmw/mwphysics/closestnotmerayresultcallback.cpp +++ b/apps/openmw/mwphysics/closestnotmerayresultcallback.cpp @@ -1,19 +1,22 @@ #include "closestnotmerayresultcallback.hpp" #include +#include #include #include "../mwworld/class.hpp" +#include "actor.hpp" +#include "collisiontype.hpp" #include "projectile.hpp" #include "ptrholder.hpp" namespace MWPhysics { - ClosestNotMeRayResultCallback::ClosestNotMeRayResultCallback(const btCollisionObject* me, const std::vector& targets, const btVector3& from, const btVector3& to, int projId) + ClosestNotMeRayResultCallback::ClosestNotMeRayResultCallback(const btCollisionObject* me, std::vector targets, const btVector3& from, const btVector3& to, Projectile* proj) : btCollisionWorld::ClosestRayResultCallback(from, to) - , mMe(me), mTargets(targets), mProjectileId(projId) + , mMe(me), mTargets(std::move(targets)), mProjectile(proj) { } @@ -25,20 +28,27 @@ namespace MWPhysics { if ((std::find(mTargets.begin(), mTargets.end(), rayResult.m_collisionObject) == mTargets.end())) { - PtrHolder* holder = static_cast(rayResult.m_collisionObject->getUserPointer()); + auto* holder = static_cast(rayResult.m_collisionObject->getUserPointer()); if (holder && !holder->getPtr().isEmpty() && holder->getPtr().getClass().isActor()) return 1.f; } } - if (mProjectileId >= 0) + btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); + if (mProjectile) { - PtrHolder* holder = static_cast(rayResult.m_collisionObject->getUserPointer()); - Projectile* projectile = dynamic_cast(holder); - if (projectile && projectile->getProjectileId() == mProjectileId) - return 1.f; + auto* holder = static_cast(rayResult.m_collisionObject->getUserPointer()); + if (auto* target = dynamic_cast(holder)) + { + mProjectile->hit(target->getPtr(), m_hitPointWorld, m_hitNormalWorld); + } + else if (auto* target = dynamic_cast(holder)) + { + target->hit(mProjectile->getPtr(), m_hitPointWorld, m_hitNormalWorld); + mProjectile->hit(target->getPtr(), m_hitPointWorld, m_hitNormalWorld); + } } - return btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); + return rayResult.m_hitFraction; } } diff --git a/apps/openmw/mwphysics/closestnotmerayresultcallback.hpp b/apps/openmw/mwphysics/closestnotmerayresultcallback.hpp index d27d64c535..b86427165a 100644 --- a/apps/openmw/mwphysics/closestnotmerayresultcallback.hpp +++ b/apps/openmw/mwphysics/closestnotmerayresultcallback.hpp @@ -9,16 +9,18 @@ class btCollisionObject; namespace MWPhysics { + class Projectile; + class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback { public: - ClosestNotMeRayResultCallback(const btCollisionObject* me, const std::vector& targets, const btVector3& from, const btVector3& to, int projId=-1); + ClosestNotMeRayResultCallback(const btCollisionObject* me, std::vector targets, const btVector3& from, const btVector3& to, Projectile* proj=nullptr); btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) override; private: const btCollisionObject* mMe; const std::vector mTargets; - const int mProjectileId; + Projectile* mProjectile; }; } diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 78010fb0ee..7da2a69643 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -288,7 +288,7 @@ namespace MWPhysics } } - ClosestNotMeRayResultCallback resultCallback(me, targetCollisionObjects, btFrom, btTo, projId); + ClosestNotMeRayResultCallback resultCallback(me, targetCollisionObjects, btFrom, btTo, getProjectile(projId)); resultCallback.m_collisionFilterGroup = group; resultCallback.m_collisionFilterMask = mask; @@ -664,7 +664,7 @@ namespace MWPhysics int PhysicsSystem::addProjectile (const osg::Vec3f& position) { mProjectileId++; - auto projectile = std::make_shared(mProjectileId, position, mTaskScheduler.get()); + auto projectile = std::make_shared(mProjectileId, position, mTaskScheduler.get(), this); mProjectiles.emplace(mProjectileId, std::move(projectile)); return mProjectileId; diff --git a/apps/openmw/mwphysics/projectile.cpp b/apps/openmw/mwphysics/projectile.cpp index 8abf238cf2..cbc5b19814 100644 --- a/apps/openmw/mwphysics/projectile.cpp +++ b/apps/openmw/mwphysics/projectile.cpp @@ -18,8 +18,9 @@ namespace MWPhysics { -Projectile::Projectile(int projectileId, const osg::Vec3f& position, PhysicsTaskScheduler* scheduler) +Projectile::Projectile(int projectileId, const osg::Vec3f& position, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem) : mActive(true) + , mPhysics(physicssystem) , mTaskScheduler(scheduler) , mProjectileId(projectileId) { @@ -35,7 +36,7 @@ Projectile::Projectile(int projectileId, const osg::Vec3f& position, PhysicsTask setPosition(position); const int collisionMask = CollisionType_World | CollisionType_HeightMap | - CollisionType_Actor | CollisionType_Door | CollisionType_Water; + CollisionType_Actor | CollisionType_Door | CollisionType_Water | CollisionType_Projectile; mTaskScheduler->addCollisionObject(mCollisionObject.get(), CollisionType_Projectile, collisionMask); commitPositionChange(); @@ -44,7 +45,11 @@ Projectile::Projectile(int projectileId, const osg::Vec3f& position, PhysicsTask Projectile::~Projectile() { if (mCollisionObject) + { + if (!mActive) + mPhysics->reportCollision(mHitPosition, mHitNormal); mTaskScheduler->removeCollisionObject(mCollisionObject.get()); + } } void Projectile::commitPositionChange() @@ -64,13 +69,14 @@ void Projectile::setPosition(const osg::Vec3f &position) mTransformUpdatePending = true; } -void Projectile::hit(MWWorld::Ptr target, osg::Vec3f pos) +void Projectile::hit(MWWorld::Ptr target, btVector3 pos, btVector3 normal) { if (!mActive.load(std::memory_order_acquire)) return; std::unique_lock lock(mPositionMutex); mHitTarget = target; mHitPosition = pos; + mHitNormal = normal; mActive.store(false, std::memory_order_release); } diff --git a/apps/openmw/mwphysics/projectile.hpp b/apps/openmw/mwphysics/projectile.hpp index 7ad0a31246..6e8aba60b8 100644 --- a/apps/openmw/mwphysics/projectile.hpp +++ b/apps/openmw/mwphysics/projectile.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include "components/misc/convert.hpp" #include "ptrholder.hpp" @@ -32,7 +32,7 @@ namespace MWPhysics class Projectile final : public PtrHolder { public: - Projectile(const int projectileId, const osg::Vec3f& position, PhysicsTaskScheduler* scheduler); + Projectile(const int projectileId, const osg::Vec3f& position, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem); ~Projectile() override; btConvexShape* getConvexShape() const { return mConvexShape; } @@ -68,7 +68,7 @@ namespace MWPhysics return Misc::Convert::toOsg(mHitPosition); } - void hit(MWWorld::Ptr target, osg::Vec3f pos); + void hit(MWWorld::Ptr target, btVector3 pos, btVector3 normal); void activate(); private: @@ -81,12 +81,14 @@ namespace MWPhysics bool mTransformUpdatePending; std::atomic mActive; MWWorld::Ptr mHitTarget; - osg::Vec3f mHitPosition; + btVector3 mHitPosition; + btVector3 mHitNormal; mutable std::mutex mPositionMutex; osg::Vec3f mPosition; + PhysicsSystem *mPhysics; PhysicsTaskScheduler *mTaskScheduler; Projectile(const Projectile&);