Tone down actor's skip simulation flag to an optional skip collision

detection flag.
pull/593/head
fredzio 4 years ago
parent 131a4665aa
commit 4fa0972b2d

@ -287,7 +287,7 @@ 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, bool moveToActive) = 0;
virtual MWWorld::Ptr moveObjectBy(const MWWorld::Ptr &ptr, osg::Vec3f vec, bool moveToActive, bool ignoreCollisions) = 0;
///< @return an updated Ptr
virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0;

@ -123,7 +123,7 @@ void Actor::updatePosition()
mSimulationPosition = mWorldPosition;
mPositionOffset = osg::Vec3f();
mStandingOnPtr = nullptr;
mSkipSimulation = true;
mSkipCollisions = true;
}
void Actor::updateWorldPosition()
@ -140,9 +140,7 @@ osg::Vec3f Actor::getWorldPosition() const
void Actor::setSimulationPosition(const osg::Vec3f& position)
{
if (!mSkipSimulation)
mSimulationPosition = position;
mSkipSimulation = false;
mSimulationPosition = position;
}
osg::Vec3f Actor::getSimulationPosition() const
@ -176,21 +174,19 @@ osg::Vec3f Actor::getCollisionObjectPosition() const
bool Actor::setPosition(const osg::Vec3f& position)
{
std::scoped_lock lock(mPositionMutex);
// position is being forced, ignore simulation results until we sync up
if (mSkipSimulation)
return false;
bool hasChanged = mPosition != position || mPositionOffset.length() != 0 || mWorldPositionChanged;
updateWorldPosition();
applyOffsetChange();
bool hasChanged = mPosition != position || mWorldPositionChanged;
mPreviousPosition = mPosition;
mPosition = position;
return hasChanged;
}
void Actor::adjustPosition(const osg::Vec3f& offset)
void Actor::adjustPosition(const osg::Vec3f& offset, bool ignoreCollisions)
{
std::scoped_lock lock(mPositionMutex);
mPositionOffset += offset;
mSkipCollisions = mSkipCollisions || ignoreCollisions;
}
void Actor::applyOffsetChange()
@ -302,4 +298,9 @@ void Actor::setStandingOnPtr(const MWWorld::Ptr& ptr)
mStandingOnPtr = ptr;
}
bool Actor::skipCollisions()
{
return std::exchange(mSkipCollisions, false);
}
}

@ -101,7 +101,7 @@ namespace MWPhysics
void updatePosition();
// register a position offset that will be applied during simulation.
void adjustPosition(const osg::Vec3f& offset);
void adjustPosition(const osg::Vec3f& offset, bool ignoreCollisions);
// apply position offset. Can't be called during simulation
void applyOffsetChange();
@ -177,6 +177,8 @@ namespace MWPhysics
mLastStuckPosition = position;
}
bool skipCollisions();
private:
MWWorld::Ptr mStandingOnPtr;
/// Removes then re-adds the collision object to the dynamics world
@ -206,7 +208,7 @@ namespace MWPhysics
osg::Vec3f mPreviousPosition;
osg::Vec3f mPositionOffset;
bool mWorldPositionChanged;
bool mSkipSimulation;
bool mSkipCollisions;
btTransform mLocalTransform;
mutable std::mutex mPositionMutex;

@ -131,7 +131,7 @@ namespace MWPhysics
// Reset per-frame data
physicActor->setWalkingOnWater(false);
// Anything to collide with?
if(!physicActor->getCollisionMode())
if(!physicActor->getCollisionMode() || actor.mSkipCollisionDetection)
{
actor.mPosition += (osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) *
osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1))
@ -437,7 +437,7 @@ namespace MWPhysics
return;
auto* physicActor = actor.mActorRaw;
if(!physicActor->getCollisionMode()) // noclipping/tcl
if(!physicActor->getCollisionMode() || actor.mSkipCollisionDetection) // noclipping/tcl
return;
auto* collisionObject = physicActor->getCollisionObject();

@ -361,7 +361,6 @@ namespace MWPhysics
for (const auto& [_, actor] : actors)
{
actor->updatePosition();
actor->setSimulationPosition(actor->getWorldPosition()); // updatePosition skip next simulation, now we need to "consume" it
actor->updateCollisionObjectPosition();
mMovedActors.emplace_back(actor->getPtr());
}

@ -954,9 +954,7 @@ namespace MWPhysics
void ActorFrameData::updatePosition(btCollisionWorld* world)
{
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.
mSkipCollisionDetection = mActorRaw->skipCollisions();
mActorRaw->applyOffsetChange();
mPosition = mActorRaw->getPosition();
if (mWaterCollision && mPosition.z() < mWaterlevel && canMoveToWaterSurface(mActorRaw, mWaterlevel, world))

@ -91,6 +91,7 @@ namespace MWPhysics
bool mFloatToSurface;
bool mNeedLand;
bool mWaterCollision;
bool mSkipCollisionDetection;
float mWaterlevel;
float mSlowFall;
float mOldHeight;

@ -32,7 +32,7 @@ namespace MWScript
std::vector<MWWorld::Ptr> actors;
MWBase::Environment::get().getWorld()->getActorsStandingOn (ptr, actors);
for (auto& actor : actors)
MWBase::Environment::get().getWorld()->moveObjectBy(actor, diff, false);
MWBase::Environment::get().getWorld()->moveObjectBy(actor, diff, false, false);
}
template<class R>
@ -303,7 +303,7 @@ namespace MWScript
}
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(ptr,
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, newPos - curPos, true));
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, newPos - curPos, true, true));
}
};
@ -726,7 +726,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()->moveObjectBy(ptr, diff, false));
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff, false, true));
}
};
@ -762,7 +762,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()->moveObjectBy(ptr, diff, false));
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff, false, true));
}
};

@ -1253,12 +1253,12 @@ namespace MWWorld
return moveObject(ptr, cell, x, y, z, movePhysics);
}
MWWorld::Ptr World::moveObjectBy(const Ptr& ptr, osg::Vec3f vec, bool moveToActive)
MWWorld::Ptr World::moveObjectBy(const Ptr& ptr, osg::Vec3f vec, bool moveToActive, bool ignoreCollisions)
{
auto* actor = mPhysics->getActor(ptr);
osg::Vec3f newpos = ptr.getRefData().getPosition().asVec3() + vec;
if (actor)
actor->adjustPosition(vec);
actor->adjustPosition(vec, ignoreCollisions);
if (ptr.getClass().isActor())
return moveObject(ptr, newpos.x(), newpos.y(), newpos.z(), false, moveToActive && ptr != getPlayerPtr());
return moveObject(ptr, newpos.x(), newpos.y(), newpos.z());

@ -377,7 +377,7 @@ 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, bool moveToActive) override;
MWWorld::Ptr moveObjectBy(const Ptr& ptr, osg::Vec3f vec, bool moveToActive, bool ignoreCollisions) override;
///< @return an updated Ptr
void scaleObject (const Ptr& ptr, float scale) override;

Loading…
Cancel
Save