From 0a883f3832b2b446ec8fa202efe1f2847a885e63 Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 20 Jun 2016 15:10:58 +1000 Subject: [PATCH 1/4] First try to fix #2522 (soccer ball pushed in air). Needs to be tested, and puck still needs to be done. --- .../CollisionDispatch/SphereTriangleDetector.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp index 23a5c7526..98c6188b7 100644 --- a/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp +++ b/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -152,8 +152,9 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &po if (distanceSqr>SIMD_EPSILON) { btScalar distance = btSqrt(distanceSqr); - resultNormal = contactToCentre; - resultNormal.normalize(); + //resultNormal = contactToCentre; + //resultNormal.normalize(); + resultNormal = normal; point = contactPoint; depth = -(radius-distance); } else From 7a95f10cc01c80601235023c6b780dab8423cd51 Mon Sep 17 00:00:00 2001 From: hiker Date: Tue, 21 Jun 2016 09:32:14 +1000 Subject: [PATCH 2/4] Try to fix #2522 for a puck. --- .../btGjkPairDetector.cpp | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/lib/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp index 8af16b9cf..3dcf58515 100644 --- a/lib/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp +++ b/lib/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -17,6 +17,10 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btConvexShape.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" #include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" @@ -441,6 +445,32 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu m_cachedSeparatingAxis = normalInB; m_cachedSeparatingDistance = distance; + // In some cases the normalInB is incorrect with a static triangle + // mesh (i.e. it's the connection point between puck and triangle, not + // the normal from the triangle - which is fine if the triangle mesh + // is a dynamic rigid body (i.e. can be pushed away), but appears to + // be wrong in case of a static body - it causes #2522 (puck suddenly + // pushed in air). So in case of a static triangle mesh, recompute + // the normal just based on the triangle mesh: + const btManifoldResult *mani = dynamic_cast(&output); + if(mani) + { + // Find the triangle: + const btCollisionObject *b = mani->getBody0Internal(); + const btTriangleShape *tri = dynamic_cast(b->getCollisionShape()); + if(!tri) + { + b = mani->getBody1Internal(); + tri = dynamic_cast(b->getCollisionShape()); + } + // If we have a triangle and it is static (mass=0), recompute the normal + if(tri && btRigidBody::upcast(b)->getInvMass()==0) + { + normalInB = (tri->m_vertices1[1]-tri->m_vertices1[0]) + .cross(tri->m_vertices1[2]-tri->m_vertices1[0]); + normalInB.normalize();; + } + } output.addContactPoint( normalInB, pointOnB+positionOffset, From 0eb4ca2abd18b00115c8449681d0643931ae18ec Mon Sep 17 00:00:00 2001 From: hiker Date: Tue, 21 Jun 2016 09:53:51 +1000 Subject: [PATCH 3/4] Fix #2522 in case of a sphere, and apply this fix only in case of a static body to reduce potential incorrect side effects. --- .../SphereTriangleDetector.cpp | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp index 98c6188b7..60187b106 100644 --- a/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp +++ b/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -17,6 +17,10 @@ subject to the following restrictions: #include "SphereTriangleDetector.h" #include "BulletCollision/CollisionShapes/btTriangleShape.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold) @@ -43,6 +47,35 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold)) { + + // In some cases the normalInB is incorrect with a static triangle + // mesh (i.e. it's the connection point between puck and triangle, not + // the normal from the triangle - which is fine if the triangle mesh + // is a dynamic rigid body (i.e. can be pushed away), but appears to + // be wrong in case of a static body - it causes #2522 (puck suddenly + // pushed in air). So in case of a static triangle mesh, recompute + // the normal just based on the triangle mesh: + const btManifoldResult *mani = dynamic_cast(&output); + if(mani) + { + // Find the triangle: + const btCollisionObject *b = mani->getBody0Internal(); + const btTriangleShape *tri = dynamic_cast(b->getCollisionShape()); + if(!tri) + { + b = mani->getBody1Internal(); + tri = dynamic_cast(b->getCollisionShape()); + } + // If we have a triangle and it is static (mass=0), recompute the normal + if(tri && btRigidBody::upcast(b)->getInvMass()==0) + { + normal = (tri->m_vertices1[1]-tri->m_vertices1[0]) + .cross(tri->m_vertices1[2]-tri->m_vertices1[0]); + normal.normalize();; + } + } + + if (swapResults) { btVector3 normalOnB = transformB.getBasis()*normal; @@ -152,9 +185,8 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &po if (distanceSqr>SIMD_EPSILON) { btScalar distance = btSqrt(distanceSqr); - //resultNormal = contactToCentre; - //resultNormal.normalize(); - resultNormal = normal; + resultNormal = contactToCentre; + resultNormal.normalize(); point = contactPoint; depth = -(radius-distance); } else From 431ed63da2e1eedf47fc8b53755d6a21f163c8c7 Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 27 Jun 2016 07:48:30 +1000 Subject: [PATCH 4/4] Improved fix for 2522 by using isStaticOrKinematicObject() function (instead of accessing the rigid body). This separates collision and dynamic handling of bullet again. --- .../CollisionDispatch/SphereTriangleDetector.cpp | 13 ++++++------- .../NarrowPhaseCollision/btGjkPairDetector.cpp | 13 ++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp index 60187b106..9a3a58592 100644 --- a/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp +++ b/lib/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -20,7 +20,6 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionDispatch/btManifoldResult.h" #include "BulletCollision/CollisionShapes/btTriangleShape.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold) @@ -59,15 +58,15 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res if(mani) { // Find the triangle: - const btCollisionObject *b = mani->getBody0Internal(); - const btTriangleShape *tri = dynamic_cast(b->getCollisionShape()); + const btCollisionObject *co = mani->getBody0Internal(); + const btTriangleShape *tri = dynamic_cast(co->getCollisionShape()); if(!tri) { - b = mani->getBody1Internal(); - tri = dynamic_cast(b->getCollisionShape()); + co = mani->getBody1Internal(); + tri = dynamic_cast(co->getCollisionShape()); } - // If we have a triangle and it is static (mass=0), recompute the normal - if(tri && btRigidBody::upcast(b)->getInvMass()==0) + // If we have a triangle and it is static, recompute the normal + if(tri && co->isStaticOrKinematicObject()) { normal = (tri->m_vertices1[1]-tri->m_vertices1[0]) .cross(tri->m_vertices1[2]-tri->m_vertices1[0]); diff --git a/lib/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/lib/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp index 3dcf58515..5f7552a11 100644 --- a/lib/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp +++ b/lib/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -20,7 +20,6 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btManifoldResult.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btTriangleShape.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" @@ -456,15 +455,15 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu if(mani) { // Find the triangle: - const btCollisionObject *b = mani->getBody0Internal(); - const btTriangleShape *tri = dynamic_cast(b->getCollisionShape()); + const btCollisionObject *co = mani->getBody0Internal(); + const btTriangleShape *tri = dynamic_cast(co->getCollisionShape()); if(!tri) { - b = mani->getBody1Internal(); - tri = dynamic_cast(b->getCollisionShape()); + co = mani->getBody1Internal(); + tri = dynamic_cast(co->getCollisionShape()); } - // If we have a triangle and it is static (mass=0), recompute the normal - if(tri && btRigidBody::upcast(b)->getInvMass()==0) + // If we have a triangle and it is static, recompute the normal + if(tri && co->isStaticOrKinematicObject()) { normalInB = (tri->m_vertices1[1]-tri->m_vertices1[0]) .cross(tri->m_vertices1[2]-tri->m_vertices1[0]);