mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-20 18:39:39 +00:00
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.
This commit is contained in:
parent
9f81dcbd1a
commit
7bae6691b6
7 changed files with 41 additions and 31 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue