mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-25 16:43:33 +00:00
Tone down actor's skip simulation flag to an optional skip collision
detection flag.
This commit is contained in:
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;
|
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, bool moveToActive) = 0;
|
virtual MWWorld::Ptr moveObjectBy(const MWWorld::Ptr &ptr, osg::Vec3f vec, bool moveToActive, bool ignoreCollisions) = 0;
|
||||||
///< @return an updated Ptr
|
///< @return an updated Ptr
|
||||||
|
|
||||||
virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0;
|
virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0;
|
||||||
|
@ -123,7 +123,7 @@ void Actor::updatePosition()
|
|||||||
mSimulationPosition = mWorldPosition;
|
mSimulationPosition = mWorldPosition;
|
||||||
mPositionOffset = osg::Vec3f();
|
mPositionOffset = osg::Vec3f();
|
||||||
mStandingOnPtr = nullptr;
|
mStandingOnPtr = nullptr;
|
||||||
mSkipSimulation = true;
|
mSkipCollisions = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actor::updateWorldPosition()
|
void Actor::updateWorldPosition()
|
||||||
@ -140,9 +140,7 @@ osg::Vec3f Actor::getWorldPosition() const
|
|||||||
|
|
||||||
void Actor::setSimulationPosition(const osg::Vec3f& position)
|
void Actor::setSimulationPosition(const osg::Vec3f& position)
|
||||||
{
|
{
|
||||||
if (!mSkipSimulation)
|
mSimulationPosition = position;
|
||||||
mSimulationPosition = position;
|
|
||||||
mSkipSimulation = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec3f Actor::getSimulationPosition() const
|
osg::Vec3f Actor::getSimulationPosition() const
|
||||||
@ -176,21 +174,19 @@ osg::Vec3f Actor::getCollisionObjectPosition() const
|
|||||||
bool Actor::setPosition(const osg::Vec3f& position)
|
bool Actor::setPosition(const osg::Vec3f& position)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mPositionMutex);
|
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();
|
updateWorldPosition();
|
||||||
applyOffsetChange();
|
applyOffsetChange();
|
||||||
|
bool hasChanged = mPosition != position || mWorldPositionChanged;
|
||||||
mPreviousPosition = mPosition;
|
mPreviousPosition = mPosition;
|
||||||
mPosition = position;
|
mPosition = position;
|
||||||
return hasChanged;
|
return hasChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actor::adjustPosition(const osg::Vec3f& offset)
|
void Actor::adjustPosition(const osg::Vec3f& offset, bool ignoreCollisions)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mPositionMutex);
|
std::scoped_lock lock(mPositionMutex);
|
||||||
mPositionOffset += offset;
|
mPositionOffset += offset;
|
||||||
|
mSkipCollisions = mSkipCollisions || ignoreCollisions;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actor::applyOffsetChange()
|
void Actor::applyOffsetChange()
|
||||||
@ -302,4 +298,9 @@ void Actor::setStandingOnPtr(const MWWorld::Ptr& ptr)
|
|||||||
mStandingOnPtr = ptr;
|
mStandingOnPtr = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Actor::skipCollisions()
|
||||||
|
{
|
||||||
|
return std::exchange(mSkipCollisions, false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ namespace MWPhysics
|
|||||||
void updatePosition();
|
void updatePosition();
|
||||||
|
|
||||||
// register a position offset that will be applied during simulation.
|
// 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
|
// apply position offset. Can't be called during simulation
|
||||||
void applyOffsetChange();
|
void applyOffsetChange();
|
||||||
@ -177,6 +177,8 @@ namespace MWPhysics
|
|||||||
mLastStuckPosition = position;
|
mLastStuckPosition = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool skipCollisions();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MWWorld::Ptr mStandingOnPtr;
|
MWWorld::Ptr mStandingOnPtr;
|
||||||
/// Removes then re-adds the collision object to the dynamics world
|
/// Removes then re-adds the collision object to the dynamics world
|
||||||
@ -206,7 +208,7 @@ namespace MWPhysics
|
|||||||
osg::Vec3f mPreviousPosition;
|
osg::Vec3f mPreviousPosition;
|
||||||
osg::Vec3f mPositionOffset;
|
osg::Vec3f mPositionOffset;
|
||||||
bool mWorldPositionChanged;
|
bool mWorldPositionChanged;
|
||||||
bool mSkipSimulation;
|
bool mSkipCollisions;
|
||||||
btTransform mLocalTransform;
|
btTransform mLocalTransform;
|
||||||
mutable std::mutex mPositionMutex;
|
mutable std::mutex mPositionMutex;
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ namespace MWPhysics
|
|||||||
// Reset per-frame data
|
// Reset per-frame data
|
||||||
physicActor->setWalkingOnWater(false);
|
physicActor->setWalkingOnWater(false);
|
||||||
// Anything to collide with?
|
// Anything to collide with?
|
||||||
if(!physicActor->getCollisionMode())
|
if(!physicActor->getCollisionMode() || actor.mSkipCollisionDetection)
|
||||||
{
|
{
|
||||||
actor.mPosition += (osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) *
|
actor.mPosition += (osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) *
|
||||||
osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1))
|
osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1))
|
||||||
@ -437,7 +437,7 @@ namespace MWPhysics
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
auto* physicActor = actor.mActorRaw;
|
auto* physicActor = actor.mActorRaw;
|
||||||
if(!physicActor->getCollisionMode()) // noclipping/tcl
|
if(!physicActor->getCollisionMode() || actor.mSkipCollisionDetection) // noclipping/tcl
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto* collisionObject = physicActor->getCollisionObject();
|
auto* collisionObject = physicActor->getCollisionObject();
|
||||||
|
@ -361,7 +361,6 @@ namespace MWPhysics
|
|||||||
for (const auto& [_, actor] : actors)
|
for (const auto& [_, actor] : actors)
|
||||||
{
|
{
|
||||||
actor->updatePosition();
|
actor->updatePosition();
|
||||||
actor->setSimulationPosition(actor->getWorldPosition()); // updatePosition skip next simulation, now we need to "consume" it
|
|
||||||
actor->updateCollisionObjectPosition();
|
actor->updateCollisionObjectPosition();
|
||||||
mMovedActors.emplace_back(actor->getPtr());
|
mMovedActors.emplace_back(actor->getPtr());
|
||||||
}
|
}
|
||||||
|
@ -954,9 +954,7 @@ namespace MWPhysics
|
|||||||
void ActorFrameData::updatePosition(btCollisionWorld* world)
|
void ActorFrameData::updatePosition(btCollisionWorld* world)
|
||||||
{
|
{
|
||||||
mActorRaw->updateWorldPosition();
|
mActorRaw->updateWorldPosition();
|
||||||
// If physics runs "fast enough", position are interpolated without simulation
|
mSkipCollisionDetection = mActorRaw->skipCollisions();
|
||||||
// By calling this here, we are sure that offsets are applied at least once per frame,
|
|
||||||
// regardless of simulation speed.
|
|
||||||
mActorRaw->applyOffsetChange();
|
mActorRaw->applyOffsetChange();
|
||||||
mPosition = mActorRaw->getPosition();
|
mPosition = mActorRaw->getPosition();
|
||||||
if (mWaterCollision && mPosition.z() < mWaterlevel && canMoveToWaterSurface(mActorRaw, mWaterlevel, world))
|
if (mWaterCollision && mPosition.z() < mWaterlevel && canMoveToWaterSurface(mActorRaw, mWaterlevel, world))
|
||||||
|
@ -91,6 +91,7 @@ namespace MWPhysics
|
|||||||
bool mFloatToSurface;
|
bool mFloatToSurface;
|
||||||
bool mNeedLand;
|
bool mNeedLand;
|
||||||
bool mWaterCollision;
|
bool mWaterCollision;
|
||||||
|
bool mSkipCollisionDetection;
|
||||||
float mWaterlevel;
|
float mWaterlevel;
|
||||||
float mSlowFall;
|
float mSlowFall;
|
||||||
float mOldHeight;
|
float mOldHeight;
|
||||||
|
@ -32,7 +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, false);
|
MWBase::Environment::get().getWorld()->moveObjectBy(actor, diff, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class R>
|
template<class R>
|
||||||
@ -303,7 +303,7 @@ namespace MWScript
|
|||||||
}
|
}
|
||||||
|
|
||||||
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(ptr,
|
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.
|
// 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()->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.
|
// 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()->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);
|
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);
|
auto* actor = mPhysics->getActor(ptr);
|
||||||
osg::Vec3f newpos = ptr.getRefData().getPosition().asVec3() + vec;
|
osg::Vec3f newpos = ptr.getRefData().getPosition().asVec3() + vec;
|
||||||
if (actor)
|
if (actor)
|
||||||
actor->adjustPosition(vec);
|
actor->adjustPosition(vec, ignoreCollisions);
|
||||||
if (ptr.getClass().isActor())
|
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(), false, moveToActive && ptr != getPlayerPtr());
|
||||||
return moveObject(ptr, newpos.x(), newpos.y(), newpos.z());
|
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;
|
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, bool moveToActive) override;
|
MWWorld::Ptr moveObjectBy(const Ptr& ptr, osg::Vec3f vec, bool moveToActive, bool ignoreCollisions) override;
|
||||||
///< @return an updated Ptr
|
///< @return an updated Ptr
|
||||||
|
|
||||||
void scaleObject (const Ptr& ptr, float scale) override;
|
void scaleObject (const Ptr& ptr, float scale) override;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user