bullet3/ObsoleteDemos/FractureDemo/btFractureBody.cpp
erwin coumans 69e5454d18 Add the old Bullet 2.x obsolete demos, and CMake buildsystem files, and gradually move them to newer Bullet 3.x structure
Use statically linked freeglut, instead of dynamic glut for the obsolete Bullet 2.x demos
Add the 'reset' method to b3GpuDynamicsWorld, and use it in the BasicGpuDemo (pretty slow in debug mode, use release mode)
Don't crash in btCollisionWorld, if there is no collision dispatcher
2013-12-19 12:40:59 -08:00

140 lines
4.1 KiB
C++

#include "btFractureBody.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletDynamics/Dynamics/btDynamicsWorld.h"
void btFractureBody::recomputeConnectivity(btCollisionWorld* world)
{
m_connections.clear();
//@todo use the AABB tree to avoid N^2 checks
if (getCollisionShape()->isCompound())
{
btCompoundShape* compound = (btCompoundShape*)getCollisionShape();
for (int i=0;i<compound->getNumChildShapes();i++)
{
for (int j=i+1;j<compound->getNumChildShapes();j++)
{
struct MyContactResultCallback : public btCollisionWorld::ContactResultCallback
{
bool m_connected;
btScalar m_margin;
MyContactResultCallback() :m_connected(false),m_margin(0.05)
{
}
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1)
{
if (cp.getDistance()<=m_margin)
m_connected = true;
return 1.f;
}
};
MyContactResultCallback result;
btCollisionObject obA;
obA.setWorldTransform(compound->getChildTransform(i));
obA.setCollisionShape(compound->getChildShape(i));
btCollisionObject obB;
obB.setWorldTransform(compound->getChildTransform(j));
obB.setCollisionShape(compound->getChildShape(j));
world->contactPairTest(&obA,&obB,result);
if (result.m_connected)
{
btConnection tmp;
tmp.m_childIndex0 = i;
tmp.m_childIndex1 = j;
tmp.m_childShape0 = compound->getChildShape(i);
tmp.m_childShape1 = compound->getChildShape(j);
tmp.m_strength = 1.f;//??
m_connections.push_back(tmp);
}
}
}
}
}
btCompoundShape* btFractureBody::shiftTransformDistributeMass(btCompoundShape* boxCompound,btScalar mass,btTransform& shift)
{
btVector3 principalInertia;
btScalar* masses = new btScalar[boxCompound->getNumChildShapes()];
for (int j=0;j<boxCompound->getNumChildShapes();j++)
{
//evenly distribute mass
masses[j]=mass/boxCompound->getNumChildShapes();
}
return shiftTransform(boxCompound,masses,shift,principalInertia);
}
btCompoundShape* btFractureBody::shiftTransform(btCompoundShape* boxCompound,btScalar* masses,btTransform& shift, btVector3& principalInertia)
{
btTransform principal;
boxCompound->calculatePrincipalAxisTransform(masses,principal,principalInertia);
///create a new compound with world transform/center of mass properly aligned with the principal axis
///non-recursive compound shapes perform better
#ifdef USE_RECURSIVE_COMPOUND
btCompoundShape* newCompound = new btCompoundShape();
newCompound->addChildShape(principal.inverse(),boxCompound);
newBoxCompound = newCompound;
//m_collisionShapes.push_back(newCompound);
//btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
//btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,newCompound,principalInertia);
#else
#ifdef CHANGE_COMPOUND_INPLACE
newBoxCompound = boxCompound;
for (int i=0;i<boxCompound->getNumChildShapes();i++)
{
btTransform newChildTransform = principal.inverse()*boxCompound->getChildTransform(i);
///updateChildTransform is really slow, because it re-calculates the AABB each time. todo: add option to disable this update
boxCompound->updateChildTransform(i,newChildTransform);
}
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
boxCompound->calculateLocalInertia(mass,localInertia);
#else
///creation is faster using a new compound to store the shifted children
btCompoundShape* newBoxCompound = new btCompoundShape();
for (int i=0;i<boxCompound->getNumChildShapes();i++)
{
btTransform newChildTransform = principal.inverse()*boxCompound->getChildTransform(i);
///updateChildTransform is really slow, because it re-calculates the AABB each time. todo: add option to disable this update
newBoxCompound->addChildShape(newChildTransform,boxCompound->getChildShape(i));
}
#endif
#endif//USE_RECURSIVE_COMPOUND
shift = principal;
return newBoxCompound;
}