1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-30 07:21:12 +00:00

Add pre-pass to collision trace function that traces over less distance if possible

This commit is contained in:
wareya 2021-10-22 23:11:23 -04:00
parent 1ffa02b2fd
commit e23b0edda4

View File

@ -12,31 +12,49 @@
namespace MWPhysics namespace MWPhysics
{ {
void ActorTracer::doTrace(const btCollisionObject *actor, const osg::Vec3f& start, const osg::Vec3f& end, const btCollisionWorld* world) ActorConvexCallback sweepHelper(const btCollisionObject *actor, const btVector3& from, const btVector3& to, const btCollisionWorld* world, bool actorFilter)
{ {
const btVector3 btstart = Misc::Convert::toBullet(start);
const btVector3 btend = Misc::Convert::toBullet(end);
const btTransform &trans = actor->getWorldTransform(); const btTransform &trans = actor->getWorldTransform();
btTransform from(trans); btTransform transFrom(trans);
btTransform to(trans); btTransform transTo(trans);
from.setOrigin(btstart); transFrom.setOrigin(from);
to.setOrigin(btend); transTo.setOrigin(to);
const btVector3 motion = btstart-btend; const btCollisionShape *shape = actor->getCollisionShape();
assert(shape->isConvex());
const btVector3 motion = from - to; // FIXME: this is backwards; means ActorConvexCallback is doing dot product tests backwards too
ActorConvexCallback newTraceCallback(actor, motion, btScalar(0.0), world); ActorConvexCallback newTraceCallback(actor, motion, btScalar(0.0), world);
// Inherit the actor's collision group and mask // Inherit the actor's collision group and mask
newTraceCallback.m_collisionFilterGroup = actor->getBroadphaseHandle()->m_collisionFilterGroup; newTraceCallback.m_collisionFilterGroup = actor->getBroadphaseHandle()->m_collisionFilterGroup;
newTraceCallback.m_collisionFilterMask = actor->getBroadphaseHandle()->m_collisionFilterMask; newTraceCallback.m_collisionFilterMask = actor->getBroadphaseHandle()->m_collisionFilterMask;
if(actorFilter)
newTraceCallback.m_collisionFilterMask &= ~CollisionType_Actor;
const btCollisionShape *shape = actor->getCollisionShape(); world->convexSweepTest(static_cast<const btConvexShape*>(shape), transFrom, transTo, newTraceCallback);
assert(shape->isConvex()); return newTraceCallback;
world->convexSweepTest(static_cast<const btConvexShape*>(shape), from, to, newTraceCallback); }
void ActorTracer::doTrace(const btCollisionObject *actor, const osg::Vec3f& start, const osg::Vec3f& end, const btCollisionWorld* world)
{
const btVector3 btstart = Misc::Convert::toBullet(start);
btVector3 btend = Misc::Convert::toBullet(end);
bool do_fallback = false;
if((btend-btstart).length2() > 5.0*5.0)
{
btend = btstart + (btend-btstart).normalized()*5.0;
do_fallback = true;
}
auto newTraceCallback = sweepHelper(actor, btstart, btend, world, false);
// Copy the hit data over to our trace results struct: // Copy the hit data over to our trace results struct:
if(newTraceCallback.hasHit()) if(newTraceCallback.hasHit())
{ {
mFraction = newTraceCallback.m_closestHitFraction; mFraction = newTraceCallback.m_closestHitFraction;
if((end-start).length2() > 0.0)
mFraction *= (btend-btstart).length() / (end-start).length();
mPlaneNormal = Misc::Convert::toOsg(newTraceCallback.m_hitNormalWorld); mPlaneNormal = Misc::Convert::toOsg(newTraceCallback.m_hitNormalWorld);
mEndPos = (end-start)*mFraction + start; mEndPos = (end-start)*mFraction + start;
mHitPoint = Misc::Convert::toOsg(newTraceCallback.m_hitPointWorld); mHitPoint = Misc::Convert::toOsg(newTraceCallback.m_hitPointWorld);
@ -44,6 +62,22 @@ void ActorTracer::doTrace(const btCollisionObject *actor, const osg::Vec3f& star
} }
else else
{ {
if(do_fallback)
{
btend = Misc::Convert::toBullet(end);
auto newTraceCallback = sweepHelper(actor, btstart, btend, world, false);
if(newTraceCallback.hasHit())
{
mFraction = newTraceCallback.m_closestHitFraction;
mPlaneNormal = Misc::Convert::toOsg(newTraceCallback.m_hitNormalWorld);
mEndPos = (end-start)*mFraction + start;
mHitPoint = Misc::Convert::toOsg(newTraceCallback.m_hitPointWorld);
mHitObject = newTraceCallback.m_hitCollisionObject;
return;
}
}
// fallthrough
mEndPos = end; mEndPos = end;
mPlaneNormal = osg::Vec3f(0.0f, 0.0f, 1.0f); mPlaneNormal = osg::Vec3f(0.0f, 0.0f, 1.0f);
mFraction = 1.0f; mFraction = 1.0f;
@ -54,21 +88,7 @@ void ActorTracer::doTrace(const btCollisionObject *actor, const osg::Vec3f& star
void ActorTracer::findGround(const Actor* actor, const osg::Vec3f& start, const osg::Vec3f& end, const btCollisionWorld* world) void ActorTracer::findGround(const Actor* actor, const osg::Vec3f& start, const osg::Vec3f& end, const btCollisionWorld* world)
{ {
const btVector3 btstart = Misc::Convert::toBullet(start); auto newTraceCallback = sweepHelper(actor->getCollisionObject(), Misc::Convert::toBullet(start), Misc::Convert::toBullet(end), world, true);
const btVector3 btend = Misc::Convert::toBullet(end);
const btTransform &trans = actor->getCollisionObject()->getWorldTransform();
btTransform from(trans.getBasis(), btstart);
btTransform to(trans.getBasis(), btend);
const btVector3 motion = btstart-btend;
ActorConvexCallback newTraceCallback(actor->getCollisionObject(), motion, btScalar(0.0), world);
// Inherit the actor's collision group and mask
newTraceCallback.m_collisionFilterGroup = actor->getCollisionObject()->getBroadphaseHandle()->m_collisionFilterGroup;
newTraceCallback.m_collisionFilterMask = actor->getCollisionObject()->getBroadphaseHandle()->m_collisionFilterMask;
newTraceCallback.m_collisionFilterMask &= ~CollisionType_Actor;
world->convexSweepTest(actor->getConvexShape(), from, to, newTraceCallback);
if(newTraceCallback.hasHit()) if(newTraceCallback.hasHit())
{ {
mFraction = newTraceCallback.m_closestHitFraction; mFraction = newTraceCallback.m_closestHitFraction;