From 32d391f5485cb63853bb5139b2ab07e2c6a05ce6 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Sat, 9 Dec 2023 14:29:26 +0100 Subject: [PATCH] Revert accumulating movement in the reset accum root callback. --- apps/openmw/mwmechanics/character.cpp | 4 +- apps/openmw/mwphysics/mtphysics.cpp | 8 -- apps/openmw/mwphysics/mtphysics.hpp | 3 - apps/openmw/mwrender/animation.cpp | 89 ++++------------------ apps/openmw/mwrender/animation.hpp | 6 +- apps/openmw/mwrender/creatureanimation.cpp | 4 +- apps/openmw/mwrender/creatureanimation.hpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 4 +- apps/openmw/mwrender/npcanimation.hpp | 2 +- apps/openmw/mwworld/datetimemanager.hpp | 5 -- 10 files changed, 23 insertions(+), 104 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 2ef3479cd9..3eb392daf1 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -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; diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index 09eb309593..deef837992 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -608,7 +608,6 @@ namespace MWPhysics if (mAdvanceSimulation) { - mNextJobSimTime = simulationTimeStart + (numSteps * newDelta); mWorldFrameData = std::make_unique(); 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 diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp index 83d3010359..986f2be973 100644 --- a/apps/openmw/mwphysics/mtphysics.hpp +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -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 mLOSCache; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index e12e8212e6..e780a30fbb 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -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 { - 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 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; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 8e159700ea..24366889c4 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -266,7 +265,6 @@ namespace MWRender Resource::ResourceSystem* mResourceSystem; osg::Vec3f mAccumulate; - std::optional 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); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 65f48f5ade..7767520715 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -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()); diff --git a/apps/openmw/mwrender/creatureanimation.hpp b/apps/openmw/mwrender/creatureanimation.hpp index 9ff3d55375..05235e5191 100644 --- a/apps/openmw/mwrender/creatureanimation.hpp +++ b/apps/openmw/mwrender/creatureanimation.hpp @@ -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. diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 951d16aefe..469978e6eb 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -693,9 +693,9 @@ namespace MWRender return std::make_unique(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); diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 0c2d67db86..a03ee28f3a 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -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. diff --git a/apps/openmw/mwworld/datetimemanager.hpp b/apps/openmw/mwworld/datetimemanager.hpp index 20d968f4ea..af62d9ba3f 100644 --- a/apps/openmw/mwworld/datetimemanager.hpp +++ b/apps/openmw/mwworld/datetimemanager.hpp @@ -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> mPausedTags; };