1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-30 12:32:36 +00:00
OpenMW/apps/openmw/mwphysics/projectile.hpp
fredzio 07fa1803f7 Use btCollisionObject* instead of MWWorld::Ptr inside of Projectile
collision handling and castRay() to avoid calling getPtr(). It is a step forward
removing the mutex inside of PtrHolder.

Do the same for DeepestNotMeContactTestResultCallback. It is used
only for not-ranged combat for now, but do it anyway for parity with all
other callback. This way, once the PtrHolder mutex is gone one will not
have to worry about wether it is safe to use the callback in a specific
context.

To avoid use-after-free with projectile / projectile collision, defer deletion of projectile.
Since instead of storing a copy of target Ptr we have a pointer to its collision object,
we can't delete projectiles until after we finished iterating over the loops.
2021-08-08 15:05:07 +02:00

101 lines
2.4 KiB
C++

#ifndef OPENMW_MWPHYSICS_PROJECTILE_H
#define OPENMW_MWPHYSICS_PROJECTILE_H
#include <atomic>
#include <memory>
#include <mutex>
#include <optional>
#include <LinearMath/btVector3.h>
#include "ptrholder.hpp"
class btCollisionObject;
class btCollisionShape;
class btConvexShape;
namespace osg
{
class Vec3f;
}
namespace Resource
{
class BulletShape;
}
namespace MWPhysics
{
class PhysicsTaskScheduler;
class PhysicsSystem;
class Projectile final : public PtrHolder
{
public:
Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, float radius, bool canCrossWaterSurface, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem);
~Projectile() override;
btConvexShape* getConvexShape() const { return mConvexShape; }
void commitPositionChange();
void setPosition(const osg::Vec3f& position);
osg::Vec3f getPosition() const;
bool isActive() const
{
return mActive.load(std::memory_order_acquire);
}
MWWorld::Ptr getTarget() const;
MWWorld::Ptr getCaster() const;
void setCaster(const MWWorld::Ptr& caster);
const btCollisionObject* getCasterCollisionObject() const
{
return mCasterColObj;
}
bool canTraverseWater() const;
void hit(const btCollisionObject* target, btVector3 pos, btVector3 normal);
void setValidTargets(const std::vector<MWWorld::Ptr>& targets);
bool isValidTarget(const btCollisionObject* target) const;
std::optional<btVector3> getWaterHitPosition();
void setWaterHitPosition(btVector3 pos);
private:
std::unique_ptr<btCollisionShape> mShape;
btConvexShape* mConvexShape;
bool mTransformUpdatePending;
bool mCanCrossWaterSurface;
bool mCrossedWaterSurface;
std::atomic<bool> mActive;
MWWorld::Ptr mCaster;
const btCollisionObject* mCasterColObj;
const btCollisionObject* mHitTarget;
std::optional<btVector3> mWaterHitPosition;
osg::Vec3f mPosition;
btVector3 mHitPosition;
btVector3 mHitNormal;
std::vector<const btCollisionObject*> mValidTargets;
mutable std::mutex mMutex;
PhysicsSystem *mPhysics;
PhysicsTaskScheduler *mTaskScheduler;
Projectile(const Projectile&);
Projectile& operator=(const Projectile&);
};
}
#endif