private Contact[] m_contacts = new Contact[Settings.maxTOIContacts];
private void solveTOI(Body body) {
// Find the minimum contact.
Contact toiContact = null;
float toi = 1.0f;
Body toiOther = null;
boolean found;
int count;
int iter = 0;
boolean bullet = body.isBullet();
// Iterate until all contacts agree on the minimum TOI. We have
// to iterate because the TOI algorithm may skip some intermediate
// collisions when objects rotate through each other.
do {
count = 0;
found = false;
for (ContactEdge ce = body.m_contactList; ce != null; ce = ce.next) {
if (ce.contact == toiContact) {
continue;
}
Body other = ce.other;
BodyType type = other.getType();
// Only bullets perform TOI with dynamic bodies.
if (bullet == true) {
// Bullets only perform TOI with bodies that have their TOI resolved.
if ((other.m_flags & Body.e_toiFlag) == 0) {
continue;
}
// No repeated hits on non-static bodies
if (type != BodyType.STATIC && (ce.contact.m_flags & Contact.BULLET_HIT_FLAG) != 0) {
continue;
}
}
else if (type == BodyType.DYNAMIC) {
continue;
}
// Check for a disabled contact.
Contact contact = ce.contact;
if (contact.isEnabled() == false) {
continue;
}
// Prevent infinite looping.
if (contact.m_toiCount > 10) {
continue;
}
Fixture fixtureA = contact.m_fixtureA;
Fixture fixtureB = contact.m_fixtureB;
// Cull sensors.
if (fixtureA.isSensor() || fixtureB.isSensor()) {
continue;
}
Body bodyA = fixtureA.m_body;
Body bodyB = fixtureB.m_body;
// Compute the time of impact in interval [0, minTOI]
toiInput.proxyA.set(fixtureA.getShape());
toiInput.proxyB.set(fixtureB.getShape());
toiInput.sweepA.set(bodyA.m_sweep);
toiInput.sweepB.set(bodyB.m_sweep);
toiInput.tMax = toi;
pool.getTimeOfImpact().timeOfImpact(toiOutput, toiInput);
if (toiOutput.state == TOIOutputState.TOUCHING && toiOutput.t < toi) {
toiContact = contact;
toi = toiOutput.t;
toiOther = other;
found = true;
}
++count;
}
++iter;
}
while (found && count > 1 && iter < 50);
if (toiContact == null) {
body.advance(1.0f);
return;
}
backup.set(body.m_sweep);
body.advance(toi);
toiContact.update(m_contactManager.m_contactListener);
if (toiContact.isEnabled() == false) {
// Contact disabled. Backup and recurse.
body.m_sweep.set(backup);
solveTOI(body);
}
++toiContact.m_toiCount;
// Update all the valid contacts on this body and build a contact island.
if (m_contacts == null || m_contacts.length < Settings.maxTOIContacts){
m_contacts = new Contact[Settings.maxTOIContacts];
}
count = 0;
for (ContactEdge ce = body.m_contactList; ce != null && count < Settings.maxTOIContacts; ce = ce.next) {
Body other = ce.other;
BodyType type = other.getType();
// Only perform correction with static bodies, so the
// body won't get pushed out of the world.
if (type == BodyType.DYNAMIC) {
continue;
}
// Check for a disabled contact.
Contact contact = ce.contact;
if (contact.isEnabled() == false) {
continue;
}
Fixture fixtureA = contact.m_fixtureA;
Fixture fixtureB = contact.m_fixtureB;
// Cull sensors.
if (fixtureA.isSensor() || fixtureB.isSensor()) {
continue;
}
// The contact likely has some new contact points. The listener
// gives the user a chance to disable the contact.
if (contact != toiContact) {
contact.update(m_contactManager.m_contactListener);
}
// Did the user disable the contact?
if (contact.isEnabled() == false) {
// Skip this contact.
continue;
}
if (contact.isTouching() == false) {
continue;
}
m_contacts[count] = contact;
++count;