185 lines
5.0 KiB
C++
185 lines
5.0 KiB
C++
#include "BulletOdeCollisionPair.h"
|
|
|
|
#include "NarrowPhaseCollision/PersistentManifold.h"
|
|
//quick hack, we need internals, not just the public ode api
|
|
#include <../ode/src/collision_kernel.h>
|
|
#include "CollisionShapes/BoxShape.h"
|
|
#include "BulletOdeCollide.h"
|
|
|
|
#include "CollisionShapes/SphereShape.h"
|
|
#include "CollisionShapes/CylinderShape.h"
|
|
#include "CollisionShapes/MultiSphereShape.h"//capped cylinder is convex hull of two spheres
|
|
#include "CollisionShapes/ConvexTriangleCallback.h"
|
|
|
|
#include "BVHTrimeshShape.h"
|
|
|
|
#include "NarrowPhaseCollision/GjkPairDetector.h"
|
|
#include "NarrowPhaseCollision/VoronoiSimplexSolver.h"
|
|
#include "NarrowPhaseCollision/MinkowskiPenetrationDepthSolver.h"
|
|
///for comparison/unit testing
|
|
#ifdef UNIT_TEST_COMPARE_PENETRATION_DEPTH
|
|
#include "../ExtraSolid35/Solid3EpaPenetrationDepth.h"
|
|
#endif //UNIT_TEST_COMPARE_PENETRATION_DEPTH
|
|
|
|
#include "BulletOdeManifoldResult.h"
|
|
#include "BulletOdeTransformConvert.h"
|
|
|
|
BulletOdeCollisionPair::BulletOdeCollisionPair(dGeomID o1,dGeomID o2)
|
|
{
|
|
m_manifold = new PersistentManifold();
|
|
|
|
m_o1 = o1;
|
|
m_o2 = o2;
|
|
|
|
m_shape1 = CreateShapeFromGeom(o1);
|
|
|
|
m_shape2 = CreateShapeFromGeom(o2);
|
|
|
|
}
|
|
|
|
|
|
BulletOdeCollisionPair::~BulletOdeCollisionPair()
|
|
{
|
|
}
|
|
|
|
void BulletOdeCollisionPair::CalculateContacts()
|
|
{
|
|
//perform gjk, passing the points to the persistent manifold and convert to ode contacts
|
|
|
|
if ((!m_shape1) || (!m_shape2))
|
|
return;
|
|
|
|
if (m_shape1->IsConcave() && m_shape2->IsConvex())
|
|
{
|
|
TriangleMeshShape* triangleMesh = (TriangleMeshShape*)m_shape1;
|
|
ConvexShape* convexShape2 = (ConvexShape*)m_shape2;
|
|
|
|
float collisionMarginTriangle = 0.02f;//triangleMesh->GetMargin();
|
|
SimdTransform triangleMeshTrans = GetTransformFromGeom(m_o1);
|
|
SimdTransform convexTrans = GetTransformFromGeom(m_o2);
|
|
|
|
ConvexTriangleCallback convexTriangleCallback(m_manifold,convexShape2,convexTrans,triangleMeshTrans);
|
|
convexTriangleCallback.Update(collisionMarginTriangle);
|
|
|
|
triangleMesh->ProcessAllTriangles( &convexTriangleCallback,convexTriangleCallback.GetAabbMin(),convexTriangleCallback.GetAabbMax());
|
|
|
|
m_manifold->RefreshContactPoints(triangleMeshTrans,convexTrans);
|
|
|
|
}
|
|
|
|
if (m_shape1->IsConvex() && m_shape2->IsConvex())
|
|
{
|
|
ConvexShape* convexShape1 = (ConvexShape*)m_shape1;
|
|
ConvexShape* convexShape2 = (ConvexShape*)m_shape2;
|
|
|
|
|
|
|
|
BulletOdeManifoldResult output(m_o1,m_o2,m_manifold);
|
|
|
|
GjkPairDetector::ClosestPointInput input;
|
|
|
|
VoronoiSimplexSolver simplexSolver;
|
|
|
|
#ifdef UNIT_TEST_COMPARE_PENETRATION_DEPTH
|
|
Solid3EpaPenetrationDepth penetrationDepthSolver;
|
|
#else
|
|
MinkowskiPenetrationDepthSolver penetrationDepthSolver;
|
|
#endif// UNIT_TEST_COMPARE_PENETRATION_DEPTH
|
|
|
|
GjkPairDetector gjkDetector(convexShape1,convexShape2,&simplexSolver,&penetrationDepthSolver);
|
|
|
|
|
|
gjkDetector.SetMinkowskiA(convexShape1);
|
|
gjkDetector.SetMinkowskiB(convexShape2);
|
|
input.m_maximumDistanceSquared = m_shape1->GetMargin()+ m_shape2->GetMargin() + m_manifold->GetManifoldMargin();
|
|
input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
|
|
|
|
input.m_maximumDistanceSquared = 1e30;//?
|
|
|
|
input.m_transformA = GetTransformFromGeom(m_o1);
|
|
input.m_transformB = GetTransformFromGeom(m_o2);
|
|
|
|
gjkDetector.GetClosestPoints(input,output,0);
|
|
|
|
m_manifold->RefreshContactPoints(input.m_transformA,input.m_transformB);
|
|
|
|
}
|
|
}
|
|
|
|
void BulletOdeCollisionPair::ProcessCollision (BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,const struct DispatcherInfo& dispatchInfo)
|
|
{
|
|
|
|
}
|
|
|
|
float BulletOdeCollisionPair::CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,const struct DispatcherInfo& dispatchInfo)
|
|
{
|
|
return 1.f;
|
|
}
|
|
|
|
|
|
CollisionShape* BulletOdeCollisionPair::CreateShapeFromGeom(dGeomID geom)
|
|
{
|
|
CollisionShape* shape = 0;
|
|
|
|
if (geom->type == dConvexClass)
|
|
{
|
|
shape = GetCollisionShapeFromConvex(geom);
|
|
} else
|
|
{
|
|
//bullet shape versus ode geom, create a compatible shape from the ode types
|
|
switch (geom->type)
|
|
{
|
|
case dPlaneClass:
|
|
break;
|
|
case dBoxClass:
|
|
{
|
|
dVector3 size;
|
|
dGeomBoxGetLengths (geom,size);
|
|
SimdVector3 halfExtents(0.5f*size[0],0.5f*size[1],0.5f*size[2]);
|
|
shape = new BoxShape(halfExtents);
|
|
break;
|
|
}
|
|
case dSphereClass:
|
|
{
|
|
dVector3 size;
|
|
shape = new SphereShape(dGeomSphereGetRadius(geom));
|
|
break;
|
|
}
|
|
case dCylinderClass:
|
|
{
|
|
dVector3 size;
|
|
dGeomBoxGetLengths (geom,size);
|
|
SimdVector3 boxHalfExtents(size[0],size[0],size[1]);
|
|
shape = new CylinderShapeZ(boxHalfExtents);
|
|
break;
|
|
}
|
|
case dCCylinderClass:
|
|
{
|
|
dReal radius,length;
|
|
dGeomCCylinderGetParams (geom, &radius, &length);
|
|
SimdVector3 boxHalfExtents(radius,radius,0.5f*length);
|
|
int numspheres = 2;
|
|
SimdVector3 centers[2]={ SimdVector3(0,0,0.5f*length),SimdVector3(0,0,-0.5f*length)};
|
|
SimdScalar radi[2]={radius,radius};
|
|
shape = new MultiSphereShape(boxHalfExtents,centers,radi,numspheres);
|
|
break;
|
|
}
|
|
case dTriMeshClass:
|
|
{
|
|
dxTriMesh* trimesh = (dxTriMesh*) geom;
|
|
shape = 0;//new BVHTrimeshShape(trimesh);
|
|
break;
|
|
}
|
|
|
|
|
|
default:
|
|
{
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
return shape;
|
|
|
|
}
|