mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-28 09:06:40 +00:00
Revert accumulating movement in the reset accum root callback.
This commit is contained in:
parent
af9312d869
commit
32d391f548
10 changed files with 23 additions and 104 deletions
|
@ -2448,9 +2448,9 @@ namespace MWMechanics
|
|||
|
||||
bool doMovementAccumulation = isMovementAnimationControlled();
|
||||
osg::Vec3f movementFromAnimation
|
||||
= mAnimation->runAnimation(mSkipAnim && !isScriptedAnimPlaying() ? 0.f : duration, doMovementAccumulation);
|
||||
= mAnimation->runAnimation(mSkipAnim && !isScriptedAnimPlaying() ? 0.f : duration);
|
||||
|
||||
if (mPtr.getClass().isActor() && doMovementAccumulation && !isScriptedAnimPlaying())
|
||||
if (mPtr.getClass().isActor() && isMovementAnimationControlled() && !isScriptedAnimPlaying())
|
||||
{
|
||||
if (duration > 0.0f)
|
||||
movementFromAnimation /= duration;
|
||||
|
|
|
@ -608,7 +608,6 @@ namespace MWPhysics
|
|||
|
||||
if (mAdvanceSimulation)
|
||||
{
|
||||
mNextJobSimTime = simulationTimeStart + (numSteps * newDelta);
|
||||
mWorldFrameData = std::make_unique<WorldFrameData>();
|
||||
mBudgetCursor += 1;
|
||||
}
|
||||
|
@ -812,7 +811,6 @@ namespace MWPhysics
|
|||
mLockingPolicy };
|
||||
for (Simulation& sim : *mSimulations)
|
||||
std::visit(vis, sim);
|
||||
mCurrentJobSimTime += mPhysicsDt;
|
||||
}
|
||||
|
||||
bool PhysicsTaskScheduler::hasLineOfSight(const Actor* actor1, const Actor* actor2)
|
||||
|
@ -922,9 +920,6 @@ namespace MWPhysics
|
|||
mLOSCache.end());
|
||||
}
|
||||
|
||||
// On paper, mCurrentJobSimTime should have added up to mNextJobSimTime already
|
||||
// But to avoid accumulating floating point errors, assign this anyway.
|
||||
mCurrentJobSimTime = mNextJobSimTime;
|
||||
mTimeEnd = mTimer->tick();
|
||||
if (mWorkersSync != nullptr)
|
||||
mWorkersSync->workIsDone();
|
||||
|
@ -939,9 +934,6 @@ namespace MWPhysics
|
|||
std::visit(vis, sim);
|
||||
mSimulations->clear();
|
||||
mSimulations = nullptr;
|
||||
const float interpolationFactor = std::clamp(mTimeAccum / mPhysicsDt, 0.0f, 1.0f);
|
||||
MWBase::Environment::get().getWorld()->getTimeManager()->setPhysicsSimulationTime(
|
||||
mCurrentJobSimTime - mPhysicsDt * (1.f - interpolationFactor));
|
||||
}
|
||||
|
||||
// Attempt to acquire unique lock on mSimulationMutex while not all worker
|
||||
|
|
|
@ -96,9 +96,6 @@ namespace MWPhysics
|
|||
float mDefaultPhysicsDt;
|
||||
float mPhysicsDt;
|
||||
float mTimeAccum;
|
||||
float mNextJobSimTime = 0.f;
|
||||
float mCurrentJobSimTime = 0.f;
|
||||
float mPreviousJobSimTime = 0.f;
|
||||
btCollisionWorld* mCollisionWorld;
|
||||
MWRender::DebugDrawer* mDebugDrawer;
|
||||
std::vector<LOSRequest> mLOSCache;
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/datetimemanager.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "../mwmechanics/character.hpp" // FIXME: for MWMechanics::Priority
|
||||
|
@ -490,23 +489,14 @@ namespace MWRender
|
|||
|
||||
class ResetAccumRootCallback : public SceneUtil::NodeCallback<ResetAccumRootCallback, osg::MatrixTransform*>
|
||||
{
|
||||
struct AccumulatedMovement
|
||||
{
|
||||
osg::Vec3f mMovement = osg::Vec3f();
|
||||
float mSimStartTime = 0.f;
|
||||
float mSimStopTime = 0.f;
|
||||
};
|
||||
|
||||
public:
|
||||
void operator()(osg::MatrixTransform* transform, osg::NodeVisitor* nv)
|
||||
{
|
||||
osg::Matrix mat = transform->getMatrix();
|
||||
osg::Vec3f position = mat.getTrans();
|
||||
position = osg::componentMultiply(mResetAxes, position);
|
||||
// Add back the offset that the movement solver has not consumed yet
|
||||
position += computeRemainder();
|
||||
mat.setTrans(position);
|
||||
transform->setMatrix(mat);
|
||||
osg::Matrix mat = transform->getMatrix();
|
||||
osg::Vec3f position = mat.getTrans();
|
||||
position = osg::componentMultiply(mResetAxes, position);
|
||||
mat.setTrans(position);
|
||||
transform->setMatrix(mat);
|
||||
|
||||
traverse(transform, nv);
|
||||
}
|
||||
|
@ -519,35 +509,7 @@ namespace MWRender
|
|||
mResetAxes.z() = accumulate.z() != 0.f ? 0.f : 1.f;
|
||||
}
|
||||
|
||||
void accumulate(const osg::Vec3f& movement, float dt)
|
||||
{
|
||||
if (dt < 0.00001f)
|
||||
return;
|
||||
|
||||
float simTime = MWBase::Environment::get().getWorld()->getTimeManager()->getSimulationTime();
|
||||
mMovement.emplace_back(AccumulatedMovement{ movement, simTime, simTime + dt });
|
||||
}
|
||||
|
||||
const osg::Vec3f computeRemainder()
|
||||
{
|
||||
float physSimTime = MWBase::Environment::get().getWorld()->getTimeManager()->getPhysicsSimulationTime();
|
||||
// Start by erasing all movement that has been fully consumed by the physics code
|
||||
std::erase_if(mMovement,
|
||||
[physSimTime](const AccumulatedMovement& movement) { return movement.mSimStopTime <= physSimTime; });
|
||||
|
||||
// Accumulate all the movement that hasn't been consumed.
|
||||
osg::Vec3f movement;
|
||||
for (const auto& m : mMovement)
|
||||
{
|
||||
float startTime = std::max(physSimTime, m.mSimStartTime);
|
||||
float fraction = (m.mSimStopTime - startTime) / (m.mSimStopTime - m.mSimStartTime);
|
||||
movement += m.mMovement * fraction;
|
||||
}
|
||||
return movement;
|
||||
}
|
||||
|
||||
private:
|
||||
std::deque<AccumulatedMovement> mMovement;
|
||||
osg::Vec3f mResetAxes;
|
||||
};
|
||||
|
||||
|
@ -1167,37 +1129,15 @@ namespace MWRender
|
|||
return velocity;
|
||||
}
|
||||
|
||||
void Animation::updatePosition(float oldtime, float newtime, osg::Vec3f& position, bool hasMovement)
|
||||
void Animation::updatePosition(float oldtime, float newtime, osg::Vec3f& position)
|
||||
{
|
||||
// Get the difference from the last update, and move the position
|
||||
osg::Vec3f offset = osg::componentMultiply(mAccumCtrl->getTranslation(newtime), mAccumulate);
|
||||
if (!hasMovement)
|
||||
{
|
||||
// When animations have no velocity, the character should have zero net movement through a complete loop or
|
||||
// animation sequence. Although any subsequence of the animation may move. This works because each sequence
|
||||
// starts and stops with Bip01 at the same position, totaling 0 movement. This allows us to accurately move
|
||||
// the character by just moving it from the position Bip01 was last frame to where it is this frame, without
|
||||
// needing to accumulate anything in-between.
|
||||
if (mPreviousAccumulatePosition)
|
||||
{
|
||||
position += offset - mPreviousAccumulatePosition.value();
|
||||
}
|
||||
mPreviousAccumulatePosition = offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
// When animations have velocity, net movement is expected. The above block would negate that movement every
|
||||
// time the animation resets. Therefore we have to accumulate from oldtime to newtime instead, which works
|
||||
// because oldtime < newtime is a guarantee even when the animation has looped.
|
||||
position += offset - osg::componentMultiply(mAccumCtrl->getTranslation(oldtime), mAccumulate);
|
||||
}
|
||||
osg::Vec3f off = osg::componentMultiply(mAccumCtrl->getTranslation(newtime), mAccumulate);
|
||||
position += off - osg::componentMultiply(mAccumCtrl->getTranslation(oldtime), mAccumulate);
|
||||
}
|
||||
|
||||
osg::Vec3f Animation::runAnimation(float duration, bool accumulateMovement)
|
||||
osg::Vec3f Animation::runAnimation(float duration)
|
||||
{
|
||||
if (!accumulateMovement)
|
||||
mPreviousAccumulatePosition = std::nullopt;
|
||||
|
||||
osg::Vec3f movement(0.f, 0.f, 0.f);
|
||||
AnimStateMap::iterator stateiter = mStates.begin();
|
||||
while (stateiter != mStates.end())
|
||||
|
@ -1211,7 +1151,6 @@ namespace MWRender
|
|||
|
||||
const SceneUtil::TextKeyMap& textkeys = state.mSource->getTextKeys();
|
||||
auto textkey = textkeys.upperBound(state.getTime());
|
||||
bool hasMovement = getVelocity(stateiter->first) > 0.001f;
|
||||
|
||||
float timepassed = duration * state.mSpeedMult;
|
||||
while (state.mPlaying)
|
||||
|
@ -1221,14 +1160,14 @@ namespace MWRender
|
|||
float targetTime = state.getTime() + timepassed;
|
||||
if (textkey == textkeys.end() || textkey->first > targetTime)
|
||||
{
|
||||
if (accumulateMovement && mAccumCtrl && state.mTime == mAnimationTimePtr[0]->getTimePtr())
|
||||
updatePosition(state.getTime(), targetTime, movement, hasMovement);
|
||||
if (mAccumCtrl && state.mTime == mAnimationTimePtr[0]->getTimePtr())
|
||||
updatePosition(state.getTime(), targetTime, movement);
|
||||
state.setTime(std::min(targetTime, state.mStopTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (accumulateMovement && mAccumCtrl && state.mTime == mAnimationTimePtr[0]->getTimePtr())
|
||||
updatePosition(state.getTime(), textkey->first, movement, hasMovement);
|
||||
if (mAccumCtrl && state.mTime == mAnimationTimePtr[0]->getTimePtr())
|
||||
updatePosition(state.getTime(), textkey->first, movement);
|
||||
state.setTime(textkey->first);
|
||||
}
|
||||
|
||||
|
@ -1311,8 +1250,6 @@ namespace MWRender
|
|||
}
|
||||
|
||||
|
||||
if (accumulateMovement && mResetAccumRootCallback)
|
||||
mResetAccumRootCallback->accumulate(movement, duration);
|
||||
return movement;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <components/sceneutil/textkeymap.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
@ -266,7 +265,6 @@ namespace MWRender
|
|||
Resource::ResourceSystem* mResourceSystem;
|
||||
|
||||
osg::Vec3f mAccumulate;
|
||||
std::optional<osg::Vec3f> mPreviousAccumulatePosition;
|
||||
|
||||
TextKeyListener* mTextKeyListener;
|
||||
|
||||
|
@ -306,7 +304,7 @@ namespace MWRender
|
|||
|
||||
/* Updates the position of the accum root node for the given time, and
|
||||
* returns the wanted movement vector from the previous time. */
|
||||
void updatePosition(float oldtime, float newtime, osg::Vec3f& position, bool hasMovement);
|
||||
void updatePosition(float oldtime, float newtime, osg::Vec3f& position);
|
||||
|
||||
/* Resets the animation to the time of the specified start marker, without
|
||||
* moving anything, and set the end time to the specified stop marker. If
|
||||
|
@ -466,7 +464,7 @@ namespace MWRender
|
|||
/** Retrieves the velocity (in units per second) that the animation will move. */
|
||||
float getVelocity(std::string_view groupname) const;
|
||||
|
||||
virtual osg::Vec3f runAnimation(float duration, bool accumulateMovement = false);
|
||||
virtual osg::Vec3f runAnimation(float duration);
|
||||
|
||||
void setLoopingEnabled(std::string_view groupname, bool enabled);
|
||||
|
||||
|
|
|
@ -258,9 +258,9 @@ namespace MWRender
|
|||
WeaponAnimation::addControllers(mNodeMap, mActiveControllers, mObjectRoot.get());
|
||||
}
|
||||
|
||||
osg::Vec3f CreatureWeaponAnimation::runAnimation(float duration, bool accumulateMovement)
|
||||
osg::Vec3f CreatureWeaponAnimation::runAnimation(float duration)
|
||||
{
|
||||
osg::Vec3f ret = Animation::runAnimation(duration, accumulateMovement);
|
||||
osg::Vec3f ret = Animation::runAnimation(duration);
|
||||
|
||||
WeaponAnimation::configureControllers(mPtr.getRefData().getPosition().rot[0] + getBodyPitchRadians());
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace MWRender
|
|||
|
||||
void addControllers() override;
|
||||
|
||||
osg::Vec3f runAnimation(float duration, bool accumulateMovement = false) override;
|
||||
osg::Vec3f runAnimation(float duration) override;
|
||||
|
||||
/// A relative factor (0-1) that decides if and how much the skeleton should be pitched
|
||||
/// to indicate the facing orientation of the character.
|
||||
|
|
|
@ -693,9 +693,9 @@ namespace MWRender
|
|||
return std::make_unique<PartHolder>(attached);
|
||||
}
|
||||
|
||||
osg::Vec3f NpcAnimation::runAnimation(float timepassed, bool accumulateMovement)
|
||||
osg::Vec3f NpcAnimation::runAnimation(float timepassed)
|
||||
{
|
||||
osg::Vec3f ret = Animation::runAnimation(timepassed, accumulateMovement);
|
||||
osg::Vec3f ret = Animation::runAnimation(timepassed);
|
||||
|
||||
mHeadAnimationTime->update(timepassed);
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ namespace MWRender
|
|||
|
||||
void setWeaponGroup(const std::string& group, bool relativeDuration) override;
|
||||
|
||||
osg::Vec3f runAnimation(float timepassed, bool accumulateMovement = false) override;
|
||||
osg::Vec3f runAnimation(float timepassed) override;
|
||||
|
||||
/// A relative factor (0-1) that decides if and how much the skeleton should be pitched
|
||||
/// to indicate the facing orientation of the character.
|
||||
|
|
|
@ -29,10 +29,6 @@ namespace MWWorld
|
|||
float getGameTimeScale() const { return mGameTimeScale; }
|
||||
void setGameTimeScale(float scale); // game time to simulation time ratio
|
||||
|
||||
// Physics simulation time
|
||||
double getPhysicsSimulationTime() const { return mPhysicsSimulationTime; }
|
||||
void setPhysicsSimulationTime(double t) { mPhysicsSimulationTime = t; }
|
||||
|
||||
// Rendering simulation time (summary simulation time of rendering frames since application start).
|
||||
double getRenderingSimulationTime() const { return mRenderingSimulationTime; }
|
||||
void setRenderingSimulationTime(double t) { mRenderingSimulationTime = t; }
|
||||
|
@ -74,7 +70,6 @@ namespace MWWorld
|
|||
float mSimulationTimeScale = 1.0;
|
||||
double mRenderingSimulationTime = 0.0;
|
||||
double mSimulationTime = 0.0;
|
||||
double mPhysicsSimulationTime = 0.0;
|
||||
bool mPaused = false;
|
||||
std::set<std::string, std::less<>> mPausedTags;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue