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/EmptyCollisionAlgorithm.h"
#include "CollisionDispatch/ConvexConcaveCollisionAlgorithm.h"
#include "CollisionDispatch/CompoundCollisionAlgorithm.h"
#include "CollisionShapes/CollisionShape.h"
#include "CollisionDispatch/CollisionObject.h"
#include <algorithm>
@ -122,6 +123,17 @@ CollisionAlgorithm* CollisionDispatcher::InternalFindAlgorithm(BroadphaseProxy&
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
return new EmptyAlgorithm(ci);

View File

@ -20,6 +20,7 @@ subject to the following restrictions:
#include "CollisionShapes/SphereShape.h" //for raycasting
#include "CollisionShapes/TriangleMeshShape.h" //for raycasting
#include "NarrowPhaseCollision/RaycastCallback.h"
#include "CollisionShapes/CompoundShape.h"
#include "NarrowPhaseCollision/SubSimplexConvexCast.h"
#include "BroadphaseCollision/BroadphaseInterface.h"
@ -139,58 +140,27 @@ void CollisionWorld::RemoveCollisionObject(CollisionObject* collisionObject)
}
}
void CollisionWorld::RayTest(const SimdVector3& rayFromWorld, const SimdVector3& rayToWorld, RayResultCallback& resultCallback)
void RayTestSingle(const SimdTransform& rayFromTrans,const SimdTransform& rayToTrans,
CollisionObject* collisionObject,
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);
/// 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))
{
if (collisionObject->m_collisionShape->IsConvex())
if (collisionShape->IsConvex())
{
ConvexCast::CastResult castResult;
castResult.m_fraction = 1.f;//??
ConvexShape* convexShape = (ConvexShape*) collisionObject->m_collisionShape;
ConvexShape* convexShape = (ConvexShape*) collisionShape;
VoronoiSimplexSolver simplexSolver;
SubsimplexConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
//GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
//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
if (castResult.m_normal.length2() > 0.0001f)
@ -217,12 +187,12 @@ void CollisionWorld::RayTest(const SimdVector3& rayFromWorld, const SimdVector3&
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 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
@ -231,12 +201,12 @@ void CollisionWorld::RayTest(const SimdVector3& rayFromWorld, const SimdVector3&
struct BridgeTriangleRaycastCallback : public TriangleRaycastCallback
{
RayResultCallback* m_resultCallback;
CollisionWorld::RayResultCallback* m_resultCallback;
CollisionObject* m_collisionObject;
TriangleMeshShape* m_triangleMesh;
BridgeTriangleRaycastCallback( const SimdVector3& from,const SimdVector3& to,
RayResultCallback* resultCallback, CollisionObject* collisionObject,TriangleMeshShape* triangleMesh):
CollisionWorld::RayResultCallback* resultCallback, CollisionObject* collisionObject,TriangleMeshShape* triangleMesh):
TriangleRaycastCallback(from,to),
m_resultCallback(resultCallback),
m_collisionObject(collisionObject),
@ -275,11 +245,76 @@ void CollisionWorld::RayTest(const SimdVector3& rayFromWorld, const SimdVector3&
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/CollisionObject.h"
#include "CollisionShapes/CompoundShape.h"
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()
{
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)

View File

@ -23,14 +23,19 @@ subject to the following restrictions:
#include "NarrowPhaseCollision/PersistentManifold.h"
class Dispatcher;
#include "BroadphaseCollision/BroadphaseProxy.h"
#include <vector>
/// CompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
/// Place holder, not fully implemented yet
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_other;

View File

@ -20,6 +20,8 @@ subject to the following restrictions:
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
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)
{
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
/// 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
{
std::vector<SimdTransform> m_childTransforms;
std::vector<CollisionShape*> m_childShapes;
SimdVector3 m_localAabbMin;
SimdVector3 m_localAabbMax;
public:
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
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/ConeShape.h"
#include "CollisionShapes/StaticPlaneShape.h"
#include "CollisionShapes/CompoundShape.h"
#include "CollisionShapes/Simplex1to4Shape.h"
#include "CollisionShapes/EmptyShape.h"
@ -205,8 +205,13 @@ int main(int argc,char** argv)
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++)
{
@ -498,8 +503,17 @@ void renderme()
char extraDebug[125];
sprintf(extraDebug,"islId, Body=%i , %i",physObjects[i]->GetRigidBody()->m_islandTag1,physObjects[i]->GetRigidBody()->m_debugBodyId);
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());
glPopMatrix();
///this block is just experimental code to show some internal issues with replacing shapes on the fly.
if (getDebugMode()!=0 && (i>0))
{

View File

@ -34,6 +34,7 @@ subject to the following restrictions:
#include "CollisionShapes/ConeShape.h"
#include "CollisionShapes/CylinderShape.h"
#include "CollisionShapes/Simplex1to4Shape.h"
#include "CollisionShapes/CompoundShape.h"
#include "CollisionShapes/ConvexTriangleMeshShape.h"
@ -105,9 +106,26 @@ public:
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();
glPushMatrix();
@ -322,8 +340,8 @@ void GL_ShapeDrawer::DrawOpenGL(float* m, const CollisionShape* shape, const Sim
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),shape->GetExtraDebugInfo());
}
glEnable(GL_DEPTH_BUFFER_BIT);
glPopMatrix();
}
glPopMatrix();
}