From 917132e326447b5bd242e7b53c1004df23f74ee3 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 7 May 2023 20:41:11 +0200 Subject: [PATCH] Replace `rayTest` with `convexSweepTest` `MovementSolver::traceDown`. Needed to prevent teleporting down through sewer grates. --- apps/openmw/mwphysics/movementsolver.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwphysics/movementsolver.cpp b/apps/openmw/mwphysics/movementsolver.cpp index 8ba9f44c73..553c1292e5 100644 --- a/apps/openmw/mwphysics/movementsolver.cpp +++ b/apps/openmw/mwphysics/movementsolver.cpp @@ -98,21 +98,27 @@ namespace MWPhysics // Check if we actually found a valid spawn point (use an infinitely thin ray this time). // Required for some broken door destinations in Morrowind.esm, where the spawn point // intersects with other geometry if the actor's base is taken into account - btVector3 from = Misc::Convert::toBullet(position); + btVector3 from = Misc::Convert::toBullet(position + offset); btVector3 to = from - btVector3(0, 0, maxHeight); - btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); + btCollisionWorld::ClosestConvexResultCallback resultCallback1(from, to); resultCallback1.m_collisionFilterGroup = CollisionType_AnyPhysical; resultCallback1.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap; - collisionWorld->rayTest(from, to, resultCallback1); + const btQuaternion btrot = btQuaternion::getIdentity(); + collisionWorld->convexSweepTest( + actor->getConvexShape(), btTransform(btrot, from), btTransform(btrot, to), resultCallback1); if (resultCallback1.hasHit() && ((Misc::Convert::toOsg(resultCallback1.m_hitPointWorld) - tracer.mEndPos + offset).length2() > 35 * 35 || !isWalkableSlope(tracer.mPlaneNormal))) { actor->setOnSlope(!isWalkableSlope(resultCallback1.m_hitNormalWorld)); - return Misc::Convert::toOsg(resultCallback1.m_hitPointWorld) + osg::Vec3f(0.f, 0.f, sGroundOffset); + osg::Vec3f res = Misc::Convert::toOsg(resultCallback1.m_hitPointWorld); + res.x() = position.x(); + res.y() = position.y(); + res.z() += sGroundOffset; + return res; } actor->setOnSlope(!isWalkableSlope(tracer.mPlaneNormal));