mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-14 01:19:59 +00:00
Merge branch 'fix-actor-sim-when-idle' into 'master'
Fix actor simulation running when completely idle Closes #5862 See merge request OpenMW/openmw!4105
This commit is contained in:
commit
0b6684734c
@ -139,17 +139,43 @@ namespace MWPhysics
|
||||
return;
|
||||
}
|
||||
|
||||
// Physics simulation can be potentially skipped if all conditions match:
|
||||
// - Actor is on ground
|
||||
// - Actor is not flying
|
||||
// - mIsAquatic is false
|
||||
// - mMovement is a zero vector
|
||||
// - mInertia is a zero vector
|
||||
// This is important to fix #3803 and others
|
||||
ActorTracer tracer;
|
||||
if (!actor.mFlying && actor.mIsOnGround && !actor.mIsAquatic && actor.mMovement.length2() == 0
|
||||
&& actor.mInertia.length2() == 0)
|
||||
{
|
||||
// We think we can skip the simulation, but we must double check to cover edge cases
|
||||
// trace the actor's collision object down to try and find valid ground to stand on
|
||||
// the ground could be removed from the actor, so we cant just remember the last ground value
|
||||
// we must also check if walking on water even if we skip this movement simulation
|
||||
// the simulation can also only be skipped if it finds solid ground, not an actor or unwalkable slope
|
||||
const osg::Vec3f from = actor.mPosition + osg::Vec3f(0.0f, 0.0f, actor.mHalfExtentsZ);
|
||||
const auto dropDistance = 2 * sGroundOffset + (actor.mIsOnGround ? sStepSizeDown : 0);
|
||||
const osg::Vec3f to = from - osg::Vec3f(0, 0, dropDistance);
|
||||
tracer.doTrace(actor.mCollisionObject, from, to, collisionWorld, actor.mIsOnGround);
|
||||
if (tracer.mFraction < 1.0f && !isActor(tracer.mHitObject) && isWalkableSlope(tracer.mPlaneNormal))
|
||||
{
|
||||
actor.mStandingOn = tracer.mHitObject;
|
||||
actor.mWalkingOnWater
|
||||
= actor.mStandingOn->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Water;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust for collision mesh offset relative to actor's "location"
|
||||
// (doTrace doesn't take local/interior collision shape translation into account, so we have to do it on our
|
||||
// own) for compatibility with vanilla assets, we have to derive this from the vertical half extent instead of
|
||||
// from internal hull translation if not for this hack, the "correct" collision hull position would be
|
||||
// physicActor->getScaledMeshTranslation()
|
||||
actor.mPosition.z() += actor.mHalfExtentsZ; // vanilla-accurate
|
||||
|
||||
float swimlevel = actor.mSwimLevel + actor.mHalfExtentsZ;
|
||||
|
||||
ActorTracer tracer;
|
||||
|
||||
osg::Vec3f velocity;
|
||||
|
||||
// Dead and paralyzed actors underwater will float to the surface,
|
||||
|
@ -1331,19 +1331,21 @@ namespace MWWorld
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isActor = ptr.getClass().isActor();
|
||||
const float terrainHeight = ptr.getCell()->isExterior()
|
||||
? getTerrainHeightAt(pos, ptr.getCell()->getCell()->getWorldSpace())
|
||||
: -std::numeric_limits<float>::max();
|
||||
pos.z() = std::max(pos.z(), terrainHeight)
|
||||
+ 20; // place slightly above terrain. will snap down to ground with code below
|
||||
pos.z() = std::max(pos.z(), terrainHeight);
|
||||
|
||||
// We still should trace down dead persistent actors - they do not use the "swimdeath" animation.
|
||||
bool swims = ptr.getClass().isActor() && isSwimming(ptr)
|
||||
bool swims = isActor && isSwimming(ptr)
|
||||
&& !(ptr.getClass().isPersistent(ptr) && ptr.getClass().getCreatureStats(ptr).isDeathAnimationFinished());
|
||||
if (force || !ptr.getClass().isActor() || (!isFlying(ptr) && !swims && isActorCollisionEnabled(ptr)))
|
||||
if (force || !isActor || (!isFlying(ptr) && !swims && isActorCollisionEnabled(ptr)))
|
||||
{
|
||||
osg::Vec3f traced
|
||||
= mPhysics->traceDown(ptr, pos, ESM::getCellSize(ptr.getCell()->getCell()->getWorldSpace()));
|
||||
// place slightly above terrain. will snap down to ground with code below
|
||||
const osg::Vec3f posAdjusted = pos + osg::Vec3f(0.0f, 0.0f, 20.0f);
|
||||
const osg::Vec3f traced
|
||||
= mPhysics->traceDown(ptr, posAdjusted, ESM::getCellSize(ptr.getCell()->getCell()->getWorldSpace()));
|
||||
pos.z() = std::min(pos.z(), traced.z());
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user