1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-01 02:45:32 +00:00

Projectile to projectile collision

This commit is contained in:
fredzio 2020-10-31 14:01:14 +01:00 committed by Frederic Chardon
parent 66fe3b0d38
commit 7e85235220
6 changed files with 41 additions and 23 deletions

View file

@ -30,9 +30,7 @@ namespace MWPhysics
return btScalar(1); return btScalar(1);
PtrHolder* targetHolder = static_cast<PtrHolder*>(mMe->getUserPointer()); PtrHolder* targetHolder = static_cast<PtrHolder*>(mMe->getUserPointer());
const MWWorld::Ptr target = targetHolder->getPtr(); const MWWorld::Ptr target = targetHolder->getPtr();
projectileHolder->hit(target, convexResult.m_hitPointLocal, convexResult.m_hitNormalLocal);
osg::Vec3f pos = Misc::Convert::makeOsgVec3f(convexResult.m_hitPointLocal);
projectileHolder->hit(target, pos);
return btScalar(1); return btScalar(1);
} }

View file

@ -1,19 +1,22 @@
#include "closestnotmerayresultcallback.hpp" #include "closestnotmerayresultcallback.hpp"
#include <algorithm> #include <algorithm>
#include <utility>
#include <BulletCollision/CollisionDispatch/btCollisionObject.h> #include <BulletCollision/CollisionDispatch/btCollisionObject.h>
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "actor.hpp"
#include "collisiontype.hpp"
#include "projectile.hpp" #include "projectile.hpp"
#include "ptrholder.hpp" #include "ptrholder.hpp"
namespace MWPhysics namespace MWPhysics
{ {
ClosestNotMeRayResultCallback::ClosestNotMeRayResultCallback(const btCollisionObject* me, const std::vector<const btCollisionObject*>& targets, const btVector3& from, const btVector3& to, int projId) ClosestNotMeRayResultCallback::ClosestNotMeRayResultCallback(const btCollisionObject* me, std::vector<const btCollisionObject*> targets, const btVector3& from, const btVector3& to, Projectile* proj)
: btCollisionWorld::ClosestRayResultCallback(from, to) : 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())) if ((std::find(mTargets.begin(), mTargets.end(), rayResult.m_collisionObject) == mTargets.end()))
{ {
PtrHolder* holder = static_cast<PtrHolder*>(rayResult.m_collisionObject->getUserPointer()); auto* holder = static_cast<PtrHolder*>(rayResult.m_collisionObject->getUserPointer());
if (holder && !holder->getPtr().isEmpty() && holder->getPtr().getClass().isActor()) if (holder && !holder->getPtr().isEmpty() && holder->getPtr().getClass().isActor())
return 1.f; return 1.f;
} }
} }
if (mProjectileId >= 0) btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
if (mProjectile)
{ {
PtrHolder* holder = static_cast<PtrHolder*>(rayResult.m_collisionObject->getUserPointer()); auto* holder = static_cast<PtrHolder*>(rayResult.m_collisionObject->getUserPointer());
Projectile* projectile = dynamic_cast<Projectile*>(holder); if (auto* target = dynamic_cast<Actor*>(holder))
if (projectile && projectile->getProjectileId() == mProjectileId) {
return 1.f; mProjectile->hit(target->getPtr(), m_hitPointWorld, m_hitNormalWorld);
}
else if (auto* target = dynamic_cast<Projectile*>(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;
} }
} }

View file

@ -9,16 +9,18 @@ class btCollisionObject;
namespace MWPhysics namespace MWPhysics
{ {
class Projectile;
class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
{ {
public: public:
ClosestNotMeRayResultCallback(const btCollisionObject* me, const std::vector<const btCollisionObject*>& targets, const btVector3& from, const btVector3& to, int projId=-1); ClosestNotMeRayResultCallback(const btCollisionObject* me, std::vector<const btCollisionObject*> targets, const btVector3& from, const btVector3& to, Projectile* proj=nullptr);
btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) override; btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) override;
private: private:
const btCollisionObject* mMe; const btCollisionObject* mMe;
const std::vector<const btCollisionObject*> mTargets; const std::vector<const btCollisionObject*> mTargets;
const int mProjectileId; Projectile* mProjectile;
}; };
} }

View file

