From 7bae6691b63878e76777ec497a1fe14bb00eb48c Mon Sep 17 00:00:00 2001 From: fredzio Date: Fri, 18 Dec 2020 08:18:07 +0100 Subject: [PATCH] Introduce World::moveObjectBy() function to translate an object relatively to its current position. Use it in relevant MWScripts opcode (move and moveworld). Remove the fragile detection of scripted translation from PhysicsTaskScheduler. No user visible change, just a more robust mechanism. --- apps/openmw/mwbase/world.hpp | 3 +++ apps/openmw/mwphysics/actor.cpp | 17 ++++++++++++----- apps/openmw/mwphysics/actor.hpp | 5 ++++- apps/openmw/mwphysics/mtphysics.cpp | 13 +------------ .../mwscript/transformationextensions.cpp | 19 ++++++------------- apps/openmw/mwworld/worldimp.cpp | 12 ++++++++++++ apps/openmw/mwworld/worldimp.hpp | 3 +++ 7 files changed, 41 insertions(+), 31 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index d4f1d2f8a..619bbbdf5 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -286,6 +286,9 @@ namespace MWBase virtual MWWorld::Ptr moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore* newCell, float x, float y, float z, bool movePhysics=true) = 0; ///< @return an updated Ptr + virtual MWWorld::Ptr moveObjectBy(const MWWorld::Ptr &ptr, osg::Vec3f vec) = 0; + ///< @return an updated Ptr + virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0; virtual void rotateObject(const MWWorld::Ptr& ptr, float x, float y, float z, diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index b1f219e33..e7fe93b35 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -120,6 +120,8 @@ int Actor::getCollisionMask() const void Actor::updatePositionUnsafe() { + if (!mWorldPositionChanged && mWorldPosition != mPtr.getRefData().getPosition().asVec3()) + mWorldPositionChanged = true; mWorldPosition = mPtr.getRefData().getPosition().asVec3(); } @@ -153,6 +155,7 @@ void Actor::updateCollisionObjectPositionUnsafe() mLocalTransform.setOrigin(Misc::Convert::toBullet(newPosition)); mLocalTransform.setRotation(Misc::Convert::toBullet(mRotation)); mCollisionObject->setWorldTransform(mLocalTransform); + mWorldPositionChanged = false; } void Actor::updateCollisionObjectPosition() @@ -167,18 +170,20 @@ osg::Vec3f Actor::getCollisionObjectPosition() const return Misc::Convert::toOsg(mLocalTransform.getOrigin()); } -void Actor::setPosition(const osg::Vec3f& position) +bool Actor::setPosition(const osg::Vec3f& position) { std::scoped_lock lock(mPositionMutex); - mPreviousPosition = mPosition; - mPosition = position; + bool hasChanged = mPosition != position || mPositionOffset.length() != 0 || mWorldPositionChanged; + mPreviousPosition = mPosition + mPositionOffset; + mPosition = position + mPositionOffset; + mPositionOffset = osg::Vec3f(); + return hasChanged; } void Actor::adjustPosition(const osg::Vec3f& offset) { std::scoped_lock lock(mPositionMutex); - mPosition += offset; - mPreviousPosition += offset; + mPositionOffset += offset; } void Actor::resetPosition() @@ -189,6 +194,8 @@ void Actor::resetPosition() mPosition = mWorldPosition; mSimulationPosition = mWorldPosition; updateCollisionObjectPositionUnsafe(); + mStandingOnPtr = nullptr; + mWorldPositionChanged = false; } osg::Vec3f Actor::getPosition() const diff --git a/apps/openmw/mwphysics/actor.hpp b/apps/openmw/mwphysics/actor.hpp index 07a9bebd2..7c8ea0b73 100644 --- a/apps/openmw/mwphysics/actor.hpp +++ b/apps/openmw/mwphysics/actor.hpp @@ -90,8 +90,9 @@ namespace MWPhysics /** * Store the current position into mPreviousPosition, then move to this position. + * Returns true if the new position is different. */ - void setPosition(const osg::Vec3f& position); + bool setPosition(const osg::Vec3f& position); void resetPosition(); void adjustPosition(const osg::Vec3f& offset); @@ -177,6 +178,8 @@ namespace MWPhysics osg::Vec3f mSimulationPosition; osg::Vec3f mPosition; osg::Vec3f mPreviousPosition; + osg::Vec3f mPositionOffset; + bool mWorldPositionChanged; btTransform mLocalTransform; mutable std::mutex mPositionMutex; diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index a78a30788..95c61edc7 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -100,15 +100,6 @@ namespace osg::Vec3f interpolateMovements(MWPhysics::ActorFrameData& actorData, float timeAccum, float physicsDt) { const float interpolationFactor = timeAccum / physicsDt; - - // account for force change of actor's position in the main thread - const auto correction = actorData.mActorRaw->getWorldPosition() - actorData.mOrigin; - if (correction.length() != 0) - { - actorData.mActorRaw->adjustPosition(correction); - actorData.mPosition = actorData.mActorRaw->getPosition(); - } - return actorData.mPosition * interpolationFactor + actorData.mActorRaw->getPreviousPosition() * (1.f - interpolationFactor); } @@ -511,9 +502,7 @@ namespace MWPhysics { if(const auto actor = actorData.mActor.lock()) { - bool positionChanged = actorData.mPosition != actorData.mActorRaw->getPosition(); - actorData.mActorRaw->setPosition(actorData.mPosition); - if (positionChanged) + if (actor->setPosition(actorData.mPosition)) { actor->updateCollisionObjectPosition(); mCollisionWorld->updateSingleAabb(actor->getCollisionObject()); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index a908940ed..103c6629d 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -32,11 +32,7 @@ namespace MWScript std::vector actors; MWBase::Environment::get().getWorld()->getActorsStandingOn (ptr, actors); for (auto& actor : actors) - { - osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3()); - actorPos += diff; - MWBase::Environment::get().getWorld()->moveObject(actor, actorPos.x(), actorPos.y(), actorPos.z()); - } + MWBase::Environment::get().getWorld()->moveObjectBy(actor, diff); } template @@ -727,14 +723,12 @@ namespace MWScript return; osg::Vec3f diff = ptr.getRefData().getBaseNode()->getAttitude() * posChange; - osg::Vec3f worldPos(ptr.getRefData().getPosition().asVec3()); - worldPos += diff; // We should move actors, standing on moving object, too. // This approach can be used to create elevators. moveStandingActors(ptr, diff); dynamic_cast(runtime.getContext()).updatePtr(ptr, - MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x(), worldPos.y(), worldPos.z())); + MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff)); } }; @@ -755,15 +749,14 @@ namespace MWScript Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration()); runtime.pop(); - const float *objPos = ptr.getRefData().getPosition().pos; osg::Vec3f diff; if (axis == "x") - diff.x() += movement; + diff.x() = movement; else if (axis == "y") - diff.y() += movement; + diff.y() = movement; else if (axis == "z") - diff.z() += movement; + diff.z() = movement; else return; @@ -771,7 +764,7 @@ namespace MWScript // This approach can be used to create elevators. moveStandingActors(ptr, diff); dynamic_cast(runtime.getContext()).updatePtr(ptr, - MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0]+diff.x(), objPos[1]+diff.y(), objPos[2]+diff.z())); + MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff)); } }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3756ea04b..3086fed83 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1251,6 +1251,18 @@ namespace MWWorld return moveObjectImp(ptr, x, y, z, true, moveToActive); } + MWWorld::Ptr World::moveObjectBy(const Ptr& ptr, osg::Vec3f vec) + { + auto* actor = mPhysics->getActor(ptr); + if (actor) + { + actor->adjustPosition(vec); + return ptr; + } + osg::Vec3f newpos = ptr.getRefData().getPosition().asVec3() + vec; + return moveObject(ptr, newpos.x(), newpos.y(), newpos.z()); + } + void World::scaleObject (const Ptr& ptr, float scale) { if (mPhysics->getActor(ptr)) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 1fc5ebc20..75717b16b 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -380,6 +380,9 @@ namespace MWWorld MWWorld::Ptr moveObject (const Ptr& ptr, CellStore* newCell, float x, float y, float z, bool movePhysics=true) override; ///< @return an updated Ptr + MWWorld::Ptr moveObjectBy(const Ptr& ptr, osg::Vec3f vec) override; + ///< @return an updated Ptr + void scaleObject (const Ptr& ptr, float scale) override; /// World rotates object, uses radians