You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw-tes3mp/apps/openmw/mwphysics/mtphysics.hpp

138 lines
5.5 KiB
C++

#ifndef OPENMW_MWPHYSICS_MTPHYSICS_H
#define OPENMW_MWPHYSICS_MTPHYSICS_H
#include <atomic>
#include <condition_variable>
#include <optional>
#include <shared_mutex>
#include <thread>
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
#include <osg/Timer>
#include "physicssystem.hpp"
#include "ptrholder.hpp"
#include "components/misc/budgetmeasurement.hpp"
namespace Misc
{
class Barrier;
}
namespace MWRender
{
class DebugDrawer;
}
namespace MWPhysics
{
class PhysicsTaskScheduler
{
public:
PhysicsTaskScheduler(float physicsDt, btCollisionWorld* collisionWorld, MWRender::DebugDrawer* debugDrawer);
~PhysicsTaskScheduler();
/// @brief move actors taking into account desired movements and collisions
/// @param numSteps how much simulation step to run
/// @param timeAccum accumulated time from previous run to interpolate movements
/// @param actorsData per actor data needed to compute new positions
/// @return new position of each actor
const std::vector<MWWorld::Ptr>& moveActors(float & timeAccum, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
const std::vector<MWWorld::Ptr>& resetSimulation(const ActorMap& actors);
// Thread safe wrappers
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
void convexSweepTest(const btConvexShape* castShape, const btTransform& from, const btTransform& to, btCollisionWorld::ConvexResultCallback& resultCallback) const;
void contactTest(btCollisionObject* colObj, btCollisionWorld::ContactResultCallback& resultCallback);
std::optional<btVector3> getHitPoint(const btTransform& from, btCollisionObject* target);
void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
void getAabb(const btCollisionObject* obj, btVector3& min, btVector3& max);
void setCollisionFilterMask(btCollisionObject* collisionObject, int collisionFilterMask);
void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask);
void removeCollisionObject(btCollisionObject* collisionObject);
void updateSingleAabb(std::weak_ptr<PtrHolder> ptr, bool immediate=false);
bool getLineOfSight(const std::weak_ptr<Actor>& actor1, const std::weak_ptr<Actor>& actor2);
void debugDraw();
private:
void syncComputation();
void worker();
void updateActorsPositions();
bool hasLineOfSight(const Actor* actor1, const Actor* actor2);
void refreshLOSCache();
void updateAabbs();
void updatePtrAabb(const std::weak_ptr<PtrHolder>& ptr);
void updateStats(osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
std::tuple<int, float> calculateStepConfig(float timeAccum) const;
void afterPreStep();
void afterPostStep();
void afterPostSim();
void waitForWorkers();
std::unique_ptr<WorldFrameData> mWorldFrameData;
std::vector<ActorFrameData> mActorsFrameData;
std::vector<MWWorld::Ptr> mMovedActors;
float mDefaultPhysicsDt;
/*
Start of tes3mp change (major)
Turn mPhysicsDt into a public variable so it can be set from elsewhere
*/
public:
float mPhysicsDt;
private:
/*
End of tes3mp change (major)
*/
float mTimeAccum;
btCollisionWorld* mCollisionWorld;
MWRender::DebugDrawer* mDebugDrawer;
std::vector<LOSRequest> mLOSCache;
std::set<std::weak_ptr<PtrHolder>, std::owner_less<std::weak_ptr<PtrHolder>>> mUpdateAabb;
// TODO: use std::experimental::flex_barrier or std::barrier once it becomes a thing
std::unique_ptr<Misc::Barrier> mPreStepBarrier;
std::unique_ptr<Misc::Barrier> mPostStepBarrier;
std::unique_ptr<Misc::Barrier> mPostSimBarrier;
int mNumThreads;
int mNumJobs;
int mRemainingSteps;
int mLOSCacheExpiry;
bool mDeferAabbUpdate;
std::size_t mFrameCounter;
bool mAdvanceSimulation;
bool mThreadSafeBullet;
bool mQuit;
std::atomic<int> mNextJob;
std::atomic<int> mNextLOS;
std::vector<std::thread> mThreads;
std::size_t mWorkersFrameCounter = 0;
std::condition_variable mWorkersDone;
std::mutex mWorkersDoneMutex;
mutable std::shared_mutex mSimulationMutex;
mutable std::shared_mutex mCollisionWorldMutex;
mutable std::shared_mutex mLOSCacheMutex;
mutable std::mutex mUpdateAabbMutex;
std::condition_variable_any mHasJob;
unsigned int mFrameNumber;
const osg::Timer* mTimer;
int mPrevStepCount;
Misc::BudgetMeasurement mBudget;
Misc::BudgetMeasurement mAsyncBudget;
unsigned int mBudgetCursor;
osg::Timer_t mAsyncStartTime;
osg::Timer_t mTimeBegin;
osg::Timer_t mTimeEnd;
osg::Timer_t mFrameStart;
};
}
#endif