1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-17 19:20:49 +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;
///< @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,

View File

@ -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

View File

@ -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;

View File

@ -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());

View File

@ -32,11 +32,7 @@ namespace MWScript
std::vector<MWWorld::Ptr> 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<class R>
@ -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<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());
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<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);
}
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))

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;
///< @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