mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-29 01:45:33 +00:00
e5fa457fe7
Before this change, if an actor position was changed while the physics simulation was running, the simulation result would be discarded. It is fine in case of one off event such as teleport, but in the case of scripts making use of this functionality to make lifts or conveyor (such as Sotha Sil Expanded mod) it broke actor movement. To alleviate this issue, at the end of the simulation, the position of the Actor in the world is compared to the position it had at the beginning of the simulation. A difference indicate a force move occured. In this case, the Actor mPosition and mPreviousPosition are translated by the difference of position. Since the Actor position will be really set while the next simulation runs, we save it in the mNextPosition field.
93 lines
4.1 KiB
C++
93 lines
4.1 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 "physicssystem.hpp"
|
|
#include "ptrholder.hpp"
|
|
|
|
namespace Misc
|
|
{
|
|
class Barrier;
|
|
}
|
|
|
|
namespace MWPhysics
|
|
{
|
|
class PhysicsTaskScheduler
|
|
{
|
|
public:
|
|
PhysicsTaskScheduler(float physicsDt, std::shared_ptr<btCollisionWorld> collisionWorld);
|
|
~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 PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector<ActorFrameData>&& actorsData, CollisionMap& standingCollisions, bool skip);
|
|
|
|
// 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 getLineOfSight(const std::weak_ptr<Actor>& actor1, const std::weak_ptr<Actor>& actor2);
|
|
|
|
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);
|
|
|
|
std::unique_ptr<WorldFrameData> mWorldFrameData;
|
|
std::vector<ActorFrameData> mActorsFrameData;
|
|
PtrPositionList mMovementResults;
|
|
PtrPositionList mPreviousMovementResults;
|
|
const float mPhysicsDt;
|
|
float mTimeAccum;
|
|
std::shared_ptr<btCollisionWorld> mCollisionWorld;
|
|
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;
|
|
bool mNewFrame;
|
|
bool mAdvanceSimulation;
|
|
bool mThreadSafeBullet;
|
|
bool mQuit;
|
|
std::atomic<int> mNextJob;
|
|
std::atomic<int> mNextLOS;
|
|
std::vector<std::thread> mThreads;
|
|
|
|
mutable std::shared_mutex mSimulationMutex;
|
|
mutable std::shared_mutex mCollisionWorldMutex;
|
|
mutable std::shared_mutex mLOSCacheMutex;
|
|
mutable std::mutex mUpdateAabbMutex;
|
|
std::condition_variable_any mHasJob;
|
|
};
|
|
|
|
}
|
|
#endif
|