Embed actor velocity inside its class. It makes the code simpler.

This commit is contained in:
fredzio 2021-05-01 20:28:17 +02:00
parent c55db790f3
commit 5b63019719
5 changed files with 29 additions and 36 deletions

View File

@ -2405,9 +2405,6 @@ void CharacterController::update(float duration)
if (!mMovementAnimationControlled) if (!mMovementAnimationControlled)
world->queueMovement(mPtr, vec); world->queueMovement(mPtr, vec);
} }
else
// We must always queue movement, even if there is none, to apply gravity.
world->queueMovement(mPtr, osg::Vec3f(0.f, 0.f, 0.f));
movement = vec; movement = vec;
movementSettings.mPosition[0] = movementSettings.mPosition[1] = 0; movementSettings.mPosition[0] = movementSettings.mPosition[1] = 0;
@ -2429,8 +2426,6 @@ void CharacterController::update(float duration)
if (cls.isPersistent(mPtr) || cls.getCreatureStats(mPtr).isDeathAnimationFinished()) if (cls.isPersistent(mPtr) || cls.getCreatureStats(mPtr).isDeathAnimationFinished())
playDeath(1.f, mDeathState); playDeath(1.f, mDeathState);
} }
// We must always queue movement, even if there is none, to apply gravity.
world->queueMovement(mPtr, osg::Vec3f(0.f, 0.f, 0.f));
} }
bool isPersist = isPersistentAnimPlaying(); bool isPersist = isPersistentAnimPlaying();

View File

@ -22,7 +22,7 @@ namespace MWPhysics
Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler) Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler)
: mStandingOnPtr(nullptr), mCanWaterWalk(false), mWalkingOnWater(false) : mStandingOnPtr(nullptr), mCanWaterWalk(false), mWalkingOnWater(false)
, mCollisionObject(nullptr), mMeshTranslation(shape->mCollisionBox.center), mHalfExtents(shape->mCollisionBox.extents) , mCollisionObject(nullptr), mMeshTranslation(shape->mCollisionBox.center), mHalfExtents(shape->mCollisionBox.extents)
, mStuckFrames(0), mLastStuckPosition{0, 0, 0} , mVelocity(0,0,0), mStuckFrames(0), mLastStuckPosition{0, 0, 0}
, mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false) , mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false)
, mInternalCollisionMode(true) , mInternalCollisionMode(true)
, mExternalCollisionMode(true) , mExternalCollisionMode(true)
@ -303,4 +303,14 @@ bool Actor::skipCollisions()
return std::exchange(mSkipCollisions, false); return std::exchange(mSkipCollisions, false);
} }
void Actor::setVelocity(osg::Vec3f velocity)
{
mVelocity = velocity;
}
osg::Vec3f Actor::velocity()
{
return std::exchange(mVelocity, osg::Vec3f());
}
} }

View File

@ -178,6 +178,9 @@ namespace MWPhysics
bool skipCollisions(); bool skipCollisions();
void setVelocity(osg::Vec3f velocity);
osg::Vec3f velocity();
private: private:
MWWorld::Ptr mStandingOnPtr; MWWorld::Ptr mStandingOnPtr;
/// Removes then re-adds the collision object to the dynamics world /// Removes then re-adds the collision object to the dynamics world
@ -206,6 +209,7 @@ namespace MWPhysics
osg::Vec3f mPosition; osg::Vec3f mPosition;
osg::Vec3f mPreviousPosition; osg::Vec3f mPreviousPosition;
osg::Vec3f mPositionOffset; osg::Vec3f mPositionOffset;
osg::Vec3f mVelocity;
bool mWorldPositionChanged; bool mWorldPositionChanged;
bool mSkipCollisions; bool mSkipCollisions;
btTransform mLocalTransform; btTransform mLocalTransform;

View File

@ -725,21 +725,15 @@ namespace MWPhysics
void PhysicsSystem::queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity) void PhysicsSystem::queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity)
{ {
for(auto& movementItem : mMovementQueue) ActorMap::iterator found = mActors.find(ptr);
{ if (found != mActors.end())
if (movementItem.first == ptr) found->second->setVelocity(velocity);
{
movementItem.second = velocity;
return;
}
}
mMovementQueue.emplace_back(ptr, velocity);
} }
void PhysicsSystem::clearQueuedMovement() void PhysicsSystem::clearQueuedMovement()
{ {
mMovementQueue.clear(); for (const auto& [_, actor] : mActors)
actor->setVelocity(osg::Vec3f());
} }
const std::vector<MWWorld::Ptr>& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) const std::vector<MWWorld::Ptr>& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
@ -756,27 +750,21 @@ namespace MWPhysics
std::vector<ActorFrameData> PhysicsSystem::prepareFrameData(bool willSimulate) std::vector<ActorFrameData> PhysicsSystem::prepareFrameData(bool willSimulate)
{ {
std::vector<ActorFrameData> actorsFrameData; std::vector<ActorFrameData> actorsFrameData;
actorsFrameData.reserve(mMovementQueue.size()); actorsFrameData.reserve(mActors.size());
const MWBase::World *world = MWBase::Environment::get().getWorld(); const MWBase::World *world = MWBase::Environment::get().getWorld();
for (const auto& [character, movement] : mMovementQueue) for (const auto& [ptr, physicActor] : mActors)
{ {
const auto foundActor = mActors.find(character);
if (foundActor == mActors.end()) // actor was already removed from the scene
continue;
auto physicActor = foundActor->second;
float waterlevel = -std::numeric_limits<float>::max(); float waterlevel = -std::numeric_limits<float>::max();
const MWWorld::CellStore *cell = character.getCell(); const MWWorld::CellStore *cell = ptr.getCell();
if(cell->getCell()->hasWater()) if(cell->getCell()->hasWater())
waterlevel = cell->getWaterLevel(); waterlevel = cell->getWaterLevel();
const MWMechanics::MagicEffects& effects = character.getClass().getCreatureStats(character).getMagicEffects(); const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(physicActor->getPtr()).getMagicEffects();
bool waterCollision = false; bool waterCollision = false;
if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude()) if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude())
{ {
if (physicActor->getCollisionMode() || !world->isUnderwater(character.getCell(), osg::Vec3f(character.getRefData().getPosition().asVec3()))) if (physicActor->getCollisionMode() || !world->isUnderwater(ptr.getCell(), osg::Vec3f(ptr.getRefData().getPosition().asVec3())))
waterCollision = true; waterCollision = true;
} }
@ -790,9 +778,8 @@ namespace MWPhysics
if (!willSimulate) if (!willSimulate)
standingOn = physicActor->getStandingOnPtr(); standingOn = physicActor->getStandingOnPtr();
actorsFrameData.emplace_back(std::move(physicActor), standingOn, waterCollision, movement, slowFall, waterlevel); actorsFrameData.emplace_back(physicActor, standingOn, waterCollision, slowFall, waterlevel);
} }
mMovementQueue.clear();
return actorsFrameData; return actorsFrameData;
} }
@ -933,10 +920,10 @@ namespace MWPhysics
} }
ActorFrameData::ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn, ActorFrameData::ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn,
bool waterCollision, osg::Vec3f movement, float slowFall, float waterlevel) bool waterCollision, float slowFall, float waterlevel)
: mActor(actor), mActorRaw(actor.get()), mStandingOn(standingOn), : mActor(actor), mActorRaw(actor.get()), mStandingOn(standingOn),
mDidJump(false), mNeedLand(false), mWaterCollision(waterCollision), mSkipCollisionDetection(actor->skipCollisions()), mDidJump(false), mNeedLand(false), mWaterCollision(waterCollision), mSkipCollisionDetection(actor->skipCollisions()),
mWaterlevel(waterlevel), mSlowFall(slowFall), mOldHeight(0), mFallHeight(0), mMovement(movement), mPosition(), mRefpos() mWaterlevel(waterlevel), mSlowFall(slowFall), mOldHeight(0), mFallHeight(0), mMovement(actor->velocity()), mPosition(), mRefpos()
{ {
const MWBase::World *world = MWBase::Environment::get().getWorld(); const MWBase::World *world = MWBase::Environment::get().getWorld();
const auto ptr = actor->getPtr(); const auto ptr = actor->getPtr();

View File

@ -78,7 +78,7 @@ namespace MWPhysics
struct ActorFrameData struct ActorFrameData
{ {
ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel); ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, float slowFall, float waterlevel);
void updatePosition(btCollisionWorld* world); void updatePosition(btCollisionWorld* world);
std::weak_ptr<Actor> mActor; std::weak_ptr<Actor> mActor;
Actor* mActorRaw; Actor* mActorRaw;
@ -281,9 +281,6 @@ namespace MWPhysics
bool mDebugDrawEnabled; bool mDebugDrawEnabled;
using PtrVelocityList = std::vector<std::pair<MWWorld::Ptr, osg::Vec3f>>;
PtrVelocityList mMovementQueue;
float mTimeAccum; float mTimeAccum;
unsigned int mProjectileId; unsigned int mProjectileId;