From a49058721e4c6dedb2e19c89f508f38c290a6422 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 18 Nov 2015 21:20:12 +0100 Subject: [PATCH] Use a contactTest for collision script functions The previous method didn't work for stationary actors. This change fixes the grinder in "Sotha Sil, Dome of Kasia" not registering collisions if the player stands still. (Fixes #1934) --- apps/openmw/mwphysics/physicssystem.cpp | 36 +++++++------------------ apps/openmw/mwphysics/physicssystem.hpp | 8 +++--- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 5d8fa2da2..5734f4827 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -234,9 +234,8 @@ namespace MWPhysics } static osg::Vec3f move(const MWWorld::Ptr &ptr, Actor* physicActor, const osg::Vec3f &movement, float time, - bool isFlying, float waterlevel, float slowFall, btCollisionWorld* collisionWorld - , std::map& collisionTracker - , std::map& standingCollisionTracker) + bool isFlying, float waterlevel, float slowFall, btCollisionWorld* collisionWorld, + std::map& standingCollisionTracker) { const ESM::Position& refpos = ptr.getRefData().getPosition(); osg::Vec3f position(refpos.asVec3()); @@ -345,13 +344,6 @@ namespace MWPhysics newPosition = tracer.mEndPos; // ok to move, so set newPosition break; } - else - { - const btCollisionObject* standingOn = tracer.mHitObject; - const PtrHolder* ptrHolder = static_cast(standingOn->getUserPointer()); - if (ptrHolder) - collisionTracker[ptr] = ptrHolder->getPtr(); - } } else { @@ -968,11 +960,11 @@ namespace MWPhysics } }; - std::vector PhysicsSystem::getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask) + std::vector PhysicsSystem::getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask) const { btCollisionObject* me = NULL; - ObjectMap::iterator found = mObjects.find(ptr); + ObjectMap::const_iterator found = mObjects.find(ptr); if (found != mObjects.end()) me = found->second->getCollisionObject(); else @@ -1081,7 +1073,6 @@ namespace MWPhysics mActors.insert(std::make_pair(updated, actor)); } - updateCollisionMapPtr(mCollisions, old, updated); updateCollisionMapPtr(mStandingCollisions, old, updated); } @@ -1197,7 +1188,6 @@ namespace MWPhysics void PhysicsSystem::clearQueuedMovement() { mMovementQueue.clear(); - mCollisions.clear(); mStandingCollisions.clear(); } @@ -1209,7 +1199,6 @@ namespace MWPhysics if(mTimeAccum >= 1.0f/60.0f) { // Collision events should be available on every frame - mCollisions.clear(); mStandingCollisions.clear(); const MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1243,7 +1232,7 @@ namespace MWPhysics osg::Vec3f newpos = MovementSolver::move(iter->first, physicActor, iter->second, mTimeAccum, world->isFlying(iter->first), - waterlevel, slowFall, mCollisionWorld, mCollisions, mStandingCollisions); + waterlevel, slowFall, mCollisionWorld, mStandingCollisions); float heightDiff = newpos.z() - oldHeight; @@ -1296,21 +1285,14 @@ namespace MWPhysics bool PhysicsSystem::isActorCollidingWith(const MWWorld::Ptr &actor, const MWWorld::Ptr &object) const { - for (CollisionMap::const_iterator it = mCollisions.begin(); it != mCollisions.end(); ++it) - { - if (it->first == actor && it->second == object) - return true; - } - return false; + std::vector collisions = getCollisions(object, CollisionType_World, CollisionType_Actor); + return (std::find(collisions.begin(), collisions.end(), actor) != collisions.end()); } void PhysicsSystem::getActorsCollidingWith(const MWWorld::Ptr &object, std::vector &out) const { - for (CollisionMap::const_iterator it = mCollisions.begin(); it != mCollisions.end(); ++it) - { - if (it->second == object) - out.push_back(it->first); - } + std::vector collisions = getCollisions(object, CollisionType_World, CollisionType_Actor); + out.insert(out.end(), collisions.begin(), collisions.end()); } void PhysicsSystem::disableWater() diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index a045638ef..1ccfb21cd 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -81,7 +81,7 @@ namespace MWPhysics void stepSimulation(float dt); void debugDraw(); - std::vector getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask); ///< get handles this object collides with + std::vector getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask) const; ///< get handles this object collides with osg::Vec3f traceDown(const MWWorld::Ptr &ptr, float maxHeight); std::pair getHitContact(const MWWorld::Ptr& actor, @@ -174,11 +174,9 @@ namespace MWPhysics bool mDebugDrawEnabled; - // Tracks all movement collisions happening during a single frame. - // This will detect e.g. running against a vertical wall. It will not detect climbing up stairs, - // stepping up small objects, etc. + // Tracks standing collisions happening during a single frame. + // This will detect standing on an object, but won't detect running e.g. against a wall. typedef std::map CollisionMap; - CollisionMap mCollisions; CollisionMap mStandingCollisions; // replaces all occurences of 'old' in the map by 'updated', no matter if its a key or value