Program Listing for File CollisionDetection.cpp
↰ Return to documentation for file (Simulation/CollisionDetection.cpp)
#include "CollisionDetection.h"
#include "Simulation/IDFactory.h"
using namespace PBD;
using namespace Utilities;
using namespace GenParam;
int CollisionDetection::CONTACT_TOLERANCE = -1;
int CollisionDetection::CollisionObjectWithoutGeometry::TYPE_ID = IDFactory::getId();
const unsigned int CollisionDetection::RigidBodyContactType = 0;
const unsigned int CollisionDetection::ParticleContactType = 1;
const unsigned int CollisionDetection::ParticleRigidBodyContactType = 2;
const unsigned int CollisionDetection::ParticleSolidContactType = 3;
const unsigned int CollisionDetection::CollisionObject::RigidBodyCollisionObjectType = 0;
const unsigned int CollisionDetection::CollisionObject::TriangleModelCollisionObjectType = 1;
const unsigned int CollisionDetection::CollisionObject::TetModelCollisionObjectType = 2;
CollisionDetection::CollisionDetection() : m_collisionObjects()
{
m_collisionObjects.reserve(1000);
m_contactCB = NULL;
m_solidContactCB = NULL;
m_tolerance = static_cast<Real>(0.01);
}
CollisionDetection::~CollisionDetection()
{
cleanup();
}
void CollisionDetection::init()
{
initParameters();
}
void CollisionDetection::initParameters()
{
ParameterObject::initParameters();
CONTACT_TOLERANCE = createNumericParameter("contactTolerance", "Contact tolerance", &m_tolerance);
setGroup(CONTACT_TOLERANCE, "Simulation|Contact");
setDescription(CONTACT_TOLERANCE, "Tolerance of the collision detection");
static_cast<NumericParameter<Real>*>(getParameter(CONTACT_TOLERANCE))->setMinValue(0.0);
}
void CollisionDetection::cleanup()
{
for (unsigned int i = 0; i < m_collisionObjects.size(); i++)
delete m_collisionObjects[i];
m_collisionObjects.clear();
}
void CollisionDetection::addRigidBodyContact(const unsigned int rbIndex1, const unsigned int rbIndex2,
const Vector3r &cp1, const Vector3r &cp2,
const Vector3r &normal, const Real dist,
const Real restitutionCoeff, const Real frictionCoeff)
{
if (m_contactCB)
m_contactCB(RigidBodyContactType, rbIndex1, rbIndex2, cp1, cp2, normal, dist, restitutionCoeff, frictionCoeff, m_contactCBUserData);
}
void CollisionDetection::addParticleRigidBodyContact(const unsigned int particleIndex, const unsigned int rbIndex,
const Vector3r &cp1, const Vector3r &cp2,
const Vector3r &normal, const Real dist,
const Real restitutionCoeff, const Real frictionCoeff)
{
if (m_contactCB)
m_contactCB(ParticleRigidBodyContactType, particleIndex, rbIndex, cp1, cp2, normal, dist, restitutionCoeff, frictionCoeff, m_contactCBUserData);
}
void CollisionDetection::addParticleSolidContact(const unsigned int particleIndex, const unsigned int solidIndex,
const unsigned int tetIndex, const Vector3r &bary, const Vector3r &cp1, const Vector3r &cp2,
const Vector3r &normal, const Real dist, const Real restitutionCoeff, const Real frictionCoeff)
{
if (m_solidContactCB)
m_solidContactCB(ParticleSolidContactType, particleIndex, solidIndex, tetIndex, bary, cp1, cp2, normal, dist, restitutionCoeff, frictionCoeff, m_contactCBUserData);
}
void CollisionDetection::addCollisionObject(const unsigned int bodyIndex, const unsigned int bodyType)
{
CollisionObjectWithoutGeometry *co = new CollisionObjectWithoutGeometry();
co->m_bodyIndex = bodyIndex;
co->m_bodyType = bodyType;
m_collisionObjects.push_back(co);
}
void CollisionDetection::setContactCallback(CollisionDetection::ContactCallbackFunction val, void *userData)
{
m_contactCB = val;
m_contactCBUserData = userData;
}
void CollisionDetection::setSolidContactCallback(CollisionDetection::SolidContactCallbackFunction val, void *userData)
{
m_solidContactCB = val;
m_solidContactCBUserData = userData;
}
void CollisionDetection::updateAABBs(SimulationModel &model)
{
const SimulationModel::RigidBodyVector &rigidBodies = model.getRigidBodies();
const SimulationModel::TriangleModelVector &triModels = model.getTriangleModels();
const SimulationModel::TetModelVector &tetModels = model.getTetModels();
const ParticleData &pd = model.getParticles();
for (unsigned int i = 0; i < m_collisionObjects.size(); i++)
{
CollisionDetection::CollisionObject *co = m_collisionObjects[i];
updateAABB(model, co);
}
}
void CollisionDetection::updateAABB(SimulationModel &model, CollisionDetection::CollisionObject *co)
{
const SimulationModel::RigidBodyVector &rigidBodies = model.getRigidBodies();
const SimulationModel::TriangleModelVector &triModels = model.getTriangleModels();
const SimulationModel::TetModelVector &tetModels = model.getTetModels();
const ParticleData &pd = model.getParticles();
if (co->m_bodyType == CollisionDetection::CollisionObject::RigidBodyCollisionObjectType)
{
const unsigned int rbIndex = co->m_bodyIndex;
RigidBody *rb = rigidBodies[rbIndex];
const VertexData &vd = rb->getGeometry().getVertexData();
co->m_aabb.m_p[0] = vd.getPosition(0);
co->m_aabb.m_p[1] = vd.getPosition(0);
for (unsigned int j = 1; j < vd.size(); j++)
{
updateAABB(vd.getPosition(j), co->m_aabb);
}
}
else if (co->m_bodyType == CollisionDetection::CollisionObject::TriangleModelCollisionObjectType)
{
const unsigned int modelIndex = co->m_bodyIndex;
TriangleModel *tm = triModels[modelIndex];
const unsigned int offset = tm->getIndexOffset();
const IndexedFaceMesh &mesh = tm->getParticleMesh();
const unsigned int numVert = mesh.numVertices();
co->m_aabb.m_p[0] = pd.getPosition(offset);
co->m_aabb.m_p[1] = pd.getPosition(offset);
for (unsigned int j = offset + 1; j < offset + numVert; j++)
{
updateAABB(pd.getPosition(j), co->m_aabb);
}
}
else if (co->m_bodyType == CollisionDetection::CollisionObject::TetModelCollisionObjectType)
{
const unsigned int modelIndex = co->m_bodyIndex;
TetModel *tm = tetModels[modelIndex];
const unsigned int offset = tm->getIndexOffset();
const IndexedTetMesh &mesh = tm->getParticleMesh();
const unsigned int numVert = mesh.numVertices();
co->m_aabb.m_p[0] = pd.getPosition(offset);
co->m_aabb.m_p[1] = pd.getPosition(offset);
for (unsigned int j = offset + 1; j < offset + numVert; j++)
{
updateAABB(pd.getPosition(j), co->m_aabb);
}
}
// Extend AABB by tolerance
co->m_aabb.m_p[0][0] -= m_tolerance;
co->m_aabb.m_p[0][1] -= m_tolerance;
co->m_aabb.m_p[0][2] -= m_tolerance;
co->m_aabb.m_p[1][0] += m_tolerance;
co->m_aabb.m_p[1][1] += m_tolerance;
co->m_aabb.m_p[1][2] += m_tolerance;
}
void CollisionDetection::updateAABB(const Vector3r &p, AABB &aabb)
{
if (aabb.m_p[0][0] > p[0])
aabb.m_p[0][0] = p[0];
if (aabb.m_p[0][1] > p[1])
aabb.m_p[0][1] = p[1];
if (aabb.m_p[0][2] > p[2])
aabb.m_p[0][2] = p[2];
if (aabb.m_p[1][0] < p[0])
aabb.m_p[1][0] = p[0];
if (aabb.m_p[1][1] < p[1])
aabb.m_p[1][1] = p[1];
if (aabb.m_p[1][2] < p[2])
aabb.m_p[1][2] = p[2];
}