mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-02 08:45:34 +00:00
Integrate MinStep move attempt into stepMove.
This can save 1 to 3 convex casts per iteration.
This commit is contained in:
parent
25a0219e4d
commit
0b08802910
1 changed files with 36 additions and 27 deletions
|
@ -55,6 +55,7 @@ namespace MWPhysics
|
||||||
static const float sMaxSlope = 49.0f;
|
static const float sMaxSlope = 49.0f;
|
||||||
static const float sStepSizeUp = 34.0f;
|
static const float sStepSizeUp = 34.0f;
|
||||||
static const float sStepSizeDown = 62.0f;
|
static const float sStepSizeDown = 62.0f;
|
||||||
|
static const float sMinStep = 10.f;
|
||||||
|
|
||||||
// Arbitrary number. To prevent infinite loops. They shouldn't happen but it's good to be prepared.
|
// Arbitrary number. To prevent infinite loops. They shouldn't happen but it's good to be prepared.
|
||||||
static const int sMaxIterations = 8;
|
static const int sMaxIterations = 8;
|
||||||
|
@ -63,6 +64,12 @@ namespace MWPhysics
|
||||||
class MovementSolver
|
class MovementSolver
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
static bool isActor(const btCollisionObject *obj)
|
||||||
|
{
|
||||||
|
assert(obj);
|
||||||
|
return obj->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor;
|
||||||
|
}
|
||||||
|
|
||||||
template <class Vec3>
|
template <class Vec3>
|
||||||
static bool isWalkableSlope(const Vec3 &normal)
|
static bool isWalkableSlope(const Vec3 &normal)
|
||||||
{
|
{
|
||||||
|
@ -70,14 +77,12 @@ namespace MWPhysics
|
||||||
return (normal.z() > sMaxSlopeCos);
|
return (normal.z() > sMaxSlopeCos);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum StepMoveResult
|
static bool canStepDown(const ActorTracer &stepper)
|
||||||
{
|
{
|
||||||
Result_Blocked, // unable to move over obstacle
|
return stepper.mHitObject && isWalkableSlope(stepper.mPlaneNormal) && !isActor(stepper.mHitObject);
|
||||||
Result_MaxSlope, // unable to end movement on this slope
|
}
|
||||||
Result_Success
|
|
||||||
};
|
|
||||||
|
|
||||||
static StepMoveResult stepMove(const btCollisionObject *colobj, osg::Vec3f &position,
|
static bool stepMove(const btCollisionObject *colobj, osg::Vec3f &position,
|
||||||
const osg::Vec3f &toMove, float &remainingTime, const btCollisionWorld* collisionWorld)
|
const osg::Vec3f &toMove, float &remainingTime, const btCollisionWorld* collisionWorld)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -128,7 +133,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
stepper.doTrace(colobj, position, position+osg::Vec3f(0.0f,0.0f,sStepSizeUp), collisionWorld);
|
stepper.doTrace(colobj, position, position+osg::Vec3f(0.0f,0.0f,sStepSizeUp), collisionWorld);
|
||||||
if(stepper.mFraction < std::numeric_limits<float>::epsilon())
|
if(stepper.mFraction < std::numeric_limits<float>::epsilon())
|
||||||
return Result_Blocked; // didn't even move the smallest representable amount
|
return false; // didn't even move the smallest representable amount
|
||||||
// (TODO: shouldn't this be larger? Why bother with such a small amount?)
|
// (TODO: shouldn't this be larger? Why bother with such a small amount?)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -144,9 +149,10 @@ namespace MWPhysics
|
||||||
* +--+
|
* +--+
|
||||||
* ==============================================
|
* ==============================================
|
||||||
*/
|
*/
|
||||||
tracer.doTrace(colobj, stepper.mEndPos, stepper.mEndPos + toMove, collisionWorld);
|
osg::Vec3f tracerPos = stepper.mEndPos;
|
||||||
|
tracer.doTrace(colobj, tracerPos, tracerPos + toMove, collisionWorld);
|
||||||
if(tracer.mFraction < std::numeric_limits<float>::epsilon())
|
if(tracer.mFraction < std::numeric_limits<float>::epsilon())
|
||||||
return Result_Blocked; // didn't even move the smallest representable amount
|
return false; // didn't even move the smallest representable amount
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try moving back down sStepSizeDown using stepper.
|
* Try moving back down sStepSizeDown using stepper.
|
||||||
|
@ -164,22 +170,32 @@ namespace MWPhysics
|
||||||
* ==============================================
|
* ==============================================
|
||||||
*/
|
*/
|
||||||
stepper.doTrace(colobj, tracer.mEndPos, tracer.mEndPos-osg::Vec3f(0.0f,0.0f,sStepSizeDown), collisionWorld);
|
stepper.doTrace(colobj, tracer.mEndPos, tracer.mEndPos-osg::Vec3f(0.0f,0.0f,sStepSizeDown), collisionWorld);
|
||||||
if (!isWalkableSlope(stepper.mPlaneNormal))
|
if (!canStepDown(stepper))
|
||||||
return Result_MaxSlope;
|
{
|
||||||
if(stepper.mFraction < 1.0f)
|
// Try again with increased step length
|
||||||
|
if (tracer.mFraction < 1.0f || toMove.length2() > sMinStep*sMinStep)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
osg::Vec3f direction = toMove;
|
||||||
|
direction.normalize();
|
||||||
|
tracer.doTrace(colobj, tracerPos, tracerPos + direction*sMinStep, collisionWorld);
|
||||||
|
if (tracer.mFraction < 0.001f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
stepper.doTrace(colobj, tracer.mEndPos, tracer.mEndPos-osg::Vec3f(0.0f,0.0f,sStepSizeDown), collisionWorld);
|
||||||
|
if (!canStepDown(stepper))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (stepper.mFraction < 1.0f)
|
||||||
{
|
{
|
||||||
// don't allow stepping up other actors
|
|
||||||
if (stepper.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor)
|
|
||||||
return Result_Blocked;
|
|
||||||
// only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall.
|
// only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall.
|
||||||
// TODO: stepper.mPlaneNormal does not appear to be reliable - needs more testing
|
// TODO: stepper.mPlaneNormal does not appear to be reliable - needs more testing
|
||||||
// NOTE: caller's variables 'position' & 'remainingTime' are modified here
|
// NOTE: caller's variables 'position' & 'remainingTime' are modified here
|
||||||
position = stepper.mEndPos;
|
position = stepper.mEndPos;
|
||||||
remainingTime *= (1.0f-tracer.mFraction); // remaining time is proportional to remaining distance
|
remainingTime *= (1.0f-tracer.mFraction); // remaining time is proportional to remaining distance
|
||||||
return Result_Success;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
return Result_Blocked;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -369,15 +385,8 @@ namespace MWPhysics
|
||||||
osg::Vec3f oldPosition = newPosition;
|
osg::Vec3f oldPosition = newPosition;
|
||||||
// We hit something. Try to step up onto it. (NOTE: stepMove does not allow stepping over)
|
// We hit something. Try to step up onto it. (NOTE: stepMove does not allow stepping over)
|
||||||
// NOTE: stepMove modifies newPosition if successful
|
// NOTE: stepMove modifies newPosition if successful
|
||||||
const float minStep = 10.f;
|
bool result = stepMove(colobj, newPosition, velocity*remainingTime, remainingTime, collisionWorld);
|
||||||
StepMoveResult result = stepMove(colobj, newPosition, velocity*remainingTime, remainingTime, collisionWorld);
|
if (result)
|
||||||
if (result == Result_MaxSlope && (velocity*remainingTime).length2() < minStep*minStep) // to make sure the maximum stepping distance isn't framerate-dependent or movement-speed dependent
|
|
||||||
{
|
|
||||||
osg::Vec3f normalizedVelocity = velocity;
|
|
||||||
normalizedVelocity.normalize();
|
|
||||||
result = stepMove(colobj, newPosition, normalizedVelocity*minStep, remainingTime, collisionWorld);
|
|
||||||
}
|
|
||||||
if(result == Result_Success)
|
|
||||||
{
|
{
|
||||||
// don't let pure water creatures move out of water after stepMove
|
// don't let pure water creatures move out of water after stepMove
|
||||||
if (ptr.getClass().isPureWaterCreature(ptr)
|
if (ptr.getClass().isPureWaterCreature(ptr)
|
||||||
|
|
Loading…
Reference in a new issue