some work on compound collision shapes (not finished yet)

This commit is contained in:
ejcoumans 2006-07-24 05:22:56 +00:00
parent 60ce7413fe
commit fdaa3a7abc
8 changed files with 464 additions and 253 deletions

View File

@ -21,6 +21,7 @@ subject to the following restrictions:
#include "CollisionDispatch/ConvexConvexAlgorithm.h" #include "CollisionDispatch/ConvexConvexAlgorithm.h"
#include "CollisionDispatch/EmptyCollisionAlgorithm.h" #include "CollisionDispatch/EmptyCollisionAlgorithm.h"
#include "CollisionDispatch/ConvexConcaveCollisionAlgorithm.h" #include "CollisionDispatch/ConvexConcaveCollisionAlgorithm.h"
#include "CollisionDispatch/CompoundCollisionAlgorithm.h"
#include "CollisionShapes/CollisionShape.h" #include "CollisionShapes/CollisionShape.h"
#include "CollisionDispatch/CollisionObject.h" #include "CollisionDispatch/CollisionObject.h"
#include <algorithm> #include <algorithm>
@ -122,6 +123,17 @@ CollisionAlgorithm* CollisionDispatcher::InternalFindAlgorithm(BroadphaseProxy&
return new ConvexConcaveCollisionAlgorithm(ci,&proxy1,&proxy0); return new ConvexConcaveCollisionAlgorithm(ci,&proxy1,&proxy0);
} }
if (body0->m_collisionShape->IsCompound())
{
return new CompoundCollisionAlgorithm(ci,&proxy0,&proxy1);
} else
{
if (body1->m_collisionShape->IsCompound())
{
return new CompoundCollisionAlgorithm(ci,&proxy1,&proxy0);
}
}
//failed to find an algorithm //failed to find an algorithm
return new EmptyAlgorithm(ci); return new EmptyAlgorithm(ci);

View File

