mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-28 21:07:59 +03:00
Merge branch 'fix-actor-sim-when-idle' into 'master'
Some checks failed
Build and test / Ubuntu (push) Has been cancelled
Build and test / MacOS (push) Has been cancelled
Build and test / Read .env file and expose it as output (push) Has been cancelled
Build and test / Windows (2019) (push) Has been cancelled
Build and test / Windows (2022) (push) Has been cancelled
Some checks failed
Build and test / Ubuntu (push) Has been cancelled
Build and test / MacOS (push) Has been cancelled
Build and test / Read .env file and expose it as output (push) Has been cancelled
Build and test / Windows (2019) (push) Has been cancelled
Build and test / Windows (2022) (push) Has been cancelled
Fix actor simulation running when completely idle Closes #5862 See merge request OpenMW/openmw!4105
This commit is contained in:
commit
042249cf2a
2 changed files with 37 additions and 9 deletions
|
@ -139,17 +139,43 @@ namespace MWPhysics
|
||||||
return;
|
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"
|
// 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
|
// (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
|
// 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
|
// from internal hull translation if not for this hack, the "correct" collision hull position would be
|
||||||
// physicActor->getScaledMeshTranslation()
|
// physicActor->getScaledMeshTranslation()
|
||||||
actor.mPosition.z() += actor.mHalfExtentsZ; // vanilla-accurate
|
actor.mPosition.z() += actor.mHalfExtentsZ; // vanilla-accurate
|
||||||
|
|
||||||
float swimlevel = actor.mSwimLevel + actor.mHalfExtentsZ;
|
float swimlevel = actor.mSwimLevel + actor.mHalfExtentsZ;
|
||||||
|
|
||||||
ActorTracer tracer;
|
|
||||||
|
|
||||||
osg::Vec3f velocity;
|
osg::Vec3f velocity;
|
||||||
|
|
||||||
// Dead and paralyzed actors underwater will float to the surface,
|
// Dead and paralyzed actors underwater will float to the surface,
|
||||||
|
|
|
@ -1331,19 +1331,21 @@ namespace MWWorld
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool isActor = ptr.getClass().isActor();
|
||||||
const float terrainHeight = ptr.getCell()->isExterior()
|
const float terrainHeight = ptr.getCell()->isExterior()
|
||||||
? getTerrainHeightAt(pos, ptr.getCell()->getCell()->getWorldSpace())
|
? getTerrainHeightAt(pos, ptr.getCell()->getCell()->getWorldSpace())
|
||||||
: -std::numeric_limits<float>::max();
|
: -std::numeric_limits<float>::max();
|
||||||
pos.z() = std::max(pos.z(), terrainHeight)
|
pos.z() = std::max(pos.z(), terrainHeight);
|
||||||
+ 20; // place slightly above terrain. will snap down to ground with code below
|
|
||||||
|
|
||||||
// We still should trace down dead persistent actors - they do not use the "swimdeath" animation.
|
// 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());
|
&& !(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
|
// place slightly above terrain. will snap down to ground with code below
|
||||||
= mPhysics->traceDown(ptr, pos, ESM::getCellSize(ptr.getCell()->getCell()->getWorldSpace()));
|
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());
|
pos.z() = std::min(pos.z(), traced.z());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue