diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index c942fecb1b..7c083ca08f 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -798,6 +798,43 @@ namespace MWPhysics return !result.mHit; } + // physactor->getOnGround() is not a reliable indicator of whether the actor + // is on the ground (defaults to false, which means code blocks such as + // CharacterController::update() may falsely detect "falling"). + // + // Also, collisions can move z position slightly off zero, giving a false + // indication. In order to reduce false detection of jumping, small distance + // below the actor is detected and ignored. A value of 1.5 is used here, but + // something larger may be more suitable. This change should resolve Bug#1271. + // + // TODO: There might be better places to update PhysicActor::mOnGround. + bool PhysicsSystem::isOnGround(const MWWorld::Ptr &actor) + { + Actor* physactor = getActor(actor); + if(!physactor) + return false; + if(physactor->getOnGround()) + return true; + else + { + osg::Vec3f pos(actor.getRefData().getPosition().asVec3()); + + ActorTracer tracer; + // a small distance above collision object is considered "on ground" + tracer.findGround(physactor, + pos, + pos - osg::Vec3f(0, 0, 1.5f), // trace a small amount down + mCollisionWorld); + if(tracer.mFraction < 1.0f) // collision, must be close to something below + { + physactor->setOnGround(true); + return true; + } + else + return false; + } + } + class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback { public: diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 7920347ad5..2defd7a507 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -104,6 +104,8 @@ namespace MWPhysics /// Return true if actor1 can see actor2. bool getLineOfSight(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2); + bool isOnGround (const MWWorld::Ptr& actor); + /// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will /// be overwritten. Valid until the next call to applyQueuedMovement. void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f4f960d97c..aa21ca7fba 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2022,44 +2022,9 @@ namespace MWWorld return pos.z < cell->getWaterLevel(); } - // physactor->getOnGround() is not a reliable indicator of whether the actor - // is on the ground (defaults to false, which means code blocks such as - // CharacterController::update() may falsely detect "falling"). - // - // Also, collisions can move z position slightly off zero, giving a false - // indication. In order to reduce false detection of jumping, small distance - // below the actor is detected and ignored. A value of 1.5 is used here, but - // something larger may be more suitable. This change should resolve Bug#1271. - // - // TODO: There might be better places to update PhysicActor::mOnGround. bool World::isOnGround(const MWWorld::Ptr &ptr) const { - MWPhysics::Actor* physactor = mPhysics->getActor(ptr); - - if(!physactor) - return false; - return physactor->getOnGround(); - /* - if(physactor->getOnGround()) - return true; - else - { - Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); - OEngine::Physic::ActorTracer tracer; - // a small distance above collision object is considered "on ground" - tracer.findGround(physactor, - pos, - pos - Ogre::Vector3(0, 0, 1.5f), // trace a small amount down - mPhysEngine); - if(tracer.mFraction < 1.0f) // collision, must be close to something below - { - physactor->setOnGround(true); - return true; - } - else - return false; - } - */ + return mPhysics->isOnGround(ptr); } void World::togglePOV()