@ -20,6 +20,7 @@ subject to the following restrictions:
#include "CollisionShapes/SphereShape.h" //for raycasting #include "CollisionShapes/SphereShape.h" //for raycasting
#include "CollisionShapes/TriangleMeshShape.h" //for raycasting #include "CollisionShapes/TriangleMeshShape.h" //for raycasting
#include "NarrowPhaseCollision/RaycastCallback.h" #include "NarrowPhaseCollision/RaycastCallback.h"
#include "CollisionShapes/CompoundShape.h"
#include "NarrowPhaseCollision/SubSimplexConvexCast.h" #include "NarrowPhaseCollision/SubSimplexConvexCast.h"
#include "BroadphaseCollision/BroadphaseInterface.h" #include "BroadphaseCollision/BroadphaseInterface.h"
@ -139,58 +140,27 @@ void CollisionWorld::RemoveCollisionObject(CollisionObject* collisionObject)
} }
} }
void RayTestSingle(const SimdTransform& rayFromTrans,const SimdTransform& rayToTrans,
CollisionObject* collisionObject,
void CollisionWorld::RayTest(const SimdVector3& rayFromWorld, const SimdVector3& rayToWorld, RayResultCallback& resultCallback) const CollisionShape* collisionShape,
const SimdTransform& colObjWorldTransform,
CollisionWorld::RayResultCallback& resultCallback)
{ {
SimdTransform rayFromTrans,rayToTrans;
rayFromTrans.setIdentity();
rayFromTrans.setOrigin(rayFromWorld);
rayToTrans.setIdentity();
rayToTrans.setOrigin(rayToWorld);
//do culling based on aabb (rayFrom/rayTo)
SimdVector3 rayAabbMin = rayFromWorld;
SimdVector3 rayAabbMax = rayFromWorld;
rayAabbMin.setMin(rayToWorld);
rayAabbMax.setMax(rayToWorld);
SphereShape pointShape(0.0f); SphereShape pointShape(0.0f);
/// brute force go over all objects. Once there is a broadphase, use that, or if (collisionShape->IsConvex())
/// add a raycast against aabb first.
std::vector<CollisionObject*>::iterator iter;
for (iter=m_collisionObjects.begin();
!(iter==m_collisionObjects.end()); iter++)
{
CollisionObject* collisionObject= (*iter);
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
SimdVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->m_collisionShape->GetAabb(collisionObject->m_worldTransform,collisionObjectAabbMin,collisionObjectAabbMax);
//check aabb overlap
if (TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,collisionObjectAabbMin,collisionObjectAabbMax))
{
if (collisionObject->m_collisionShape->IsConvex())
{ {
ConvexCast::CastResult castResult; ConvexCast::CastResult castResult;
castResult.m_fraction = 1.f;//?? castResult.m_fraction = 1.f;//??
ConvexShape* convexShape = (ConvexShape*) collisionObject->m_collisionShape; ConvexShape* convexShape = (ConvexShape*) collisionShape;
VoronoiSimplexSolver simplexSolver; VoronoiSimplexSolver simplexSolver;
SubsimplexConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); SubsimplexConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
//GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,collisionObject->m_worldTransform,collisionObject->m_worldTransform,castResult)) if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
{ {
//add hit //add hit
if (castResult.m_normal.length2() > 0.0001f) if (castResult.m_normal.length2() > 0.0001f)
@ -217,12 +187,12 @@ void CollisionWorld::RayTest(const SimdVector3& rayFromWorld, const SimdVector3&
else else
{ {
if (collisionObject->m_collisionShape->IsConcave()) if (collisionShape->IsConcave())
{ {
TriangleMeshShape* triangleMesh = (TriangleMeshShape*)collisionObject->m_collisionShape; TriangleMeshShape* triangleMesh = (TriangleMeshShape*)collisionShape;
SimdTransform worldTocollisionObject = collisionObject->m_worldTransform.inverse(); SimdTransform worldTocollisionObject = colObjWorldTransform.inverse();
SimdVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); SimdVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
SimdVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); SimdVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
@ -231,12 +201,12 @@ void CollisionWorld::RayTest(const SimdVector3& rayFromWorld, const SimdVector3&
struct BridgeTriangleRaycastCallback : public TriangleRaycastCallback struct BridgeTriangleRaycastCallback : public TriangleRaycastCallback
{ {
RayResultCallback* m_resultCallback; CollisionWorld::RayResultCallback* m_resultCallback;
CollisionObject* m_collisionObject; CollisionObject* m_collisionObject;
TriangleMeshShape* m_triangleMesh; TriangleMeshShape* m_triangleMesh;
BridgeTriangleRaycastCallback( const SimdVector3& from,const SimdVector3& to, BridgeTriangleRaycastCallback( const SimdVector3& from,const SimdVector3& to,
RayResultCallback* resultCallback, CollisionObject* collisionObject,TriangleMeshShape* triangleMesh): CollisionWorld::RayResultCallback* resultCallback, CollisionObject* collisionObject,TriangleMeshShape* triangleMesh):
TriangleRaycastCallback(from,to), TriangleRaycastCallback(from,to),
m_resultCallback(resultCallback), m_resultCallback(resultCallback),
m_collisionObject(collisionObject), m_collisionObject(collisionObject),
@ -275,11 +245,76 @@ void CollisionWorld::RayTest(const SimdVector3& rayFromWorld, const SimdVector3&
triangleMesh->ProcessAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); triangleMesh->ProcessAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
} else
{
//todo: use AABB tree or other BVH acceleration structure!
if (collisionShape->IsCompound())
{
const CompoundShape* compoundShape = static_cast<const CompoundShape*>(collisionShape);
int i=0;
for (i=0;i<compoundShape->GetNumChildShapes();i++)
{
SimdTransform childTrans = compoundShape->GetChildTransform(i);
const CollisionShape* childCollisionShape = compoundShape->GetChildShape(i);
SimdTransform childWorldTrans = colObjWorldTransform * childTrans;
RayTestSingle(rayFromTrans,rayToTrans,
collisionObject,
childCollisionShape,
childWorldTrans,
resultCallback);
} }
} }
} }
} }
}
void CollisionWorld::RayTest(const SimdVector3& rayFromWorld, const SimdVector3& rayToWorld, RayResultCallback& resultCallback)
{
SimdTransform rayFromTrans,rayToTrans;
rayFromTrans.setIdentity();
rayFromTrans.setOrigin(rayFromWorld);
rayToTrans.setIdentity();
rayToTrans.setOrigin(rayToWorld);
//do culling based on aabb (rayFrom/rayTo)
SimdVector3 rayAabbMin = rayFromWorld;
SimdVector3 rayAabbMax = rayFromWorld;
rayAabbMin.setMin(rayToWorld);
rayAabbMax.setMax(rayToWorld);
/// brute force go over all objects. Once there is a broadphase, use that, or
/// add a raycast against aabb first.
std::vector<CollisionObject*>::iterator iter;
for (iter=m_collisionObjects.begin();
!(iter==m_collisionObjects.end()); iter++)
{
CollisionObject* collisionObject= (*iter);
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
SimdVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->m_collisionShape->GetAabb(collisionObject->m_worldTransform,collisionObjectAabbMin,collisionObjectAabbMax);
//check aabb overlap
if (TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,collisionObjectAabbMin,collisionObjectAabbMax))
{
RayTestSingle(rayFromTrans,rayToTrans,
collisionObject,
collisionObject->m_collisionShape,
collisionObject->m_worldTransform,
resultCallback);
}
}
} }

View File

@ -14,19 +14,70 @@ subject to the following restrictions:
*/ */
#include "CollisionDispatch/CompoundCollisionAlgorithm.h" #include "CollisionDispatch/CompoundCollisionAlgorithm.h"
#include "CollisionDispatch/CollisionObject.h"
#include "CollisionShapes/CompoundShape.h"
CompoundCollisionAlgorithm::CompoundCollisionAlgorithm( const CollisionAlgorithmConstructionInfo& ci,BroadphaseProxy* proxy0,BroadphaseProxy* proxy1) CompoundCollisionAlgorithm::CompoundCollisionAlgorithm( const CollisionAlgorithmConstructionInfo& ci,BroadphaseProxy* proxy0,BroadphaseProxy* proxy1)
:m_dispatcher(ci.m_dispatcher),
m_compoundProxy(*proxy0),
m_otherProxy(*proxy1)
{ {
CollisionObject* colObj = static_cast<CollisionObject*>(m_compoundProxy.m_clientObject);
assert (colObj->m_collisionShape->IsCompound());
CompoundShape* compoundShape = static_cast<CompoundShape*>(colObj->m_collisionShape);
int numChildren = compoundShape->GetNumChildShapes();
m_childProxies.resize( numChildren );
int i;
for (i=0;i<numChildren;i++)
{
m_childProxies[i] = BroadphaseProxy(*proxy0);
} }
m_childCollisionAlgorithms.resize(numChildren);
for (i=0;i<numChildren;i++)
{
CollisionShape* childShape = compoundShape->GetChildShape(i);
CollisionObject* colObj = static_cast<CollisionObject*>(m_childProxies[i].m_clientObject);
CollisionShape* orgShape = colObj->m_collisionShape;
colObj->m_collisionShape = childShape;
m_childCollisionAlgorithms[i] = m_dispatcher->FindAlgorithm(m_childProxies[i],m_otherProxy);
colObj->m_collisionShape =orgShape;
}
}
CompoundCollisionAlgorithm::~CompoundCollisionAlgorithm() CompoundCollisionAlgorithm::~CompoundCollisionAlgorithm()
{ {
int numChildren = m_childCollisionAlgorithms.size();
int i;
for (i=0;i<numChildren;i++)
{
delete m_childCollisionAlgorithms[i];
}
} }
void CompoundCollisionAlgorithm::ProcessCollision (BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,const DispatcherInfo& dispatchInfo) void CompoundCollisionAlgorithm::ProcessCollision (BroadphaseProxy* ,BroadphaseProxy* ,const DispatcherInfo& dispatchInfo)
{ {
CollisionObject* colObj = static_cast<CollisionObject*>(m_compoundProxy.m_clientObject);
assert (colObj->m_collisionShape->IsCompound());
CompoundShape* compoundShape = static_cast<CompoundShape*>(colObj->m_collisionShape);
int numChildren = m_childCollisionAlgorithms.size();
int i;
for (i=0;i<numChildren;i++)
{
//temporarily exchange parent CollisionShape with childShape, and recurse
CollisionShape* childShape = compoundShape->GetChildShape(i);
CollisionObject* colObj = static_cast<CollisionObject*>(m_childProxies[i].m_clientObject);
CollisionShape* orgShape = colObj->m_collisionShape;
colObj->m_collisionShape = childShape;
m_childCollisionAlgorithms[i]->ProcessCollision(&m_childProxies[i],&m_otherProxy,dispatchInfo);
//revert back
colObj->m_collisionShape =orgShape;
}
} }
float CompoundCollisionAlgorithm::CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,const DispatcherInfo& dispatchInfo) float CompoundCollisionAlgorithm::CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,const DispatcherInfo& dispatchInfo)

View File

@ -23,14 +23,19 @@ subject to the following restrictions:
#include "NarrowPhaseCollision/PersistentManifold.h" #include "NarrowPhaseCollision/PersistentManifold.h"
class Dispatcher; class Dispatcher;
#include "BroadphaseCollision/BroadphaseProxy.h" #include "BroadphaseCollision/BroadphaseProxy.h"
#include <vector>
/// CompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes /// CompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
/// Place holder, not fully implemented yet /// Place holder, not fully implemented yet
class CompoundCollisionAlgorithm : public CollisionAlgorithm class CompoundCollisionAlgorithm : public CollisionAlgorithm
{ {
BroadphaseProxy m_compoundProxy;
BroadphaseProxy m_otherProxy;
std::vector<BroadphaseProxy> m_childProxies;
std::vector<CollisionAlgorithm*> m_childCollisionAlgorithms;
Dispatcher* m_dispatcher;
BroadphaseProxy m_compound; BroadphaseProxy m_compound;
BroadphaseProxy m_other; BroadphaseProxy m_other;

View File

@ -20,6 +20,8 @@ subject to the following restrictions:
CompoundShape::CompoundShape() CompoundShape::CompoundShape()
:m_localAabbMin(1e30f,1e30f,1e30f),
m_localAabbMax(-1e30f,-1e30f,-1e30f)
{ {
} }
@ -28,21 +30,66 @@ CompoundShape::~CompoundShape()
{ {
} }
void CompoundShape::AddChildShape(const SimdTransform& localTransform,CollisionShape* shape)
{
m_childTransforms.push_back(localTransform);
m_childShapes.push_back(shape);
//extend the local aabbMin/aabbMax
SimdVector3 localAabbMin,localAabbMax;
shape->GetAabb(localTransform,localAabbMin,localAabbMax);
for (int i=0;i<3;i++)
{
if (m_localAabbMin[i] > localAabbMin[i])
{
m_localAabbMin[i] = localAabbMin[i];
}
if (m_localAabbMax[i] < localAabbMax[i])
{
m_localAabbMax[i] = localAabbMax[i];
}
}
}
///GetAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version ///GetAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
void CompoundShape::GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const void CompoundShape::GetAabb(const SimdTransform& trans,SimdVector3& aabbMin,SimdVector3& aabbMax) const
{ {
SimdVector3 margin(GetMargin(),GetMargin(),GetMargin()); SimdVector3 localHalfExtents = 0.5f*(m_localAabbMax-m_localAabbMin);
SimdVector3 localCenter = 0.5f*(m_localAabbMax+m_localAabbMin);
aabbMin = t.getOrigin() - margin; SimdMatrix3x3 abs_b = trans.getBasis().absolute();
aabbMax = t.getOrigin() + margin; SimdPoint3 center = trans(localCenter);
SimdVector3 extent = SimdVector3(abs_b[0].dot(localHalfExtents),
abs_b[1].dot(localHalfExtents),
abs_b[2].dot(localHalfExtents));
extent += SimdVector3(GetMargin(),GetMargin(),GetMargin());
aabbMin = center - extent;
aabbMax = center + extent;
} }
void CompoundShape::CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia) void CompoundShape::CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
{ {
assert(0); //approximation: take the inertia from the aabb for now
SimdTransform ident;
SimdVector3 aabbMin,aabbMax;
GetAabb(ident,aabbMin,aabbMax);
SimdVector3 halfExtents = (aabbMax-aabbMin)*0.5f;
SimdScalar lx=2.f*(halfExtents.x());
SimdScalar ly=2.f*(halfExtents.y());
SimdScalar lz=2.f*(halfExtents.z());
inertia[0] = mass/(12.0f) * (ly*ly + lz*lz);
inertia[1] = mass/(12.0f) * (lx*lx + lz*lz);
inertia[2] = mass/(12.0f) * (lx*lx + ly*ly);
} }

View File

@ -28,14 +28,43 @@ subject to the following restrictions:
/// CompoundShape allows to store multiple other CollisionShapes /// CompoundShape allows to store multiple other CollisionShapes
/// This allows for concave collision objects. This is more general then the Static Concave TriangleMeshShape. /// This allows for concave collision objects. This is more general then the Static Concave TriangleMeshShape.
/// Place holder, not fully implemented yet
class CompoundShape : public CollisionShape class CompoundShape : public CollisionShape
{ {
std::vector<SimdTransform> m_childTransforms;
std::vector<CollisionShape*> m_childShapes;
SimdVector3 m_localAabbMin;
SimdVector3 m_localAabbMax;
public: public:
CompoundShape(); CompoundShape();
virtual ~CompoundShape(); virtual ~CompoundShape();
void AddChildShape(const SimdTransform& localTransform,CollisionShape* shape);
int GetNumChildShapes() const
{
return m_childShapes.size();
}
CollisionShape* GetChildShape(int index)
{
return m_childShapes[index];
}
const CollisionShape* GetChildShape(int index) const
{
return m_childShapes[index];
}
SimdTransform GetChildTransform(int index)
{
return m_childTransforms[index];
}
const SimdTransform GetChildTransform(int index) const
{
return m_childTransforms[index];
}
///GetAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version ///GetAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
void GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const; void GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const;

View File

@ -26,7 +26,7 @@ subject to the following restrictions:
#include "CollisionShapes/SphereShape.h" #include "CollisionShapes/SphereShape.h"
#include "CollisionShapes/ConeShape.h" #include "CollisionShapes/ConeShape.h"
#include "CollisionShapes/StaticPlaneShape.h" #include "CollisionShapes/StaticPlaneShape.h"
#include "CollisionShapes/CompoundShape.h"
#include "CollisionShapes/Simplex1to4Shape.h" #include "CollisionShapes/Simplex1to4Shape.h"
#include "CollisionShapes/EmptyShape.h" #include "CollisionShapes/EmptyShape.h"
@ -205,8 +205,13 @@ int main(int argc,char** argv)
shapeIndex[i] = 0; shapeIndex[i] = 0;
} }
CompoundShape* compoundShape = new CompoundShape();
//shapePtr[1] = compoundShape;
SimdTransform ident;
ident.setIdentity();
compoundShape->AddChildShape(ident,new BoxShape (SimdVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)));
for (i=0;i<numObjects;i++) for (i=0;i<numObjects;i++)
{ {
@ -498,8 +503,17 @@ void renderme()
char extraDebug[125]; char extraDebug[125];
sprintf(extraDebug,"islId, Body=%i , %i",physObjects[i]->GetRigidBody()->m_islandTag1,physObjects[i]->GetRigidBody()->m_debugBodyId); sprintf(extraDebug,"islId, Body=%i , %i",physObjects[i]->GetRigidBody()->m_islandTag1,physObjects[i]->GetRigidBody()->m_debugBodyId);
physObjects[i]->GetRigidBody()->GetCollisionShape()->SetExtraDebugInfo(extraDebug); physObjects[i]->GetRigidBody()->GetCollisionShape()->SetExtraDebugInfo(extraDebug);
float vec[16];
SimdTransform ident;
ident.setIdentity();
ident.getOpenGLMatrix(vec);
glPushMatrix();
glLoadMatrixf(vec);
GL_ShapeDrawer::DrawOpenGL(m,physObjects[i]->GetRigidBody()->GetCollisionShape(),wireColor,getDebugMode()); GL_ShapeDrawer::DrawOpenGL(m,physObjects[i]->GetRigidBody()->GetCollisionShape(),wireColor,getDebugMode());
glPopMatrix();
///this block is just experimental code to show some internal issues with replacing shapes on the fly. ///this block is just experimental code to show some internal issues with replacing shapes on the fly.
if (getDebugMode()!=0 && (i>0)) if (getDebugMode()!=0 && (i>0))
{ {

View File

@ -34,6 +34,7 @@ subject to the following restrictions:
#include "CollisionShapes/ConeShape.h" #include "CollisionShapes/ConeShape.h"
#include "CollisionShapes/CylinderShape.h" #include "CollisionShapes/CylinderShape.h"
#include "CollisionShapes/Simplex1to4Shape.h" #include "CollisionShapes/Simplex1to4Shape.h"
#include "CollisionShapes/CompoundShape.h"
#include "CollisionShapes/ConvexTriangleMeshShape.h" #include "CollisionShapes/ConvexTriangleMeshShape.h"
@ -105,9 +106,26 @@ public:
void GL_ShapeDrawer::DrawOpenGL(float* m, const CollisionShape* shape, const SimdVector3& color,int debugMode) void GL_ShapeDrawer::DrawOpenGL(float* m, const CollisionShape* shape, const SimdVector3& color,int debugMode)
{ {
glPushMatrix();
glLoadMatrixf(m);
glPushMatrix();
glMultMatrixf(m);
if (shape->GetShapeType() == COMPOUND_SHAPE_PROXYTYPE)
{
const CompoundShape* compoundShape = static_cast<const CompoundShape*>(shape);
for (int i=0;i<compoundShape->GetNumChildShapes();i++)
{
SimdTransform childTrans = compoundShape->GetChildTransform(i);
const CollisionShape* colShape = compoundShape->GetChildShape(i);
float childMat[16];
childTrans.getOpenGLMatrix(childMat);
DrawOpenGL(childMat,colShape,color,debugMode);
}
return;
} else
{
//DrawCoordSystem(); //DrawCoordSystem();
glPushMatrix(); glPushMatrix();
@ -322,8 +340,8 @@ void GL_ShapeDrawer::DrawOpenGL(float* m, const CollisionShape* shape, const Sim
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),shape->GetExtraDebugInfo()); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),shape->GetExtraDebugInfo());
} }
glEnable(GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_BUFFER_BIT);
glPopMatrix(); glPopMatrix();
}
glPopMatrix(); glPopMatrix();
} }