use of spacegraph.space2d.phys.dynamics.contacts.ContactEdge in project narchy by automenta.
the class ContactManager method addPair.
/**
* Broad-phase callback.
*
* @param proxyUserDataA
* @param proxyUserDataB
*/
public void addPair(Object proxyUserDataA, Object proxyUserDataB) {
FixtureProxy proxyA = (FixtureProxy) proxyUserDataA;
Fixture fixtureA = proxyA.fixture;
if (fixtureA == null)
// uncreated or threading issue
return;
FixtureProxy proxyB = (FixtureProxy) proxyUserDataB;
Fixture fixtureB = proxyB.fixture;
if (fixtureB == null)
// uncreated or threading issue
return;
int indexA = proxyA.childIndex;
int indexB = proxyB.childIndex;
Body2D bodyA = fixtureA.getBody();
Body2D bodyB = fixtureB.getBody();
// Are the fixtures on the same body?
if (bodyA == bodyB) {
return;
}
// TODO_ERIN use a hash table to remove a potential bottleneck when both
// bodies have a lot of contacts.
// Does a contact already exist?
ContactEdge edge = bodyB.contacts();
while (edge != null) {
if (edge.other == bodyA) {
Contact ec = edge.contact;
Fixture fA = ec.aFixture;
Fixture fB = ec.bFixture;
int iA = ec.aIndex;
int iB = ec.bIndex;
if (fA == fixtureA && iA == indexA && fB == fixtureB && iB == indexB) {
// A contact already exists.
return;
}
if (fA == fixtureB && iA == indexB && fB == fixtureA && iB == indexA) {
// A contact already exists.
return;
}
}
edge = edge.next;
}
// Does a joint override collision? is at least one body dynamic?
if (!bodyB.shouldCollide(bodyA)) {
return;
}
// Check user filtering.
if (m_contactFilter != null && !ContactFilter.shouldCollide(fixtureA, fixtureB)) {
return;
}
// Call the factory.
Contact c = popContact(fixtureA, indexA, fixtureB, indexB);
if (c == null) {
return;
}
// Contact creation may swap fixtures.
fixtureA = c.aFixture;
fixtureB = c.bFixture;
// indexA = c.aIndex;
// indexB = c.bIndex;
bodyA = fixtureA.getBody();
bodyB = fixtureB.getBody();
// Insert into the world.
c.m_prev = null;
c.m_next = m_contactList;
if (m_contactList != null) {
m_contactList.m_prev = c;
}
m_contactList = c;
// Connect to island graph.
// Connect to body A
c.m_nodeA.contact = c;
c.m_nodeA.other = bodyB;
c.m_nodeA.prev = null;
c.m_nodeA.next = bodyA.contacts;
if (bodyA.contacts != null) {
bodyA.contacts.prev = c.m_nodeA;
}
bodyA.contacts = c.m_nodeA;
// Connect to body B
c.m_nodeB.contact = c;
c.m_nodeB.other = bodyA;
c.m_nodeB.prev = null;
c.m_nodeB.next = bodyB.contacts;
if (bodyB.contacts != null) {
bodyB.contacts.prev = c.m_nodeB;
}
bodyB.contacts = c.m_nodeB;
// wake up the bodies
if (!fixtureA.isSensor() && !fixtureB.isSensor()) {
bodyA.setAwake(true);
bodyB.setAwake(true);
}
++m_contactCount;
}
use of spacegraph.space2d.phys.dynamics.contacts.ContactEdge in project narchy by automenta.
the class Body2D method setType.
/**
* Set the type of this body. This may alter the mass and velocity.
*
* @param type
*/
public void setType(BodyType type) {
if (this.type == type) {
return;
}
this.type = type;
resetMassData();
if (this.type == BodyType.STATIC) {
vel.setZero();
velAngular = 0.0f;
sweep.a0 = sweep.a;
sweep.c0.set(sweep.c);
synchronizeFixtures();
}
setAwake(true);
force.setZero();
torque = 0.0f;
// Delete the attached contacts.
ContactEdge ce = contacts;
while (ce != null) {
ContactEdge ce0 = ce;
ce = ce.next;
W.contactManager.destroy(ce0.contact);
}
contacts = null;
// Touch the proxies so that new contacts will be created (when appropriate)
BroadPhase broadPhase = W.contactManager.broadPhase;
for (Fixture f = fixtures; f != null; f = f.next) {
int proxyCount = f.m_proxyCount;
for (int i = 0; i < proxyCount; ++i) {
broadPhase.touchProxy(f.proxies[i].id);
}
}
}
use of spacegraph.space2d.phys.dynamics.contacts.ContactEdge in project narchy by automenta.
the class Body2D method setActive.
/**
* Set the active state of the body. An inactive body is not simulated and cannot be collided with
* or woken up. If you pass a flag of true, all fixtures will be added to the broad-phase. If you
* pass a flag of false, all fixtures will be removed from the broad-phase and all contacts will
* be destroyed. Fixtures and joints are otherwise unaffected. You may continue to create/destroy
* fixtures and joints on inactive bodies. Fixtures on an inactive body are implicitly inactive
* and will not participate in collisions, ray-casts, or queries. Joints connected to an inactive
* body are implicitly inactive. An inactive body is still owned by a World object and remains in
* the body list.
*
* @param flag
*/
void setActive(boolean flag) {
if (flag == isActive()) {
return;
}
W.invoke(() -> {
if (flag) {
flags |= e_activeFlag;
// Create all proxies.
BroadPhase broadPhase = W.contactManager.broadPhase;
for (Fixture f = fixtures; f != null; f = f.next) {
f.createProxies(broadPhase, this);
}
// Contacts are created the next time step.
} else {
flags &= ~e_activeFlag;
// Destroy all proxies.
BroadPhase broadPhase = W.contactManager.broadPhase;
for (Fixture f = fixtures; f != null; f = f.next) {
f.destroyProxies(broadPhase);
}
// Destroy the attached contacts.
ContactEdge ce = contacts;
while (ce != null) {
ContactEdge ce0 = ce;
ce = ce.next;
W.contactManager.destroy(ce0.contact);
}
contacts = null;
}
});
}
use of spacegraph.space2d.phys.dynamics.contacts.ContactEdge in project narchy by automenta.
the class WorldRayCastWrapper method removeJoint.
/**
* destroy a joint. This may cause the connected bodies to begin colliding.
*
* @param joint
* @warning This function is locked during callbacks.
*/
public void removeJoint(Joint j) {
if (joints.remove(j)) {
invoke(() -> {
boolean collideConnected = j.getCollideConnected();
// Disconnect from island graph.
// Wake up connected bodies.
Body2D bodyA = j.getBodyA();
bodyA.setAwake(true);
Body2D bodyB = j.getBodyB();
bodyB.setAwake(true);
// Remove from body 1.
if (j.edgeA.prev != null) {
j.edgeA.prev.next = j.edgeA.next;
}
if (j.edgeA.next != null) {
j.edgeA.next.prev = j.edgeA.prev;
}
if (j.edgeA == bodyA.joints) {
bodyA.joints = j.edgeA.next;
}
j.edgeA.prev = null;
j.edgeA.next = null;
// Remove from body 2
if (j.edgeB.prev != null) {
j.edgeB.prev.next = j.edgeB.next;
}
if (j.edgeB.next != null) {
j.edgeB.next.prev = j.edgeB.prev;
}
if (j.edgeB == bodyB.joints) {
bodyB.joints = j.edgeB.next;
}
j.edgeB.prev = null;
j.edgeB.next = null;
Joint.destroy(j);
assert (jointCount > 0);
--jointCount;
// If the joint prevents collisions, then flag any contacts for filtering.
if (!collideConnected) {
ContactEdge edge = bodyB.contacts();
while (edge != null) {
if (edge.other == bodyA) {
// Flag the contact for filtering at the next time step (where either
// body is awake).
edge.contact.flagForFiltering();
}
edge = edge.next;
}
}
});
}
}
use of spacegraph.space2d.phys.dynamics.contacts.ContactEdge in project narchy by automenta.
the class WorldRayCastWrapper method removeBody.
/**
* destroy a rigid body given a definition. No reference to the definition is retained. This
* function is locked during callbacks.
*
* @param b
* @warning This automatically deletes all associated shapes and joints.
* @warning This function is locked during callbacks.
*/
public void removeBody(Body2D b) {
if (bodies.remove(b)) {
invoke(() -> {
b.onRemoval();
b.setActive(false);
// Delete the attached joints.
JointEdge je = b.joints;
while (je != null) {
JointEdge je0 = je;
je = je.next;
if (m_destructionListener != null) {
m_destructionListener.beforeDestruct(je0.joint);
}
removeJoint(je0.joint);
b.joints = je;
}
b.joints = null;
// Delete the attached contacts.
ContactEdge ce = b.contacts;
while (ce != null) {
ContactEdge ce0 = ce;
ce = ce.next;
contactManager.destroy(ce0.contact);
}
b.contacts = null;
Fixture f = b.fixtures;
while (f != null) {
Fixture f0 = f;
f = f.next;
if (m_destructionListener != null) {
m_destructionListener.beforeDestruct(f0);
}
f0.destroyProxies(contactManager.broadPhase);
f0.destroy();
// TODO djm recycle fixtures (here or in that destroy method)
b.fixtures = f;
b.fixtureCount -= 1;
}
b.fixtures = null;
b.fixtureCount = 0;
});
}
}
Aggregations