@ -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_collisionFilterGroup = group;
resultCallback.m_collisionFilterMask = mask; resultCallback.m_collisionFilterMask = mask;
@ -664,7 +664,7 @@ namespace MWPhysics
int PhysicsSystem::addProjectile (const osg::Vec3f& position) int PhysicsSystem::addProjectile (const osg::Vec3f& position)
{ {
mProjectileId++; mProjectileId++;
auto projectile = std::make_shared<Projectile>(mProjectileId, position, mTaskScheduler.get()); auto projectile = std::make_shared<Projectile>(mProjectileId, position, mTaskScheduler.get(), this);
mProjectiles.emplace(mProjectileId, std::move(projectile)); mProjectiles.emplace(mProjectileId, std::move(projectile));
return mProjectileId; return mProjectileId;

View file

@ -18,8 +18,9 @@
namespace MWPhysics 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) : mActive(true)
, mPhysics(physicssystem)
, mTaskScheduler(scheduler) , mTaskScheduler(scheduler)
, mProjectileId(projectileId) , mProjectileId(projectileId)
{ {
@ -35,7 +36,7 @@ Projectile::Projectile(int projectileId, const osg::Vec3f& position, PhysicsTask
setPosition(position); setPosition(position);
const int collisionMask = CollisionType_World | CollisionType_HeightMap | 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); mTaskScheduler->addCollisionObject(mCollisionObject.get(), CollisionType_Projectile, collisionMask);
commitPositionChange(); commitPositionChange();
@ -44,8 +45,12 @@ Projectile::Projectile(int projectileId, const osg::Vec3f& position, PhysicsTask
Projectile::~Projectile() Projectile::~Projectile()
{ {
if (mCollisionObject) if (mCollisionObject)
{
if (!mActive)
mPhysics->reportCollision(mHitPosition, mHitNormal);
mTaskScheduler->removeCollisionObject(mCollisionObject.get()); mTaskScheduler->removeCollisionObject(mCollisionObject.get());
} }
}
void Projectile::commitPositionChange() void Projectile::commitPositionChange()
{ {
@ -64,13 +69,14 @@ void Projectile::setPosition(const osg::Vec3f &position)
mTransformUpdatePending = true; 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)) if (!mActive.load(std::memory_order_acquire))
return; return;
std::unique_lock<std::mutex> lock(mPositionMutex); std::unique_lock<std::mutex> lock(mPositionMutex);
mHitTarget = target; mHitTarget = target;
mHitPosition = pos; mHitPosition = pos;
mHitNormal = normal;
mActive.store(false, std::memory_order_release); mActive.store(false, std::memory_order_release);
} }

View file

@ -5,7 +5,7 @@
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <components/misc/convert.hpp> #include "components/misc/convert.hpp"
#include "ptrholder.hpp" #include "ptrholder.hpp"
@ -32,7 +32,7 @@ namespace MWPhysics
class Projectile final : public PtrHolder class Projectile final : public PtrHolder
{ {
public: 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; ~Projectile() override;
btConvexShape* getConvexShape() const { return mConvexShape; } btConvexShape* getConvexShape() const { return mConvexShape; }
@ -68,7 +68,7 @@ namespace MWPhysics
return Misc::Convert::toOsg(mHitPosition); return Misc::Convert::toOsg(mHitPosition);
} }
void hit(MWWorld::Ptr target, osg::Vec3f pos); void hit(MWWorld::Ptr target, btVector3 pos, btVector3 normal);
void activate(); void activate();
private: private:
@ -81,12 +81,14 @@ namespace MWPhysics
bool mTransformUpdatePending; bool mTransformUpdatePending;
std::atomic<bool> mActive; std::atomic<bool> mActive;
MWWorld::Ptr mHitTarget; MWWorld::Ptr mHitTarget;
osg::Vec3f mHitPosition; btVector3 mHitPosition;
btVector3 mHitNormal;
mutable std::mutex mPositionMutex; mutable std::mutex mPositionMutex;
osg::Vec3f mPosition; osg::Vec3f mPosition;
PhysicsSystem *mPhysics;
PhysicsTaskScheduler *mTaskScheduler; PhysicsTaskScheduler *mTaskScheduler;
Projectile(const Projectile&); Projectile(const Projectile&);