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)
openmw-38
scrawl 9 years ago
parent 9fce428929
commit a49058721e

@ -234,9 +234,8 @@ namespace MWPhysics
} }
static osg::Vec3f move(const MWWorld::Ptr &ptr, Actor* physicActor, const osg::Vec3f &movement, float time, static osg::Vec3f move(const MWWorld::Ptr &ptr, Actor* physicActor, const osg::Vec3f &movement, float time,
bool isFlying, float waterlevel, float slowFall, btCollisionWorld* collisionWorld bool isFlying, float waterlevel, float slowFall, btCollisionWorld* collisionWorld,
, std::map<MWWorld::Ptr, MWWorld::Ptr>& collisionTracker std::map<MWWorld::Ptr, MWWorld::Ptr>& standingCollisionTracker)
, std::map<MWWorld::Ptr, MWWorld::Ptr>& standingCollisionTracker)
{ {
const ESM::Position& refpos = ptr.getRefData().getPosition(); const ESM::Position& refpos = ptr.getRefData().getPosition();
osg::Vec3f position(refpos.asVec3()); osg::Vec3f position(refpos.asVec3());
@ -345,13 +344,6 @@ namespace MWPhysics
newPosition = tracer.mEndPos; // ok to move, so set newPosition newPosition = tracer.mEndPos; // ok to move, so set newPosition
break; break;
} }
else
{
const btCollisionObject* standingOn = tracer.mHitObject;
const PtrHolder* ptrHolder = static_cast<const PtrHolder*>(standingOn->getUserPointer());
if (ptrHolder)
collisionTracker[ptr] = ptrHolder->getPtr();
}
} }
else else
{ {
@ -968,11 +960,11 @@ namespace MWPhysics
} }
}; };
std::vector<MWWorld::Ptr> PhysicsSystem::getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask) std::vector<MWWorld::Ptr> PhysicsSystem::getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask) const
{ {
btCollisionObject* me = NULL; btCollisionObject* me = NULL;
ObjectMap::iterator found = mObjects.find(ptr); ObjectMap::const_iterator found = mObjects.find(ptr);
if (found != mObjects.end()) if (found != mObjects.end())
me = found->second->getCollisionObject(); me = found->second->getCollisionObject();
else else
@ -1081,7 +1073,6 @@ namespace MWPhysics
mActors.insert(std::make_pair(updated, actor)); mActors.insert(std::make_pair(updated, actor));
} }
updateCollisionMapPtr(mCollisions, old, updated);
updateCollisionMapPtr(mStandingCollisions, old, updated); updateCollisionMapPtr(mStandingCollisions, old, updated);
} }
@ -1197,7 +1188,6 @@ namespace MWPhysics
void PhysicsSystem::clearQueuedMovement() void PhysicsSystem::clearQueuedMovement()
{ {
mMovementQueue.clear(); mMovementQueue.clear();
mCollisions.clear();
mStandingCollisions.clear(); mStandingCollisions.clear();
} }
@ -1209,7 +1199,6 @@ namespace MWPhysics
if(mTimeAccum >= 1.0f/60.0f) if(mTimeAccum >= 1.0f/60.0f)
{ {
// Collision events should be available on every frame // Collision events should be available on every frame
mCollisions.clear();
mStandingCollisions.clear(); mStandingCollisions.clear();
const MWBase::World *world = MWBase::Environment::get().getWorld(); 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, osg::Vec3f newpos = MovementSolver::move(iter->first, physicActor, iter->second, mTimeAccum,
world->isFlying(iter->first), world->isFlying(iter->first),
waterlevel, slowFall, mCollisionWorld, mCollisions, mStandingCollisions); waterlevel, slowFall, mCollisionWorld, mStandingCollisions);
float heightDiff = newpos.z() - oldHeight; float heightDiff = newpos.z() - oldHeight;
@ -1296,21 +1285,14 @@ namespace MWPhysics
bool PhysicsSystem::isActorCollidingWith(const MWWorld::Ptr &actor, const MWWorld::Ptr &object) const bool PhysicsSystem::isActorCollidingWith(const MWWorld::Ptr &actor, const MWWorld::Ptr &object) const
{ {
for (CollisionMap::const_iterator it = mCollisions.begin(); it != mCollisions.end(); ++it) std::vector<MWWorld::Ptr> collisions = getCollisions(object, CollisionType_World, CollisionType_Actor);
{ return (std::find(collisions.begin(), collisions.end(), actor) != collisions.end());
if (it->first == actor && it->second == object)
return true;
}
return false;
} }
void PhysicsSystem::getActorsCollidingWith(const MWWorld::Ptr &object, std::vector<MWWorld::Ptr> &out) const void PhysicsSystem::getActorsCollidingWith(const MWWorld::Ptr &object, std::vector<MWWorld::Ptr> &out) const
{ {
for (CollisionMap::const_iterator it = mCollisions.begin(); it != mCollisions.end(); ++it) std::vector<MWWorld::Ptr> collisions = getCollisions(object, CollisionType_World, CollisionType_Actor);
{ out.insert(out.end(), collisions.begin(), collisions.end());
if (it->second == object)
out.push_back(it->first);
}
} }
void PhysicsSystem::disableWater() void PhysicsSystem::disableWater()

@ -81,7 +81,7 @@ namespace MWPhysics
void stepSimulation(float dt); void stepSimulation(float dt);
void debugDraw(); void debugDraw();
std::vector<MWWorld::Ptr> getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask); ///< get handles this object collides with std::vector<MWWorld::Ptr> 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); osg::Vec3f traceDown(const MWWorld::Ptr &ptr, float maxHeight);
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor, std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor,
@ -174,11 +174,9 @@ namespace MWPhysics
bool mDebugDrawEnabled; bool mDebugDrawEnabled;
// Tracks all movement collisions happening during a single frame. <actor handle, collided handle> // Tracks standing collisions happening during a single frame. <actor handle, collided handle>
// This will detect e.g. running against a vertical wall. It will not detect climbing up stairs, // This will detect standing on an object, but won't detect running e.g. against a wall.
// stepping up small objects, etc.
typedef std::map<MWWorld::Ptr, MWWorld::Ptr> CollisionMap; typedef std::map<MWWorld::Ptr, MWWorld::Ptr> CollisionMap;
CollisionMap mCollisions;
CollisionMap mStandingCollisions; CollisionMap mStandingCollisions;
// replaces all occurences of 'old' in the map by 'updated', no matter if its a key or value // replaces all occurences of 'old' in the map by 'updated', no matter if its a key or value

Loading…
Cancel
Save