remove speculative contacts, they break restitution and cause other artifacts
use btConvexPolyhedron for debug rendering, if available fixes in btConvexConvexAlgorithm for polyhedral contact clipping, if GJK separating normal is zero don't shift vertices in btPolyhedralConvexShape
This commit is contained in:
@@ -35,7 +35,7 @@ subject to the following restrictions:
|
||||
#include "BulletCollision/CollisionShapes/btUniformScalingShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
|
||||
|
||||
#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
|
||||
|
||||
///
|
||||
#include "BulletCollision/CollisionShapes/btShapeHull.h"
|
||||
@@ -729,43 +729,41 @@ void GL_ShapeDrawer::drawOpenGL(btScalar* m, const btCollisionShape* shape, cons
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
|
||||
if (shape->isConvex())
|
||||
{
|
||||
ShapeCache* sc=cache((btConvexShape*)shape);
|
||||
#if 0
|
||||
btConvexShape* convexShape = (btConvexShape*)shape;
|
||||
if (!shape->getUserPointer())
|
||||
const btConvexPolyhedron* poly = shape->isPolyhedral() ? ((btPolyhedralConvexShape*) shape)->getConvexPolyhedron() : 0;
|
||||
if (poly)
|
||||
{
|
||||
int i;
|
||||
glBegin (GL_TRIANGLES);
|
||||
for (i=0;i<poly->m_faces.size();i++)
|
||||
{
|
||||
btVector3 centroid(0,0,0);
|
||||
int numVerts = poly->m_faces[i].m_indices.size();
|
||||
if (numVerts>2)
|
||||
{
|
||||
btVector3 v1 = poly->m_vertices[poly->m_faces[i].m_indices[0]];
|
||||
for (int v=0;v<poly->m_faces[i].m_indices.size()-2;v++)
|
||||
{
|
||||
//create a hull approximation
|
||||
void* mem = btAlignedAlloc(sizeof(btShapeHull),16);
|
||||
btShapeHull* hull = new(mem) btShapeHull(convexShape);
|
||||
|
||||
///cleanup memory
|
||||
m_shapeHulls.push_back(hull);
|
||||
|
||||
btScalar margin = shape->getMargin();
|
||||
hull->buildHull(margin);
|
||||
convexShape->setUserPointer(hull);
|
||||
|
||||
|
||||
// printf("numTriangles = %d\n", hull->numTriangles ());
|
||||
// printf("numIndices = %d\n", hull->numIndices ());
|
||||
// printf("numVertices = %d\n", hull->numVertices ());
|
||||
|
||||
|
||||
btVector3 v2 = poly->m_vertices[poly->m_faces[i].m_indices[v+1]];
|
||||
btVector3 v3 = poly->m_vertices[poly->m_faces[i].m_indices[v+2]];
|
||||
btVector3 normal = (v3-v1).cross(v2-v1);
|
||||
normal.normalize ();
|
||||
glNormal3f(normal.getX(),normal.getY(),normal.getZ());
|
||||
glVertex3f (v1.x(), v1.y(), v1.z());
|
||||
glVertex3f (v2.x(), v2.y(), v2.z());
|
||||
glVertex3f (v3.x(), v3.y(), v3.z());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//if (shape->getUserPointer())
|
||||
}
|
||||
}
|
||||
glEnd ();
|
||||
} else
|
||||
{
|
||||
ShapeCache* sc=cache((btConvexShape*)shape);
|
||||
//glutSolidCube(1.0);
|
||||
btShapeHull* hull = &sc->m_shapehull/*(btShapeHull*)shape->getUserPointer()*/;
|
||||
|
||||
|
||||
if (hull->numTriangles () > 0)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
@@ -441,7 +441,10 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
|
||||
//gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
|
||||
gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
|
||||
#endif //ZERO_MARGIN
|
||||
sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
|
||||
btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
|
||||
if (l2>SIMD_EPSILON)
|
||||
{
|
||||
sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
|
||||
//minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance();
|
||||
minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin();
|
||||
|
||||
@@ -451,6 +454,7 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
|
||||
foundSepAxis = gjkPairDetector.getCachedSeparatingDistance()<(min0->getMargin()+min1->getMargin());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (foundSepAxis)
|
||||
{
|
||||
// printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
|
||||
@@ -486,7 +490,7 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
|
||||
btScalar minDist =-1e30f;
|
||||
btScalar maxDist = threshold;
|
||||
|
||||
bool foundSepAxis = true;
|
||||
bool foundSepAxis = false;
|
||||
if (0)
|
||||
{
|
||||
polyhedronB->initializePolyhedralFeatures();
|
||||
@@ -506,10 +510,15 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
|
||||
gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
|
||||
#endif//ZERO_MARGIN
|
||||
|
||||
sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
|
||||
btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
|
||||
if (l2>SIMD_EPSILON)
|
||||
{
|
||||
sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
|
||||
//minDist = gjkPairDetector.getCachedSeparatingDistance();
|
||||
//maxDist = threshold;
|
||||
minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin();
|
||||
foundSepAxis = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -544,8 +553,12 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
|
||||
int i;
|
||||
btVector3 v0,v1;
|
||||
btVector3 sepNormalWorldSpace;
|
||||
btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
|
||||
|
||||
if (l2>SIMD_EPSILON)
|
||||
{
|
||||
sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
|
||||
|
||||
sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
|
||||
btPlaneSpace1(sepNormalWorldSpace,v0,v1);
|
||||
|
||||
|
||||
@@ -588,22 +601,22 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
|
||||
{
|
||||
input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis());
|
||||
input.m_transformB = body1->getWorldTransform();
|
||||
#ifdef DEBUG_CONTACTS
|
||||
#ifdef DEBUG_CONTACTS
|
||||
dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0);
|
||||
#endif //DEBUG_CONTACTS
|
||||
#endif //DEBUG_CONTACTS
|
||||
} else
|
||||
{
|
||||
input.m_transformA = body0->getWorldTransform();
|
||||
input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis());
|
||||
#ifdef DEBUG_CONTACTS
|
||||
#ifdef DEBUG_CONTACTS
|
||||
dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw);
|
||||
gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,8 +64,8 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
|
||||
btAssert(m_manifoldPtr);
|
||||
//order in manifold needs to match
|
||||
|
||||
// if (depth > m_manifoldPtr->getContactBreakingThreshold())
|
||||
if (depth > m_manifoldPtr->getContactProcessingThreshold())
|
||||
if (depth > m_manifoldPtr->getContactBreakingThreshold())
|
||||
// if (depth > m_manifoldPtr->getContactProcessingThreshold())
|
||||
return;
|
||||
|
||||
bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
|
||||
|
||||
@@ -53,7 +53,7 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
|
||||
getVertex(i,newVertex);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
btAlignedObjectArray<btVector3> planeEquations;
|
||||
btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);
|
||||
|
||||
@@ -68,11 +68,17 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
|
||||
btAlignedObjectArray<btVector3> tmpVertices;
|
||||
|
||||
btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
|
||||
|
||||
|
||||
btConvexHullComputer conv;
|
||||
conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);
|
||||
|
||||
#else
|
||||
btConvexHullComputer conv;
|
||||
conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
btAlignedObjectArray<btVector3> faceNormals;
|
||||
int numFaces = conv.faces.size();
|
||||
faceNormals.resize(numFaces);
|
||||
|
||||
@@ -197,15 +197,11 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool validContactDistance(const btManifoldPoint& pt) const
|
||||
{
|
||||
if (pt.m_lifeTime >1)
|
||||
{
|
||||
return pt.m_distance1 <= getContactBreakingThreshold();
|
||||
}
|
||||
return pt.m_distance1 <= getContactProcessingThreshold();
|
||||
|
||||
}
|
||||
/// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
|
||||
void refreshContactPoints( const btTransform& trA,const btTransform& trB);
|
||||
|
||||
|
||||
@@ -327,9 +327,6 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
|
||||
///perform collision detection
|
||||
performDiscreteCollisionDetection();
|
||||
|
||||
if (getDispatchInfo().m_useContinuous)
|
||||
addSpeculativeContacts(timeStep);
|
||||
|
||||
|
||||
calculateSimulationIslands();
|
||||
|
||||
@@ -951,114 +948,6 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
|
||||
}
|
||||
}
|
||||
|
||||
void btDiscreteDynamicsWorld::addSpeculativeContacts(btScalar timeStep)
|
||||
{
|
||||
BT_PROFILE("addSpeculativeContacts");
|
||||
btTransform predictedTrans;
|
||||
for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
|
||||
{
|
||||
btRigidBody* body = m_nonStaticRigidBodies[i];
|
||||
body->setHitFraction(1.f);
|
||||
|
||||
if (body->isActive() && (!body->isStaticOrKinematicObject()))
|
||||
{
|
||||
body->predictIntegratedTransform(timeStep, predictedTrans);
|
||||
btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
|
||||
|
||||
if (body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
|
||||
{
|
||||
BT_PROFILE("search speculative contacts");
|
||||
if (body->getCollisionShape()->isConvex())
|
||||
{
|
||||
gNumClampedCcdMotions++;
|
||||
|
||||
btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
|
||||
//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
|
||||
btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
|
||||
|
||||
sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
|
||||
sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
|
||||
btTransform modifiedPredictedTrans;
|
||||
modifiedPredictedTrans = predictedTrans;
|
||||
modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
|
||||
|
||||
convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
|
||||
if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
|
||||
{
|
||||
btBroadphaseProxy* proxy0 = body->getBroadphaseHandle();
|
||||
btBroadphaseProxy* proxy1 = sweepResults.m_hitCollisionObject->getBroadphaseHandle();
|
||||
btBroadphasePair* pair = sweepResults.m_pairCache->findPair(proxy0,proxy1);
|
||||
if (pair)
|
||||
{
|
||||
if (pair->m_algorithm)
|
||||
{
|
||||
btManifoldArray contacts;
|
||||
pair->m_algorithm->getAllContactManifolds(contacts);
|
||||
if (contacts.size())
|
||||
{
|
||||
btManifoldResult result(body,sweepResults.m_hitCollisionObject);
|
||||
result.setPersistentManifold(contacts[0]);
|
||||
|
||||
btVector3 vec = (modifiedPredictedTrans.getOrigin()-body->getWorldTransform().getOrigin());
|
||||
vec*=sweepResults.m_closestHitFraction;
|
||||
|
||||
btScalar lenSqr = vec.length2();
|
||||
btScalar depth = 0.f;
|
||||
btVector3 pointWorld = sweepResults.m_hitPointWorld;
|
||||
if (lenSqr>SIMD_EPSILON)
|
||||
{
|
||||
depth = btSqrt(lenSqr);
|
||||
pointWorld -= vec;
|
||||
vec /= depth;
|
||||
}
|
||||
|
||||
if (contacts[0]->getBody0()==body)
|
||||
{
|
||||
result.addContactPoint(sweepResults.m_hitNormalWorld,pointWorld,depth);
|
||||
#if 0
|
||||
debugContacts.push_back(sweepResults.m_hitPointWorld);//sweepResults.m_hitPointWorld);
|
||||
debugNormals.push_back(sweepResults.m_hitNormalWorld);
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
//swapped
|
||||
result.addContactPoint(-sweepResults.m_hitNormalWorld,pointWorld,depth);
|
||||
//sweepResults.m_hitPointWorld,depth);
|
||||
|
||||
#if 0
|
||||
if (1)//firstHit==1)
|
||||
{
|
||||
firstHit=0;
|
||||
debugNormals.push_back(sweepResults.m_hitNormalWorld);
|
||||
debugContacts.push_back(pointWorld);//sweepResults.m_hitPointWorld);
|
||||
debugNormals.push_back(sweepResults.m_hitNormalWorld);
|
||||
debugContacts.push_back(sweepResults.m_hitPointWorld);
|
||||
}
|
||||
firstHit--;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
} else
|
||||
{
|
||||
//no algorithm, use dispatcher to create one
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else
|
||||
{
|
||||
//add an overlapping pair
|
||||
//printf("pair missing\n");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,8 +62,6 @@ protected:
|
||||
|
||||
virtual void integrateTransforms(btScalar timeStep);
|
||||
|
||||
virtual void addSpeculativeContacts(btScalar timeStep);
|
||||
|
||||
virtual void calculateSimulationIslands();
|
||||
|
||||
virtual void solveConstraints(btContactSolverInfo& solverInfo);
|
||||
|
||||
@@ -329,7 +329,7 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
|
||||
{
|
||||
const btScalar scl=(btScalar)0.8;
|
||||
const btScalar alp=(btScalar)1;
|
||||
const btVector3 col((btScalar)0.7,(btScalar)0.7,(btScalar)0.7);
|
||||
const btVector3 col((btScalar)0.3,(btScalar)0.3,(btScalar)0.7);
|
||||
for(int i=0;i<psb->m_tetras.size();++i)
|
||||
{
|
||||
const btSoftBody::Tetra& t=psb->m_tetras[i];
|
||||
|
||||
@@ -276,7 +276,8 @@ CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
|
||||
RecursionCounter( 0 ),
|
||||
Parent( parent ),
|
||||
Child( NULL ),
|
||||
Sibling( NULL )
|
||||
Sibling( NULL ),
|
||||
m_userPtr(0)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
@@ -82,7 +82,8 @@ public:
|
||||
const char * Get_Name( void ) { return Name; }
|
||||
int Get_Total_Calls( void ) { return TotalCalls; }
|
||||
float Get_Total_Time( void ) { return TotalTime; }
|
||||
|
||||
void* GetUserPointer() const {return m_userPtr;}
|
||||
void SetUserPointer(void* ptr) { m_userPtr = ptr;}
|
||||
protected:
|
||||
|
||||
const char * Name;
|
||||
@@ -94,6 +95,7 @@ protected:
|
||||
CProfileNode * Parent;
|
||||
CProfileNode * Child;
|
||||
CProfileNode * Sibling;
|
||||
void* m_userPtr;
|
||||
};
|
||||
|
||||
///An iterator to navigate through the tree
|
||||
@@ -115,16 +117,21 @@ public:
|
||||
int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
|
||||
float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
|
||||
|
||||
void* Get_Current_UserPointer( void ) { return CurrentChild->GetUserPointer(); }
|
||||
void Set_Current_UserPointer(void* ptr) {CurrentChild->SetUserPointer(ptr);}
|
||||
// Access the current parent
|
||||
const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
|
||||
int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
|
||||
float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
CProfileNode * CurrentParent;
|
||||
CProfileNode * CurrentChild;
|
||||
|
||||
|
||||
CProfileIterator( CProfileNode * start );
|
||||
friend class CProfileManager;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user