1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-29 13:20:35 +00:00

Store the btCollisionObject* of the object we're standing on instead of

MWWorld::Ptr:
- they are equivalent
- btCollisionObject* is readily available from the simulation, it saves
  a call to a mutex
- btCollisionObject* is smaller
This commit is contained in:
fredzio 2021-07-23 22:37:55 +02:00
parent 26d9052b8c
commit 0c5cf6ec19
5 changed files with 42 additions and 32 deletions

View File

@ -345,13 +345,9 @@ namespace MWPhysics
{
isOnGround = true;
isOnSlope = !isWalkableSlope(tracer.mPlaneNormal);
actor.mStandingOn = tracer.mHitObject;
const btCollisionObject* standingOn = tracer.mHitObject;
PtrHolder* ptrHolder = static_cast<PtrHolder*>(standingOn->getUserPointer());
if (ptrHolder)
actor.mStandingOn = ptrHolder->getPtr();
if (standingOn->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Water)
if (actor.mStandingOn->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Water)
actor.mWalkingOnWater = true;
if (!actor.mFlying && !isOnSlope)
{

View File

@ -83,21 +83,6 @@ namespace
return actorData.mPosition * interpolationFactor + actor.getPreviousPosition() * (1.f - interpolationFactor);
}
void updateActor(MWPhysics::Actor& actor, MWPhysics::ActorFrameData& actorData, bool simulationPerformed, float timeAccum, float dt)
{
actor.setSimulationPosition(interpolateMovements(actor, actorData, timeAccum, dt));
actor.setLastStuckPosition(actorData.mLastStuckPosition);
actor.setStuckFrames(actorData.mStuckFrames);
if (simulationPerformed)
{
actor.setStandingOnPtr(actorData.mStandingOn);
actor.setOnGround(actorData.mIsOnGround);
actor.setOnSlope(actorData.mIsOnSlope);
actor.setWalkingOnWater(actorData.mWalkingOnWater);
actor.setInertialForce(actorData.mInertia);
}
}
namespace Config
{
/// @return either the number of thread as configured by the user, or 1 if Bullet doesn't support multithreading
@ -357,12 +342,14 @@ namespace MWPhysics
void PhysicsTaskScheduler::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
{
mCollisionObjects.insert(collisionObject);
std::unique_lock lock(mCollisionWorldMutex);
mCollisionWorld->addCollisionObject(collisionObject, collisionFilterGroup, collisionFilterMask);
}
void PhysicsTaskScheduler::removeCollisionObject(btCollisionObject* collisionObject)
{
mCollisionObjects.erase(collisionObject);
std::unique_lock lock(mCollisionWorldMutex);
mCollisionWorld->removeCollisionObject(collisionObject);
}
@ -506,6 +493,27 @@ namespace MWPhysics
}
}
void PhysicsTaskScheduler::updateActor(Actor& actor, ActorFrameData& actorData, bool simulationPerformed, float timeAccum, float dt) const
{
actor.setSimulationPosition(interpolateMovements(actor, actorData, timeAccum, dt));
actor.setLastStuckPosition(actorData.mLastStuckPosition);
actor.setStuckFrames(actorData.mStuckFrames);
if (simulationPerformed)
{
MWWorld::Ptr standingOn;
auto* ptrHolder = static_cast<MWPhysics::PtrHolder*>(getUserPointer(actorData.mStandingOn));
if (ptrHolder)
standingOn = ptrHolder->getPtr();
actor.setStandingOnPtr(standingOn);
// the "on ground" state of an actor might have been updated by a traceDown, don't overwrite the change
if (actor.getOnGround() == actorData.mWasOnGround)
actor.setOnGround(actorData.mIsOnGround);
actor.setOnSlope(actorData.mIsOnSlope);
actor.setWalkingOnWater(actorData.mWalkingOnWater);
actor.setInertialForce(actorData.mInertia);
}
}
bool PhysicsTaskScheduler::hasLineOfSight(const Actor* actor1, const Actor* actor2)
{
btVector3 pos1 = Misc::Convert::toBullet(actor1->getCollisionObjectPosition() + osg::Vec3f(0,0,actor1->getHalfExtents().z() * 0.9)); // eye level
@ -566,6 +574,14 @@ namespace MWPhysics
mDebugDrawer->step();
}
void* PhysicsTaskScheduler::getUserPointer(const btCollisionObject* object) const
{
auto it = mCollisionObjects.find(object);
if (it == mCollisionObjects.end())
return nullptr;
return (*it)->getUserPointer();
}
void PhysicsTaskScheduler::afterPreStep()
{
updateAabbs();

View File

@ -6,6 +6,7 @@
#include <optional>
#include <shared_mutex>
#include <thread>
#include <unordered_set>
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
@ -55,11 +56,13 @@ namespace MWPhysics
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();
void* getUserPointer(const btCollisionObject* object) const;
private:
void syncComputation();
void worker();
void updateActorsPositions();
void updateActor(Actor& actor, ActorFrameData& actorData, bool simulationPerformed, float timeAccum, float dt) const;
bool hasLineOfSight(const Actor* actor1, const Actor* actor2);
void refreshLOSCache();
void updateAabbs();
@ -73,6 +76,7 @@ namespace MWPhysics
std::unique_ptr<WorldFrameData> mWorldFrameData;
std::vector<std::weak_ptr<Actor>> mActors;
std::vector<ActorFrameData> mActorsFrameData;
std::unordered_set<const btCollisionObject*> mCollisionObjects;
float mDefaultPhysicsDt;
float mPhysicsDt;
float mTimeAccum;

View File

@ -811,13 +811,8 @@ namespace MWPhysics
// Slow fall reduces fall speed by a factor of (effect magnitude / 200)
const float slowFall = 1.f - std::max(0.f, std::min(1.f, effects.get(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f));
// Ue current value only if we don't advance the simulation. Otherwise we might get a stale value.
MWWorld::Ptr standingOn;
if (!willSimulate)
standingOn = physicActor->getStandingOnPtr();
framedata.first.emplace_back(physicActor);
framedata.second.emplace_back(*physicActor, standingOn, waterCollision, slowFall, waterlevel);
framedata.second.emplace_back(*physicActor, waterCollision, slowFall, waterlevel);
// if the simulation will run, a jump request will be fulfilled. Update mechanics accordingly.
if (willSimulate)
@ -989,10 +984,9 @@ namespace MWPhysics
mDebugDrawer->addCollision(position, normal);
}
ActorFrameData::ActorFrameData(Actor& actor, const MWWorld::Ptr standingOn,
bool waterCollision, float slowFall, float waterlevel)
ActorFrameData::ActorFrameData(Actor& actor, bool waterCollision, float slowFall, float waterlevel)
: mCollisionObject(actor.getCollisionObject())
, mStandingOn(standingOn)
, mStandingOn(nullptr)
, mWasOnGround(actor.getOnGround())
, mIsOnGround(actor.getOnGround())
, mIsOnSlope(actor.getOnSlope())

View File

@ -78,10 +78,10 @@ namespace MWPhysics
struct ActorFrameData
{
ActorFrameData(Actor& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, float slowFall, float waterlevel);
ActorFrameData(Actor& actor, bool moveToWaterSurface, float slowFall, float waterlevel);
void updatePosition(Actor& actor, btCollisionWorld* world);
btCollisionObject* mCollisionObject;
MWWorld::Ptr mStandingOn;
const btCollisionObject* mStandingOn;
bool mFlying;
bool mWasOnGround;
bool mIsOnGround;