1 #ifndef OPENMW_MWPHYSICS_MTPHYSICS_H
2 #define OPENMW_MWPHYSICS_MTPHYSICS_H
3 
4 #include <atomic>
5 #include <condition_variable>
6 #include <optional>
7 #include <shared_mutex>
8 #include <thread>
9 
10 #include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
11 
12 #include <osg/Timer>
13 
14 #include "physicssystem.hpp"
15 #include "ptrholder.hpp"
16 #include "components/misc/budgetmeasurement.hpp"
17 
18 namespace Misc
19 {
20     class Barrier;
21 }
22 
23 namespace MWRender
24 {
25     class DebugDrawer;
26 }
27 
28 namespace MWPhysics
29 {
30     class PhysicsTaskScheduler
31     {
32         public:
33             PhysicsTaskScheduler(float physicsDt, btCollisionWorld* collisionWorld, MWRender::DebugDrawer* debugDrawer);
34             ~PhysicsTaskScheduler();
35 
36             /// @brief move actors taking into account desired movements and collisions
37             /// @param numSteps how much simulation step to run
38             /// @param timeAccum accumulated time from previous run to interpolate movements
39             /// @param actorsData per actor data needed to compute new positions
40             /// @return new position of each actor
41             const std::vector<MWWorld::Ptr>& moveActors(float & timeAccum, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
42 
43             const std::vector<MWWorld::Ptr>& resetSimulation(const ActorMap& actors);
44 
45             // Thread safe wrappers
46             void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
47             void convexSweepTest(const btConvexShape* castShape, const btTransform& from, const btTransform& to, btCollisionWorld::ConvexResultCallback& resultCallback) const;
48             void contactTest(btCollisionObject* colObj, btCollisionWorld::ContactResultCallback& resultCallback);
49             std::optional<btVector3> getHitPoint(const btTransform& from, btCollisionObject* target);
50             void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
51             void getAabb(const btCollisionObject* obj, btVector3& min, btVector3& max);
52             void setCollisionFilterMask(btCollisionObject* collisionObject, int collisionFilterMask);
53             void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask);
54             void removeCollisionObject(btCollisionObject* collisionObject);
55             void updateSingleAabb(std::weak_ptr<PtrHolder> ptr, bool immediate=false);
56             bool getLineOfSight(const std::weak_ptr<Actor>& actor1, const std::weak_ptr<Actor>& actor2);
57             void debugDraw();
58 
59         private:
60             void syncComputation();
61             void worker();
62             void updateActorsPositions();
63             bool hasLineOfSight(const Actor* actor1, const Actor* actor2);
64             void refreshLOSCache();
65             void updateAabbs();
66             void updatePtrAabb(const std::weak_ptr<PtrHolder>& ptr);
67             void updateStats(osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
68             std::tuple<int, float> calculateStepConfig(float timeAccum) const;
69             void afterPreStep();
70             void afterPostStep();
71             void afterPostSim();
72 
73             std::unique_ptr<WorldFrameData> mWorldFrameData;
74             std::vector<ActorFrameData> mActorsFrameData;
75             std::vector<MWWorld::Ptr> mMovedActors;
76             float mDefaultPhysicsDt;
77             float mPhysicsDt;
78             float mTimeAccum;
79             btCollisionWorld* mCollisionWorld;
80             MWRender::DebugDrawer* mDebugDrawer;
81             std::vector<LOSRequest> mLOSCache;
82             std::set<std::weak_ptr<PtrHolder>, std::owner_less<std::weak_ptr<PtrHolder>>> mUpdateAabb;
83 
84             // TODO: use std::experimental::flex_barrier or std::barrier once it becomes a thing
85             std::unique_ptr<Misc::Barrier> mPreStepBarrier;
86             std::unique_ptr<Misc::Barrier> mPostStepBarrier;
87             std::unique_ptr<Misc::Barrier> mPostSimBarrier;
88 
89             int mNumThreads;
90             int mNumJobs;
91             int mRemainingSteps;
92             int mLOSCacheExpiry;
93             bool mDeferAabbUpdate;
94             bool mNewFrame;
95             bool mAdvanceSimulation;
96             bool mThreadSafeBullet;
97             bool mQuit;
98             std::atomic<int> mNextJob;
99             std::atomic<int> mNextLOS;
100             std::vector<std::thread> mThreads;
101 
102             mutable std::shared_mutex mSimulationMutex;
103             mutable std::shared_mutex mCollisionWorldMutex;
104             mutable std::shared_mutex mLOSCacheMutex;
105             mutable std::mutex mUpdateAabbMutex;
106             std::condition_variable_any mHasJob;
107 
108             unsigned int mFrameNumber;
109             const osg::Timer* mTimer;
110 
111             int mPrevStepCount;
112             Misc::BudgetMeasurement mBudget;
113             Misc::BudgetMeasurement mAsyncBudget;
114             unsigned int mBudgetCursor;
115             osg::Timer_t mAsyncStartTime;
116             osg::Timer_t mTimeBegin;
117             osg::Timer_t mTimeEnd;
118             osg::Timer_t mFrameStart;
119     };
120 
121 }
122 #endif
123