Files
bullet3/Extras/BulletOdeCollide/BulletOdeCollisionPair.cpp
2006-05-25 19:18:29 +00:00

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;
}