From fb5ef95a5bbf8eaa4c5bb03dea3e9bf526a3ba4e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 29 Jan 2019 11:00:18 -0800 Subject: [PATCH 1/2] disable bf triangle collisions for flying MyAvatar --- interface/src/Application.cpp | 2 ++ libraries/physics/src/PhysicsEngine.cpp | 27 +++++++++++++++++++++++++ libraries/physics/src/PhysicsEngine.h | 2 ++ 3 files changed, 31 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 356065a9bb..135ada6312 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6289,6 +6289,8 @@ void Application::update(float deltaTime) { avatarManager->handleProcessedPhysicsTransaction(transaction); myAvatar->prepareForPhysicsSimulation(); + _physicsEngine->enableGlobalContactAddedCallback(myAvatar->isFlying()); + _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) { dynamic->prepareForPhysicsSimulation(); }); diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index bf6e2463e5..deaad81296 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -27,6 +27,23 @@ #include "ThreadSafeDynamicsWorld.h" #include "PhysicsLogging.h" +static bool flipNormalsMyAvatarVsBackfacingTriangles(btManifoldPoint& cp, + const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, + const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1) { + if (colObj1Wrap->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE) { + auto triShape = static_cast(colObj1Wrap->getCollisionShape()); + const btVector3* v = triShape->m_vertices1; + btVector3 faceNormal = colObj1Wrap->getWorldTransform().getBasis() * btCross(v[1] - v[0], v[2] - v[0]); + float nDotF = btDot(faceNormal, cp.m_normalWorldOnB); + if (nDotF <= 0.0f) { + faceNormal.normalize(); + // flip the contact normal to be aligned with the face normal + cp.m_normalWorldOnB += -2.0f * nDotF * faceNormal; + } + } + // return value is currently ignored but to be future-proof: return false when not modifying friction + return false; +} PhysicsEngine::PhysicsEngine(const glm::vec3& offset) : _originOffset(offset), @@ -904,6 +921,16 @@ void PhysicsEngine::setShowBulletConstraintLimits(bool value) { } } +void PhysicsEngine::enableGlobalContactAddedCallback(bool enabled) { + if (enabled) { + // register contact filter to help MyAvatar pass through backfacing triangles + gContactAddedCallback = flipNormalsMyAvatarVsBackfacingTriangles; + } else { + // deregister contact filter + gContactAddedCallback = nullptr; + } +} + struct AllContactsCallback : public btCollisionWorld::ContactResultCallback { AllContactsCallback(int32_t mask, int32_t group, const ShapeInfo& shapeInfo, const Transform& transform, btCollisionObject* myAvatarCollisionObject, float threshold) : btCollisionWorld::ContactResultCallback(), diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index d10be018b8..43cc0d2176 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -148,6 +148,8 @@ public: // See PhysicsCollisionGroups.h for mask flags. std::vector contactTest(uint16_t mask, const ShapeInfo& regionShapeInfo, const Transform& regionTransform, uint16_t group = USER_COLLISION_GROUP_DYNAMIC, float threshold = 0.0f) const; + void enableGlobalContactAddedCallback(bool enabled); + private: QList removeDynamicsForBody(btRigidBody* body); void addObjectToDynamicsWorld(ObjectMotionState* motionState); From e372cb668ad19068d480c6d923e93f03cc336d46 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 29 Jan 2019 11:11:54 -0800 Subject: [PATCH 2/2] enable CCD for MyAvatar's RigidBody --- libraries/physics/src/CharacterController.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index d5ded6f909..2eceb226c9 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -124,6 +124,11 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) { _rigidBody->setGravity(_currentGravity * _currentUp); // set flag to enable custom contactAddedCallback _rigidBody->setCollisionFlags(btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + + // enable CCD + _rigidBody->setCcdSweptSphereRadius(_radius); + _rigidBody->setCcdMotionThreshold(_radius); + btCollisionShape* shape = _rigidBody->getCollisionShape(); assert(shape && shape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE); _ghost.setCharacterShape(static_cast(shape)); @@ -454,6 +459,12 @@ void CharacterController::setLocalBoundingBox(const glm::vec3& minCorner, const // it's ok to change offset immediately -- there are no thread safety issues here _shapeLocalOffset = minCorner + 0.5f * scale; + + if (_rigidBody) { + // update CCD with new _radius + _rigidBody->setCcdSweptSphereRadius(_radius); + _rigidBody->setCcdMotionThreshold(_radius); + } } void CharacterController::setCollisionless(bool collisionless) {