1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
#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;
}
|