1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-30 16:20:21 +00:00

Merge branch 'relative_move' into 'master'

Relative translation for scripts

See merge request OpenMW/openmw!477
This commit is contained in:
psi29a 2020-12-18 09:23:18 +00:00
commit d01d5745c6
7 changed files with 41 additions and 31 deletions

View File

@ -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; 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 ///< @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 scaleObject (const MWWorld::Ptr& ptr, float scale) = 0;
virtual void rotateObject(const MWWorld::Ptr& ptr, float x, float y, float z, virtual void rotateObject(const MWWorld::Ptr& ptr, float x, float y, float z,

View File

@ -120,6 +120,8 @@ int Actor::getCollisionMask() const
void Actor::updatePositionUnsafe() void Actor::updatePositionUnsafe()
{ {
if (!mWorldPositionChanged && mWorldPosition != mPtr.getRefData().getPosition().asVec3())
mWorldPositionChanged = true;
mWorldPosition = mPtr.getRefData().getPosition().asVec3(); mWorldPosition = mPtr.getRefData().getPosition().asVec3();
} }
@ -153,6 +155,7 @@ void Actor::updateCollisionObjectPositionUnsafe()
mLocalTransform.setOrigin(Misc::Convert::toBullet(newPosition)); mLocalTransform.setOrigin(Misc::Convert::toBullet(newPosition));
mLocalTransform.setRotation(Misc::Convert::toBullet(mRotation)); mLocalTransform.setRotation(Misc::Convert::toBullet(mRotation));
mCollisionObject->setWorldTransform(mLocalTransform); mCollisionObject->setWorldTransform(mLocalTransform);
mWorldPositionChanged = false;
} }
void Actor::updateCollisionObjectPosition() void Actor::updateCollisionObjectPosition()
@ -167,18 +170,20 @@ osg::Vec3f Actor::getCollisionObjectPosition() const
return Misc::Convert::toOsg(mLocalTransform.getOrigin()); 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); std::scoped_lock lock(mPositionMutex);
mPreviousPosition = mPosition; bool hasChanged = mPosition != position || mPositionOffset.length() != 0 || mWorldPositionChanged;
mPosition = position; mPreviousPosition = mPosition + mPositionOffset;
mPosition = position + mPositionOffset;
mPositionOffset = osg::Vec3f();
return hasChanged;
} }
void Actor::adjustPosition(const osg::Vec3f& offset) void Actor::adjustPosition(const osg::Vec3f& offset)
{ {
std::scoped_lock lock(mPositionMutex); std::scoped_lock lock(mPositionMutex);
mPosition += offset; mPositionOffset += offset;
mPreviousPosition += offset;
} }
void Actor::resetPosition() void Actor::resetPosition()
@ -189,6 +194,8 @@ void Actor::resetPosition()
mPosition = mWorldPosition; mPosition = mWorldPosition;
mSimulationPosition = mWorldPosition; mSimulationPosition = mWorldPosition;
updateCollisionObjectPositionUnsafe(); updateCollisionObjectPositionUnsafe();
mStandingOnPtr = nullptr;
mWorldPositionChanged = false;
} }
osg::Vec3f Actor::getPosition() const osg::Vec3f Actor::getPosition() const

View File

