mirror of
https://github.com/bulletphysics/bullet3
synced 2024-12-14 13:50:04 +00:00
140 lines
4.1 KiB
C++
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|