1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-07-21 06:14:05 +00:00

Improve movement inertia

Handles all 3 axis. Incoming velocity is only added to inertia when
leaving the ground, and does not continually add to it.
This commit is contained in:
Chris Robinson 2013-08-18 05:38:50 -07:00
parent 9d56e2d86d
commit 8c3564326e
3 changed files with 48 additions and 39 deletions

View file

@ -132,8 +132,10 @@ namespace MWWorld
position.z += halfExtents.z; position.z += halfExtents.z;
OEngine::Physic::ActorTracer tracer; OEngine::Physic::ActorTracer tracer;
bool onground = false; bool wasOnGround = false;
bool isOnGround = false;
const Ogre::Quaternion orient; // Don't rotate actor collision boxes const Ogre::Quaternion orient; // Don't rotate actor collision boxes
Ogre::Vector3 inertia(0.0f);
Ogre::Vector3 velocity; Ogre::Vector3 velocity;
if(!gravity) if(!gravity)
{ {
@ -143,18 +145,20 @@ namespace MWWorld
movement; movement;
} }
else else
{
if(!(movement.z > 0.0f))
{ {
tracer.doTrace(colobj, position, position-Ogre::Vector3(0,0,4), engine); tracer.doTrace(colobj, position, position-Ogre::Vector3(0,0,4), engine);
if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope) if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope)
onground = true; {
wasOnGround = true;
if(!(movement.z > 0.0f))
isOnGround = true;
} }
inertia = physicActor->getInertialForce();
velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z) * movement; velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z) * movement;
velocity.z += physicActor->getVerticalForce(); velocity += inertia;
} }
if(onground) if(isOnGround)
{ {
// if we're on the ground, don't try to fall // if we're on the ground, don't try to fall
velocity.z = std::max(0.0f, velocity.z); velocity.z = std::max(0.0f, velocity.z);
@ -179,7 +183,7 @@ namespace MWWorld
//std::cout<<"angle: "<<getSlope(trace.planenormal)<<"\n"; //std::cout<<"angle: "<<getSlope(trace.planenormal)<<"\n";
// We hit something. Try to step up onto it. // We hit something. Try to step up onto it.
if(stepMove(colobj, newPosition, velocity, remainingTime, engine)) if(stepMove(colobj, newPosition, velocity, remainingTime, engine))
onground = gravity; isOnGround = gravity;
else else
{ {
// Can't move this way, try to find another spot along the plane // Can't move this way, try to find another spot along the plane
@ -195,17 +199,25 @@ namespace MWWorld
} }
} }
if(onground) if(isOnGround)
{ {
tracer.doTrace(colobj, newPosition, newPosition-Ogre::Vector3(0,0,sStepSize+4.0f), engine); tracer.doTrace(colobj, newPosition, newPosition-Ogre::Vector3(0,0,sStepSize+4.0f), engine);
if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope) if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope)
newPosition.z = tracer.mEndPos.z + 2.0f; newPosition.z = tracer.mEndPos.z + 2.0f;
else else
onground = false; isOnGround = false;
} }
physicActor->setOnGround(onground); physicActor->setOnGround(isOnGround);
physicActor->setVerticalForce(!onground ? velocity.z - time*627.2f : 0.0f); if(isOnGround)
physicActor->setInertialForce(Ogre::Vector3(0.0f));
else
{
if(wasOnGround)
inertia = velocity;
inertia.z -= time*627.2f;
physicActor->setInertialForce(inertia);
}
newPosition.z -= halfExtents.z; newPosition.z -= halfExtents.z;
return newPosition; return newPosition;

View file

@ -19,7 +19,8 @@ namespace Physic
PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale) PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale)
: mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0) : mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0)
, mBody(0), mRaycastingBody(0), onGround(false), collisionMode(true), mBoxRotation(0,0,0,0), verticalForce(0.0f) , mBody(0), mRaycastingBody(0), mOnGround(false), mCollisionMode(true), mBoxRotation(0,0,0,0)
, mForce(0.0f)
{ {
mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation); mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation);
mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation, true); mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation, true);
@ -45,9 +46,9 @@ namespace Physic
void PhysicActor::enableCollisions(bool collision) void PhysicActor::enableCollisions(bool collision)
{ {
assert(mBody); assert(mBody);
if(collision && !collisionMode) enableCollisionBody(); if(collision && !mCollisionMode) enableCollisionBody();
if(!collision && collisionMode) disableCollisionBody(); if(!collision && mCollisionMode) disableCollisionBody();
collisionMode = collision; mCollisionMode = collision;
} }
@ -123,24 +124,14 @@ namespace Physic
return Ogre::Vector3(0.0f); return Ogre::Vector3(0.0f);
} }
void PhysicActor::setVerticalForce(float force) void PhysicActor::setInertialForce(const Ogre::Vector3 &force)
{ {
verticalForce = force; mForce = force;
}
float PhysicActor::getVerticalForce() const
{
return verticalForce;
} }
void PhysicActor::setOnGround(bool grounded) void PhysicActor::setOnGround(bool grounded)
{ {
onGround = grounded; mOnGround = grounded;
}
bool PhysicActor::getOnGround() const
{
return collisionMode && onGround;
} }
void PhysicActor::disableCollisionBody() void PhysicActor::disableCollisionBody()

View file

@ -104,7 +104,7 @@ namespace Physic
bool getCollisionMode() const bool getCollisionMode() const
{ {
return collisionMode; return mCollisionMode;
} }
@ -130,18 +130,24 @@ namespace Physic
Ogre::Vector3 getHalfExtents() const; Ogre::Vector3 getHalfExtents() const;
/** /**
* Sets the current amount of vertical force (gravity) affecting this physic actor * Sets the current amount of inertial force (incl. gravity) affecting this physic actor
*/ */
void setVerticalForce(float force); void setInertialForce(const Ogre::Vector3 &force);
/** /**
* Gets the current amount of vertical force (gravity) affecting this physic actor * Gets the current amount of inertial force (incl. gravity) affecting this physic actor
*/ */
float getVerticalForce() const; const Ogre::Vector3 &getInertialForce() const
{
return mForce;
}
void setOnGround(bool grounded); void setOnGround(bool grounded);
bool getOnGround() const; bool getOnGround() const
{
return mCollisionMode && mOnGround;
}
btCollisionObject *getCollisionBody() const btCollisionObject *getCollisionBody() const
{ {
@ -169,9 +175,9 @@ public:
Ogre::Quaternion mBoxRotation; Ogre::Quaternion mBoxRotation;
btQuaternion mBoxRotationInverse; btQuaternion mBoxRotationInverse;
float verticalForce; Ogre::Vector3 mForce;
bool onGround; bool mOnGround;
bool collisionMode; bool mCollisionMode;
std::string mMesh; std::string mMesh;
std::string mName; std::string mName;