@ -90,8 +90,9 @@ namespace MWPhysics
/** /**
* Store the current position into mPreviousPosition, then move to this position. * 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 resetPosition();
void adjustPosition(const osg::Vec3f& offset); void adjustPosition(const osg::Vec3f& offset);
@ -177,6 +178,8 @@ namespace MWPhysics
osg::Vec3f mSimulationPosition; osg::Vec3f mSimulationPosition;
osg::Vec3f mPosition; osg::Vec3f mPosition;
osg::Vec3f mPreviousPosition; osg::Vec3f mPreviousPosition;
osg::Vec3f mPositionOffset;
bool mWorldPositionChanged;
btTransform mLocalTransform; btTransform mLocalTransform;
mutable std::mutex mPositionMutex; mutable std::mutex mPositionMutex;

View File

@ -100,15 +100,6 @@ namespace
osg::Vec3f interpolateMovements(MWPhysics::ActorFrameData& actorData, float timeAccum, float physicsDt) osg::Vec3f interpolateMovements(MWPhysics::ActorFrameData& actorData, float timeAccum, float physicsDt)
{ {
const float interpolationFactor = timeAccum / 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); return actorData.mPosition * interpolationFactor + actorData.mActorRaw->getPreviousPosition() * (1.f - interpolationFactor);
} }
@ -511,9 +502,7 @@ namespace MWPhysics
{ {
if(const auto actor = actorData.mActor.lock()) if(const auto actor = actorData.mActor.lock())
{ {
bool positionChanged = actorData.mPosition != actorData.mActorRaw->getPosition(); if (actor->setPosition(actorData.mPosition))
actorData.mActorRaw->setPosition(actorData.mPosition);
if (positionChanged)
{ {
actor->updateCollisionObjectPosition(); actor->updateCollisionObjectPosition();
mCollisionWorld->updateSingleAabb(actor->getCollisionObject()); mCollisionWorld->updateSingleAabb(actor->getCollisionObject());

View File

@ -32,11 +32,7 @@ namespace MWScript
std::vector<MWWorld::Ptr> actors; std::vector<MWWorld::Ptr> actors;
MWBase::Environment::get().getWorld()->getActorsStandingOn (ptr, actors); MWBase::Environment::get().getWorld()->getActorsStandingOn (ptr, actors);
for (auto& actor : actors) for (auto& actor : actors)
{ MWBase::Environment::get().getWorld()->moveObjectBy(actor, diff);
osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
actorPos += diff;
MWBase::Environment::get().getWorld()->moveObject(actor, actorPos.x(), actorPos.y(), actorPos.z());
}
} }
template<class R> template<class R>
@ -727,14 +723,12 @@ namespace MWScript
return; return;
osg::Vec3f diff = ptr.getRefData().getBaseNode()->getAttitude() * posChange; 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. // We should move actors, standing on moving object, too.
// This approach can be used to create elevators. // This approach can be used to create elevators.
moveStandingActors(ptr, diff); moveStandingActors(ptr, diff);
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(ptr, dynamic_cast<MWScript::InterpreterContext&>(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()); Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
runtime.pop(); runtime.pop();
const float *objPos = ptr.getRefData().getPosition().pos;
osg::Vec3f diff; osg::Vec3f diff;
if (axis == "x") if (axis == "x")
diff.x() += movement; diff.x() = movement;
else if (axis == "y") else if (axis == "y")
diff.y() += movement; diff.y() = movement;
else if (axis == "z") else if (axis == "z")
diff.z() += movement; diff.z() = movement;
else else
return; return;
@ -771,7 +764,7 @@ namespace MWScript
// This approach can be used to create elevators. // This approach can be used to create elevators.
moveStandingActors(ptr, diff); moveStandingActors(ptr, diff);
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(ptr, dynamic_cast<MWScript::InterpreterContext&>(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));
} }
}; };

View File

@ -1251,6 +1251,18 @@ namespace MWWorld
return moveObjectImp(ptr, x, y, z, true, moveToActive); 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) void World::scaleObject (const Ptr& ptr, float scale)
{ {
if (mPhysics->getActor(ptr)) if (mPhysics->getActor(ptr))

View File

@ -380,6 +380,9 @@ namespace MWWorld
MWWorld::Ptr moveObject (const Ptr& ptr, CellStore* newCell, float x, float y, float z, bool movePhysics=true) override; MWWorld::Ptr moveObject (const Ptr& ptr, CellStore* newCell, float x, float y, float z, bool movePhysics=true) override;
///< @return an updated Ptr ///< @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; void scaleObject (const Ptr& ptr, float scale) override;
/// World rotates object, uses radians /// World rotates object, uses radians