From 0bef75487366b786c3db147181ea009f8649b86b Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 13 Apr 2014 08:46:02 +1000 Subject: [PATCH 1/4] Fix jumping animation glitches caused by minor vertical movements. Should resolve Bug #1271. --- apps/openmw/mwmechanics/character.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 93c789af1a..b7d99adeca 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1090,7 +1090,13 @@ void CharacterController::update(float duration) if (inwater || flying) cls.getCreatureStats(mPtr).land(); - if(!onground && !flying && !inwater) + // FIXME: The check for vec.z is a hack, but onground is not a reliable + // indicator of whether the actor is on the ground (defaults to false, which + // means this code block will always execute at least once for most, and + // collisions can move z position slightly off zero). A very small value of + // 0.1 is used here, but maybe something larger like 10 should be used. + // Should resolve Bug#1271. + if(!onground && !flying && !inwater && vec.z > 0.1f) { // In the air (either getting up —ascending part of jump— or falling). From e9be6d3f42fa89ef52ca3393e46db66d833e9b0d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 13 Apr 2014 11:34:59 +1000 Subject: [PATCH 2/4] Fix falling animation where vec.z is set to zero. --- apps/openmw/mwmechanics/character.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index b7d99adeca..d34812417d 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1090,13 +1090,14 @@ void CharacterController::update(float duration) if (inwater || flying) cls.getCreatureStats(mPtr).land(); - // FIXME: The check for vec.z is a hack, but onground is not a reliable - // indicator of whether the actor is on the ground (defaults to false, which - // means this code block will always execute at least once for most, and - // collisions can move z position slightly off zero). A very small value of - // 0.1 is used here, but maybe something larger like 10 should be used. - // Should resolve Bug#1271. - if(!onground && !flying && !inwater && vec.z > 0.1f) + if(!onground && !flying && !inwater + // FIXME: The check for vec.z is a hack, but onground is not a reliable + // indicator of whether the actor is on the ground (defaults to false, which + // means this code block will always execute at least once for most actors, + // and collisions can move z position slightly off zero). A very small value + // of 0.1 is used here, but something larger like 10 may be more suitable. + // Should resolve Bug#1271. + && (mJumpState == JumpState_Falling || vec.z > 0.1f)) { // In the air (either getting up —ascending part of jump— or falling). From 3e6e325e5b44e199b84ffa417765480d717962bc Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 13 Apr 2014 14:53:36 +1000 Subject: [PATCH 3/4] Instead of hacking character.cpp, provide a more reliable check for world->isOnGround(mPtr). --- apps/openmw/mwmechanics/character.cpp | 9 +-------- apps/openmw/mwworld/worldimp.cpp | 29 ++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index d34812417d..93c789af1a 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1090,14 +1090,7 @@ void CharacterController::update(float duration) if (inwater || flying) cls.getCreatureStats(mPtr).land(); - if(!onground && !flying && !inwater - // FIXME: The check for vec.z is a hack, but onground is not a reliable - // indicator of whether the actor is on the ground (defaults to false, which - // means this code block will always execute at least once for most actors, - // and collisions can move z position slightly off zero). A very small value - // of 0.1 is used here, but something larger like 10 may be more suitable. - // Should resolve Bug#1271. - && (mJumpState == JumpState_Falling || vec.z > 0.1f)) + if(!onground && !flying && !inwater) { // In the air (either getting up —ascending part of jump— or falling). diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f808856c55..83299e126b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -9,6 +9,7 @@ #include +#include #include #include @@ -1711,11 +1712,37 @@ 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. + // + // FIXME: Collision detection each time may have a performance impact. + // There might be better places to update PhysicActor::mOnGround. bool World::isOnGround(const MWWorld::Ptr &ptr) const { RefData &refdata = ptr.getRefData(); const OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle()); - return physactor && physactor->getOnGround(); + if(physactor) + { + Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); + OEngine::Physic::ActorTracer tracer; + // a small distance above collision object is considered "on ground" + tracer.findGround(physactor->getCollisionBody(), + 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 + return true; // TODO: should update physactor + else + return physactor->getOnGround(); + } + else + return false; } bool World::vanityRotateCamera(float * rot) From 966ed468701799429663edc2d7bb1abc3a4618ae Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 13 Apr 2014 18:34:08 +1000 Subject: [PATCH 4/4] Better performance but less tolerant of collision induced glitches. Also had to use const_cast to cache on ground status. --- apps/openmw/mwworld/worldimp.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 83299e126b..d56ca1f160 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1721,13 +1721,18 @@ namespace MWWorld // 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. // - // FIXME: Collision detection each time may have a performance impact. - // There might be better places to update PhysicActor::mOnGround. + // TODO: There might be better places to update PhysicActor::mOnGround. bool World::isOnGround(const MWWorld::Ptr &ptr) const { RefData &refdata = ptr.getRefData(); const OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle()); - if(physactor) + + if(!physactor) + return false; + + if(physactor->getOnGround()) + return true; + else { Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); OEngine::Physic::ActorTracer tracer; @@ -1737,12 +1742,13 @@ namespace MWWorld 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 - return true; // TODO: should update physactor + { + const_cast (physactor)->setOnGround(true); + return true; + } else - return physactor->getOnGround(); + return false; } - else - return false; } bool World::vanityRotateCamera(float * rot)