From 8c3564326e73bb897f84084f2f4601b8af1e0174 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 18 Aug 2013 05:38:50 -0700 Subject: [PATCH] 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. --- apps/openmw/mwworld/physicssystem.cpp | 38 ++++++++++++++++++--------- libs/openengine/bullet/physic.cpp | 25 ++++++------------ libs/openengine/bullet/physic.hpp | 24 ++++++++++------- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 94eba704c..bff7b28ab 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -132,8 +132,10 @@ namespace MWWorld position.z += halfExtents.z; OEngine::Physic::ActorTracer tracer; - bool onground = false; + bool wasOnGround = false; + bool isOnGround = false; const Ogre::Quaternion orient; // Don't rotate actor collision boxes + Ogre::Vector3 inertia(0.0f); Ogre::Vector3 velocity; if(!gravity) { @@ -144,17 +146,19 @@ namespace MWWorld } else { - if(!(movement.z > 0.0f)) + tracer.doTrace(colobj, position, position-Ogre::Vector3(0,0,4), engine); + if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope) { - tracer.doTrace(colobj, position, position-Ogre::Vector3(0,0,4), engine); - if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope) - onground = true; + wasOnGround = true; + if(!(movement.z > 0.0f)) + isOnGround = true; } - velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z) * movement; - velocity.z += physicActor->getVerticalForce(); + inertia = physicActor->getInertialForce(); + velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z) * movement; + velocity += inertia; } - if(onground) + if(isOnGround) { // if we're on the ground, don't try to fall velocity.z = std::max(0.0f, velocity.z); @@ -179,7 +183,7 @@ namespace MWWorld //std::cout<<"angle: "<setOnGround(onground); - physicActor->setVerticalForce(!onground ? velocity.z - time*627.2f : 0.0f); + physicActor->setOnGround(isOnGround); + 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; return newPosition; diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index ba47b6e64..e488d6e99 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -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) : 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); mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation, true); @@ -45,9 +46,9 @@ namespace Physic void PhysicActor::enableCollisions(bool collision) { assert(mBody); - if(collision && !collisionMode) enableCollisionBody(); - if(!collision && collisionMode) disableCollisionBody(); - collisionMode = collision; + if(collision && !mCollisionMode) enableCollisionBody(); + if(!collision && mCollisionMode) disableCollisionBody(); + mCollisionMode = collision; } @@ -123,24 +124,14 @@ namespace Physic return Ogre::Vector3(0.0f); } - void PhysicActor::setVerticalForce(float force) + void PhysicActor::setInertialForce(const Ogre::Vector3 &force) { - verticalForce = force; - } - - float PhysicActor::getVerticalForce() const - { - return verticalForce; + mForce = force; } void PhysicActor::setOnGround(bool grounded) { - onGround = grounded; - } - - bool PhysicActor::getOnGround() const - { - return collisionMode && onGround; + mOnGround = grounded; } void PhysicActor::disableCollisionBody() diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 9b1541ea2..46dafda76 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -104,7 +104,7 @@ namespace Physic bool getCollisionMode() const { - return collisionMode; + return mCollisionMode; } @@ -130,18 +130,24 @@ namespace Physic 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); - bool getOnGround() const; + bool getOnGround() const + { + return mCollisionMode && mOnGround; + } btCollisionObject *getCollisionBody() const { @@ -169,9 +175,9 @@ public: Ogre::Quaternion mBoxRotation; btQuaternion mBoxRotationInverse; - float verticalForce; - bool onGround; - bool collisionMode; + Ogre::Vector3 mForce; + bool mOnGround; + bool mCollisionMode; std::string mMesh; std::string mName;