|
|
|
@ -185,7 +185,7 @@ namespace MWPhysics
|
|
|
|
|
mNewFrame = false;
|
|
|
|
|
if (mLOSCacheExpiry >= 0)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock(mLOSCacheMutex);
|
|
|
|
|
std::unique_lock lock(mLOSCacheMutex);
|
|
|
|
|
mLOSCache.erase(
|
|
|
|
|
std::remove_if(mLOSCache.begin(), mLOSCache.end(),
|
|
|
|
|
[](const LOSRequest& req) { return req.mStale; }),
|
|
|
|
@ -196,7 +196,7 @@ namespace MWPhysics
|
|
|
|
|
|
|
|
|
|
PhysicsTaskScheduler::~PhysicsTaskScheduler()
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock(mSimulationMutex);
|
|
|
|
|
std::unique_lock lock(mSimulationMutex);
|
|
|
|
|
mQuit = true;
|
|
|
|
|
mNumJobs = 0;
|
|
|
|
|
mRemainingSteps = 0;
|
|
|
|
@ -211,7 +211,7 @@ namespace MWPhysics
|
|
|
|
|
// This function run in the main thread.
|
|
|
|
|
// While the mSimulationMutex is held, background physics threads can't run.
|
|
|
|
|
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock(mSimulationMutex);
|
|
|
|
|
std::unique_lock lock(mSimulationMutex);
|
|
|
|
|
|
|
|
|
|
// start by finishing previous background computation
|
|
|
|
|
if (mNumThreads != 0)
|
|
|
|
@ -294,25 +294,25 @@ namespace MWPhysics
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
|
|
|
|
|
{
|
|
|
|
|
MaybeSharedLock<std::shared_timed_mutex> lock(mCollisionWorldMutex, mThreadSafeBullet);
|
|
|
|
|
MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet);
|
|
|
|
|
mCollisionWorld->rayTest(rayFromWorld, rayToWorld, resultCallback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::convexSweepTest(const btConvexShape* castShape, const btTransform& from, const btTransform& to, btCollisionWorld::ConvexResultCallback& resultCallback) const
|
|
|
|
|
{
|
|
|
|
|
MaybeSharedLock<std::shared_timed_mutex> lock(mCollisionWorldMutex, mThreadSafeBullet);
|
|
|
|
|
MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet);
|
|
|
|
|
mCollisionWorld->convexSweepTest(castShape, from, to, resultCallback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::contactTest(btCollisionObject* colObj, btCollisionWorld::ContactResultCallback& resultCallback)
|
|
|
|
|
{
|
|
|
|
|
std::shared_lock<std::shared_timed_mutex> lock(mCollisionWorldMutex);
|
|
|
|
|
std::shared_lock lock(mCollisionWorldMutex);
|
|
|
|
|
mCollisionWorld->contactTest(colObj, resultCallback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boost::optional<btVector3> PhysicsTaskScheduler::getHitPoint(const btTransform& from, btCollisionObject* target)
|
|
|
|
|
std::optional<btVector3> PhysicsTaskScheduler::getHitPoint(const btTransform& from, btCollisionObject* target)
|
|
|
|
|
{
|
|
|
|
|
MaybeSharedLock<std::shared_timed_mutex> lock(mCollisionWorldMutex, mThreadSafeBullet);
|
|
|
|
|
MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet);
|
|
|
|
|
// target the collision object's world origin, this should be the center of the collision object
|
|
|
|
|
btTransform rayTo;
|
|
|
|
|
rayTo.setIdentity();
|
|
|
|
@ -323,37 +323,37 @@ namespace MWPhysics
|
|
|
|
|
mCollisionWorld->rayTestSingle(from, rayTo, target, target->getCollisionShape(), target->getWorldTransform(), cb);
|
|
|
|
|
if (!cb.hasHit())
|
|
|
|
|
// didn't hit the target. this could happen if point is already inside the collision box
|
|
|
|
|
return boost::none;
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
return {cb.m_hitPointWorld};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
|
|
|
|
|
{
|
|
|
|
|
std::shared_lock<std::shared_timed_mutex> lock(mCollisionWorldMutex);
|
|
|
|
|
std::shared_lock lock(mCollisionWorldMutex);
|
|
|
|
|
mCollisionWorld->getBroadphase()->aabbTest(aabbMin, aabbMax, callback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::getAabb(const btCollisionObject* obj, btVector3& min, btVector3& max)
|
|
|
|
|
{
|
|
|
|
|
std::shared_lock<std::shared_timed_mutex> lock(mCollisionWorldMutex);
|
|
|
|
|
std::shared_lock lock(mCollisionWorldMutex);
|
|
|
|
|
obj->getCollisionShape()->getAabb(obj->getWorldTransform(), min, max);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::setCollisionFilterMask(btCollisionObject* collisionObject, int collisionFilterMask)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock(mCollisionWorldMutex);
|
|
|
|
|
std::unique_lock lock(mCollisionWorldMutex);
|
|
|
|
|
collisionObject->getBroadphaseHandle()->m_collisionFilterMask = collisionFilterMask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock(mCollisionWorldMutex);
|
|
|
|
|
std::unique_lock lock(mCollisionWorldMutex);
|
|
|
|
|
mCollisionWorld->addCollisionObject(collisionObject, collisionFilterGroup, collisionFilterMask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::removeCollisionObject(btCollisionObject* collisionObject)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock(mCollisionWorldMutex);
|
|
|
|
|
std::unique_lock lock(mCollisionWorldMutex);
|
|
|
|
|
mCollisionWorld->removeCollisionObject(collisionObject);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -361,19 +361,19 @@ namespace MWPhysics
|
|
|
|
|
{
|
|
|
|
|
if (mDeferAabbUpdate)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(mUpdateAabbMutex);
|
|
|
|
|
std::unique_lock lock(mUpdateAabbMutex);
|
|
|
|
|
mUpdateAabb.insert(std::move(ptr));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock(mCollisionWorldMutex);
|
|
|
|
|
std::unique_lock lock(mCollisionWorldMutex);
|
|
|
|
|
updatePtrAabb(ptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PhysicsTaskScheduler::getLineOfSight(const std::weak_ptr<Actor>& actor1, const std::weak_ptr<Actor>& actor2)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock(mLOSCacheMutex);
|
|
|
|
|
std::unique_lock lock(mLOSCacheMutex);
|
|
|
|
|
|
|
|
|
|
auto actorPtr1 = actor1.lock();
|
|
|
|
|
auto actorPtr2 = actor2.lock();
|
|
|
|
@ -395,7 +395,7 @@ namespace MWPhysics
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::refreshLOSCache()
|
|
|
|
|
{
|
|
|
|
|
std::shared_lock<std::shared_timed_mutex> lock(mLOSCacheMutex);
|
|
|
|
|
std::shared_lock lock(mLOSCacheMutex);
|
|
|
|
|
int job = 0;
|
|
|
|
|
int numLOS = mLOSCache.size();
|
|
|
|
|
while ((job = mNextLOS.fetch_add(1, std::memory_order_relaxed)) < numLOS)
|
|
|
|
@ -414,9 +414,7 @@ namespace MWPhysics
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::updateAabbs()
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock1(mCollisionWorldMutex, std::defer_lock);
|
|
|
|
|
std::unique_lock<std::mutex> lock2(mUpdateAabbMutex, std::defer_lock);
|
|
|
|
|
std::lock(lock1, lock2);
|
|
|
|
|
std::scoped_lock lock(mCollisionWorldMutex, mUpdateAabbMutex);
|
|
|
|
|
std::for_each(mUpdateAabb.begin(), mUpdateAabb.end(),
|
|
|
|
|
[this](const std::weak_ptr<PtrHolder>& ptr) { updatePtrAabb(ptr); });
|
|
|
|
|
mUpdateAabb.clear();
|
|
|
|
@ -441,7 +439,7 @@ namespace MWPhysics
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::worker()
|
|
|
|
|
{
|
|
|
|
|
std::shared_lock<std::shared_timed_mutex> lock(mSimulationMutex);
|
|
|
|
|
std::shared_lock lock(mSimulationMutex);
|
|
|
|
|
while (!mQuit)
|
|
|
|
|
{
|
|
|
|
|
if (!mNewFrame)
|
|
|
|
@ -453,7 +451,7 @@ namespace MWPhysics
|
|
|
|
|
int job = 0;
|
|
|
|
|
while (mRemainingSteps && (job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs)
|
|
|
|
|
{
|
|
|
|
|
MaybeSharedLock<std::shared_timed_mutex> lockColWorld(mCollisionWorldMutex, mThreadSafeBullet);
|
|
|
|
|
MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet);
|
|
|
|
|
if(const auto actor = mActorsFrameData[job].mActor.lock())
|
|
|
|
|
MovementSolver::move(mActorsFrameData[job], mPhysicsDt, mCollisionWorld.get(), *mWorldFrameData);
|
|
|
|
|
}
|
|
|
|
@ -481,7 +479,7 @@ namespace MWPhysics
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::updateActorsPositions()
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock(mCollisionWorldMutex);
|
|
|
|
|
std::unique_lock lock(mCollisionWorldMutex);
|
|
|
|
|
for (auto& actorData : mActorsFrameData)
|
|
|
|
|
{
|
|
|
|
|
if(const auto actor = actorData.mActor.lock())
|
|
|
|
@ -499,7 +497,7 @@ namespace MWPhysics
|
|
|
|
|
|
|
|
|
|
void PhysicsTaskScheduler::udpateActorsAabbs()
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::shared_timed_mutex> lock(mCollisionWorldMutex);
|
|
|
|
|
std::unique_lock lock(mCollisionWorldMutex);
|
|
|
|
|
for (const auto& actorData : mActorsFrameData)
|
|
|
|
|
if (actorData.mPositionChanged)
|
|
|
|
|
{
|
|
|
|
@ -517,7 +515,7 @@ namespace MWPhysics
|
|
|
|
|
resultCallback.m_collisionFilterGroup = 0xFF;
|
|
|
|
|
resultCallback.m_collisionFilterMask = CollisionType_World|CollisionType_HeightMap|CollisionType_Door;
|
|
|
|
|
|
|
|
|
|
MaybeSharedLock<std::shared_timed_mutex> lockColWorld(mCollisionWorldMutex, mThreadSafeBullet);
|
|
|
|
|
MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet);
|
|
|
|
|
mCollisionWorld->rayTest(pos1, pos2, resultCallback);
|
|
|
|
|
|
|
|
|
|
return !resultCallback.hasHit();
|
|
|
|
|