Merge branch 'setpos' into 'master'

Use relative movement inside of SetPos

See merge request OpenMW/openmw!649
pull/593/head
Evil Eye 4 years ago
commit 4db2f79a3c

@ -190,6 +190,17 @@ void Actor::adjustPosition(const osg::Vec3f& offset)
mPositionOffset += offset; mPositionOffset += offset;
} }
void Actor::applyOffsetChange()
{
if (mPositionOffset.length() == 0)
return;
mWorldPosition += mPositionOffset;
mPosition += mPositionOffset;
mPreviousPosition += mPositionOffset;
mPositionOffset = osg::Vec3f();
mWorldPositionChanged = true;
}
osg::Vec3f Actor::getPosition() const osg::Vec3f Actor::getPosition() const
{ {
return mPosition; return mPosition;

@ -96,9 +96,16 @@ namespace MWPhysics
* Returns true if the new position is different. * Returns true if the new position is different.
*/ */
bool setPosition(const osg::Vec3f& position); bool setPosition(const osg::Vec3f& position);
// force set actor position to be as in Ptr::RefData
void updatePosition(); void updatePosition();
// register a position offset that will be applied during simulation.
void adjustPosition(const osg::Vec3f& offset); void adjustPosition(const osg::Vec3f& offset);
// apply position offset. Can't be called during simulation
void applyOffsetChange();
osg::Vec3f getPosition() const; osg::Vec3f getPosition() const;
osg::Vec3f getPreviousPosition() const; osg::Vec3f getPreviousPosition() const;

@ -492,6 +492,7 @@ namespace MWPhysics
if (actor->setPosition(actorData.mPosition)) if (actor->setPosition(actorData.mPosition))
{ {
std::scoped_lock lock(mCollisionWorldMutex); std::scoped_lock lock(mCollisionWorldMutex);
actorData.mPosition = actor->getPosition(); // account for potential position change made by script
actor->updateCollisionObjectPosition(); actor->updateCollisionObjectPosition();
mCollisionWorld->updateSingleAabb(actor->getCollisionObject()); mCollisionWorld->updateSingleAabb(actor->getCollisionObject());
} }

@ -961,6 +961,10 @@ namespace MWPhysics
void ActorFrameData::updatePosition() void ActorFrameData::updatePosition()
{ {
mActorRaw->updateWorldPosition(); mActorRaw->updateWorldPosition();
// If physics runs "fast enough", position are interpolated without simulation
// By calling this here, we are sure that offsets are applied at least once per frame,
// regardless of simulation speed.
mActorRaw->applyOffsetChange();
mPosition = mActorRaw->getPosition(); mPosition = mActorRaw->getPosition();
if (mMoveToWaterSurface) if (mMoveToWaterSurface)
{ {

@ -270,20 +270,17 @@ namespace MWScript
Interpreter::Type_Float pos = runtime[0].mFloat; Interpreter::Type_Float pos = runtime[0].mFloat;
runtime.pop(); runtime.pop();
float ax = ptr.getRefData().getPosition().pos[0];
float ay = ptr.getRefData().getPosition().pos[1];
float az = ptr.getRefData().getPosition().pos[2];
// Note: SetPos does not skip weather transitions in vanilla engine, so we do not call setTeleported(true) here. // Note: SetPos does not skip weather transitions in vanilla engine, so we do not call setTeleported(true) here.
MWWorld::Ptr updated = ptr; const auto curPos = ptr.getRefData().getPosition().asVec3();
auto newPos = curPos;
if(axis == "x") if(axis == "x")
{ {
updated = MWBase::Environment::get().getWorld()->moveObject(ptr,pos,ay,az,true); newPos[0] = pos;
} }
else if(axis == "y") else if(axis == "y")
{ {
updated = MWBase::Environment::get().getWorld()->moveObject(ptr,ax,pos,az,true); newPos[1] = pos;
} }
else if(axis == "z") else if(axis == "z")
{ {
@ -292,20 +289,21 @@ namespace MWScript
{ {
float terrainHeight = -std::numeric_limits<float>::max(); float terrainHeight = -std::numeric_limits<float>::max();
if (ptr.getCell()->isExterior()) if (ptr.getCell()->isExterior())
terrainHeight = MWBase::Environment::get().getWorld()->getTerrainHeightAt(osg::Vec3f(ax, ay, az)); terrainHeight = MWBase::Environment::get().getWorld()->getTerrainHeightAt(curPos);
if (pos < terrainHeight) if (pos < terrainHeight)
pos = terrainHeight; pos = terrainHeight;
} }
updated = MWBase::Environment::get().getWorld()->moveObject(ptr,ax,ay,pos,true); newPos[2] = pos;
} }
else else
{ {
return; return;
} }
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(ptr,updated); dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(ptr,
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, newPos - curPos));
} }
}; };

Loading…
Cancel
Save