mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-27 05:40:25 +00:00
Add a flag for jump when queueing movement, so inertia can be added accurately.
This commit is contained in:
parent
32d391f548
commit
c79446818e
8 changed files with 53 additions and 16 deletions
|
@ -295,9 +295,13 @@ namespace MWBase
|
||||||
/// relative to \a referenceObject (but the object may be placed somewhere else if the wanted location is
|
/// relative to \a referenceObject (but the object may be placed somewhere else if the wanted location is
|
||||||
/// obstructed).
|
/// obstructed).
|
||||||
|
|
||||||
virtual void queueMovement(const MWWorld::Ptr& ptr, const osg::Vec3f& velocity, float duration) = 0;
|
virtual void queueMovement(
|
||||||
|
const MWWorld::Ptr& ptr, const osg::Vec3f& velocity, float duration, bool jump = false)
|
||||||
|
= 0;
|
||||||
///< Queues movement for \a ptr (in local space), to be applied in the next call to
|
///< Queues movement for \a ptr (in local space), to be applied in the next call to
|
||||||
/// doPhysics.
|
/// doPhysics.
|
||||||
|
/// \param duration The duration this speed shall be held, starting at current simulation time
|
||||||
|
/// \param jump Whether the movement shall be run over time, or immediately added as inertia instead
|
||||||
|
|
||||||
virtual void updateAnimatedCollisionShape(const MWWorld::Ptr& ptr) = 0;
|
virtual void updateAnimatedCollisionShape(const MWWorld::Ptr& ptr) = 0;
|
||||||
|
|
||||||
|
@ -567,7 +571,8 @@ namespace MWBase
|
||||||
virtual DetourNavigator::Navigator* getNavigator() const = 0;
|
virtual DetourNavigator::Navigator* getNavigator() const = 0;
|
||||||
|
|
||||||
virtual void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
|
virtual void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
|
||||||
const DetourNavigator::AgentBounds& agentBounds, const osg::Vec3f& start, const osg::Vec3f& end) const = 0;
|
const DetourNavigator::AgentBounds& agentBounds, const osg::Vec3f& start, const osg::Vec3f& end) const
|
||||||
|
= 0;
|
||||||
|
|
||||||
virtual void removeActorPath(const MWWorld::ConstPtr& actor) const = 0;
|
virtual void removeActorPath(const MWWorld::ConstPtr& actor) const = 0;
|
||||||
|
|
||||||
|
@ -576,10 +581,12 @@ namespace MWBase
|
||||||
virtual DetourNavigator::AgentBounds getPathfindingAgentBounds(const MWWorld::ConstPtr& actor) const = 0;
|
virtual DetourNavigator::AgentBounds getPathfindingAgentBounds(const MWWorld::ConstPtr& actor) const = 0;
|
||||||
|
|
||||||
virtual bool hasCollisionWithDoor(
|
virtual bool hasCollisionWithDoor(
|
||||||
const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const = 0;
|
const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const
|
||||||
|
= 0;
|
||||||
|
|
||||||
virtual bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
virtual bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius,
|
||||||
std::span<const MWWorld::ConstPtr> ignore, std::vector<MWWorld::Ptr>* occupyingActors = nullptr) const = 0;
|
std::span<const MWWorld::ConstPtr> ignore, std::vector<MWWorld::Ptr>* occupyingActors = nullptr) const
|
||||||
|
= 0;
|
||||||
|
|
||||||
virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const = 0;
|
virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const = 0;
|
||||||
|
|
||||||
|
|
|
@ -2420,7 +2420,9 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isMovementAnimationControlled() && !isScriptedAnimPlaying())
|
if (!isMovementAnimationControlled() && !isScriptedAnimPlaying())
|
||||||
world->queueMovement(mPtr, vec, duration);
|
{
|
||||||
|
world->queueMovement(mPtr, vec, duration, mInJump && mJumpState == JumpState_None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
movement = vec;
|
movement = vec;
|
||||||
|
@ -2446,7 +2448,6 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool doMovementAccumulation = isMovementAnimationControlled();
|
|
||||||
osg::Vec3f movementFromAnimation
|
osg::Vec3f movementFromAnimation
|
||||||
= mAnimation->runAnimation(mSkipAnim && !isScriptedAnimPlaying() ? 0.f : duration);
|
= mAnimation->runAnimation(mSkipAnim && !isScriptedAnimPlaying() ? 0.f : duration);
|
||||||
|
|
||||||
|
@ -2494,7 +2495,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update movement
|
// Update movement
|
||||||
world->queueMovement(mPtr, movement, duration);
|
world->queueMovement(mPtr, movement, duration, mInJump && mJumpState == JumpState_None);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSkipAnim = false;
|
mSkipAnim = false;
|
||||||
|
|
|
@ -210,6 +210,13 @@ namespace
|
||||||
auto it = actor.movement().begin();
|
auto it = actor.movement().begin();
|
||||||
while (it != actor.movement().end())
|
while (it != actor.movement().end())
|
||||||
{
|
{
|
||||||
|
if (it->jump)
|
||||||
|
{
|
||||||
|
// Adjusting inertia is instant and should not be performed over time like other movement is.
|
||||||
|
it++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
float start = std::max(it->simulationTimeStart, startTime);
|
float start = std::max(it->simulationTimeStart, startTime);
|
||||||
float stop = std::min(it->simulationTimeStop, endTime);
|
float stop = std::min(it->simulationTimeStop, endTime);
|
||||||
movement += it->velocity * (stop - start);
|
movement += it->velocity * (stop - start);
|
||||||
|
@ -222,6 +229,23 @@ namespace
|
||||||
return movement;
|
return movement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<osg::Vec3f> takeInertia(MWPhysics::PtrHolder& actor, float startTime) const
|
||||||
|
{
|
||||||
|
std::optional<osg::Vec3f> inertia = std::nullopt;
|
||||||
|
auto it = actor.movement().begin();
|
||||||
|
while (it != actor.movement().end())
|
||||||
|
{
|
||||||
|
if (it->jump && it->simulationTimeStart >= startTime)
|
||||||
|
{
|
||||||
|
inertia = it->velocity;
|
||||||
|
it = actor.movement().erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
return inertia;
|
||||||
|
}
|
||||||
|
|
||||||
void operator()(auto& sim) const
|
void operator()(auto& sim) const
|
||||||
{
|
{
|
||||||
if (mSteps <= 0 || mDelta < 0.00001f)
|
if (mSteps <= 0 || mDelta < 0.00001f)
|
||||||
|
@ -237,8 +261,10 @@ namespace
|
||||||
// movement solver
|
// movement solver
|
||||||
osg::Vec3f velocity
|
osg::Vec3f velocity
|
||||||
= takeMovement(*ptrHolder, mSimulationTime, mSimulationTime + mDelta * mSteps) / (mSteps * mDelta);
|
= takeMovement(*ptrHolder, mSimulationTime, mSimulationTime + mDelta * mSteps) / (mSteps * mDelta);
|
||||||
|
// takeInertia() returns a velocity and should be taken over the velocity calculated above to initiate a jump
|
||||||
|
auto inertia = takeInertia(*ptrHolder, mSimulationTime);
|
||||||
|
|
||||||
frameDataRef.get().mMovement += velocity;
|
frameDataRef.get().mMovement += inertia.value_or(velocity);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -624,12 +624,12 @@ namespace MWPhysics
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::queueObjectMovement(const MWWorld::Ptr& ptr, const osg::Vec3f& velocity, float duration)
|
void PhysicsSystem::queueObjectMovement(const MWWorld::Ptr& ptr, const osg::Vec3f& velocity, float duration, bool jump)
|
||||||
{
|
{
|
||||||
float start = MWBase::Environment::get().getWorld()->getTimeManager()->getSimulationTime();
|
float start = MWBase::Environment::get().getWorld()->getTimeManager()->getSimulationTime();
|
||||||
ActorMap::iterator found = mActors.find(ptr.mRef);
|
ActorMap::iterator found = mActors.find(ptr.mRef);
|
||||||
if (found != mActors.end())
|
if (found != mActors.end())
|
||||||
found->second->queueMovement(velocity, start, start + duration);
|
found->second->queueMovement(velocity, start, start + duration, jump);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::clearQueuedMovement()
|
void PhysicsSystem::clearQueuedMovement()
|
||||||
|
|
|
@ -245,7 +245,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
|
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
|
||||||
/// be overwritten. Valid until the next call to stepSimulation
|
/// be overwritten. Valid until the next call to stepSimulation
|
||||||
void queueObjectMovement(const MWWorld::Ptr& ptr, const osg::Vec3f& velocity, float duration);
|
void queueObjectMovement(const MWWorld::Ptr& ptr, const osg::Vec3f& velocity, float duration, bool jump = false);
|
||||||
|
|
||||||
/// Clear the queued movements list without applying.
|
/// Clear the queued movements list without applying.
|
||||||
void clearQueuedMovement();
|
void clearQueuedMovement();
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace MWPhysics
|
||||||
osg::Vec3f velocity = osg::Vec3f();
|
osg::Vec3f velocity = osg::Vec3f();
|
||||||
float simulationTimeStart = 0.f; // The time at which this movement begun
|
float simulationTimeStart = 0.f; // The time at which this movement begun
|
||||||
float simulationTimeStop = 0.f; // The time at which this movement finished
|
float simulationTimeStop = 0.f; // The time at which this movement finished
|
||||||
|
bool jump = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PtrHolder
|
class PtrHolder
|
||||||
|
@ -41,9 +42,9 @@ namespace MWPhysics
|
||||||
btCollisionObject* getCollisionObject() const { return mCollisionObject.get(); }
|
btCollisionObject* getCollisionObject() const { return mCollisionObject.get(); }
|
||||||
|
|
||||||
void clearMovement() { mMovement = {}; }
|
void clearMovement() { mMovement = {}; }
|
||||||
void queueMovement(osg::Vec3f velocity, float simulationTimeStart, float simulationTimeStop)
|
void queueMovement(osg::Vec3f velocity, float simulationTimeStart, float simulationTimeStop, bool jump = false)
|
||||||
{
|
{
|
||||||
mMovement.push_back(Movement{ velocity, simulationTimeStart, simulationTimeStop });
|
mMovement.push_back(Movement{ velocity, simulationTimeStart, simulationTimeStop, jump });
|
||||||
}
|
}
|
||||||
|
|
||||||
std::deque<Movement>& movement() { return mMovement; }
|
std::deque<Movement>& movement() { return mMovement; }
|
||||||
|
|
|
@ -1448,9 +1448,9 @@ namespace MWWorld
|
||||||
return placed;
|
return placed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::queueMovement(const Ptr& ptr, const osg::Vec3f& velocity, float duration)
|
void World::queueMovement(const Ptr& ptr, const osg::Vec3f& velocity, float duration, bool jump)
|
||||||
{
|
{
|
||||||
mPhysics->queueObjectMovement(ptr, velocity, duration);
|
mPhysics->queueObjectMovement(ptr, velocity, duration, jump);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::updateAnimatedCollisionShape(const Ptr& ptr)
|
void World::updateAnimatedCollisionShape(const Ptr& ptr)
|
||||||
|
|
|
@ -383,9 +383,11 @@ namespace MWWorld
|
||||||
|
|
||||||
float getMaxActivationDistance() const override;
|
float getMaxActivationDistance() const override;
|
||||||
|
|
||||||
void queueMovement(const Ptr& ptr, const osg::Vec3f& velocity, float duration) override;
|
void queueMovement(const Ptr& ptr, const osg::Vec3f& velocity, float duration, bool jump = false) override;
|
||||||
///< Queues movement for \a ptr (in local space), to be applied in the next call to
|
///< Queues movement for \a ptr (in local space), to be applied in the next call to
|
||||||
/// doPhysics.
|
/// doPhysics.
|
||||||
|
/// \param duration The duration this speed shall be held, starting at current simulation time
|
||||||
|
/// \param jump Whether the movement shall be run over time, or immediately added as inertia instead
|
||||||
|
|
||||||
void updateAnimatedCollisionShape(const Ptr& ptr) override;
|
void updateAnimatedCollisionShape(const Ptr& ptr) override;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue