use of spacegraph.space2d.phys.dynamics.joints.JointEdge 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;
});
}
}
use of spacegraph.space2d.phys.dynamics.joints.JointEdge in project narchy by automenta.
the class WorldRayCastWrapper method solve.
private void solve(TimeStep step) {
m_profile.solveInit.startAccum();
m_profile.solveVelocity.startAccum();
m_profile.solvePosition.startAccum();
List<Body2D> preRemove = new FasterList(0);
bodies(b -> {
// Clear all the island flags.
b.flags &= ~Body2D.e_islandFlag;
if (!b.preUpdate()) {
preRemove.add(b);
} else {
// update previous transforms
b.transformPrev.set(b);
}
});
preRemove.forEach(this::removeBody);
preRemove.clear();
// Size the island for the worst case.
int bodyCount = bodies.size();
island.init(bodyCount, contactManager.m_contactCount, jointCount, contactManager.contactListener);
for (Contact c = contactManager.m_contactList; c != null; c = c.m_next) {
c.m_flags &= ~Contact.ISLAND_FLAG;
}
joints(j -> j.islandFlag = false);
// Build and simulate all awake islands.
int stackSize = bodyCount;
// TODO djm find a good initial stack number;
Body2D[] stack = new Body2D[stackSize];
bodies(seed -> {
if ((seed.flags & Body2D.e_islandFlag) == Body2D.e_islandFlag)
return;
if (!seed.isAwake() || !seed.isActive())
return;
// The seed can be dynamic or kinematic.
if (seed.getType() == BodyType.STATIC)
return;
// Reset island and stack.
island.clear();
int stackCount = 0;
stack[stackCount++] = seed;
seed.flags |= Body2D.e_islandFlag;
// Perform a depth first search (DFS) on the constraint graph.
while (stackCount > 0) {
// Grab the next body off the stack and add it to the island.
Body2D b = stack[--stackCount];
if (!b.isActive())
continue;
// assert (b.isActive());
island.add(b);
// Make sure the body is awake.
b.setAwake(true);
// propagate islands across static bodies.
if (b.getType() == BodyType.STATIC)
continue;
// Search all contacts connected to this body.
for (ContactEdge ce = b.contacts; ce != null; ce = ce.next) {
Contact contact = ce.contact;
// Has this contact already been added to an island?
if ((contact.m_flags & Contact.ISLAND_FLAG) == Contact.ISLAND_FLAG) {
continue;
}
// Is this contact solid and touching?
if (!contact.isEnabled() || !contact.isTouching()) {
continue;
}
// Skip sensors.
boolean sensorA = contact.aFixture.isSensor;
boolean sensorB = contact.bFixture.isSensor;
if (sensorA || sensorB) {
continue;
}
island.add(contact);
contact.m_flags |= Contact.ISLAND_FLAG;
Body2D other = ce.other;
// Was the other body already added to this island?
if ((other.flags & Body2D.e_islandFlag) == Body2D.e_islandFlag) {
continue;
}
assert (stackCount < stackSize);
stack[stackCount++] = other;
other.flags |= Body2D.e_islandFlag;
}
// Search all joints connect to this body.
for (JointEdge je = b.joints; je != null; je = je.next) {
if (je.joint.islandFlag) {
continue;
}
Body2D other = je.other;
// Don't simulate joints connected to inactive bodies.
if (!other.isActive()) {
continue;
}
island.add(je.joint);
je.joint.islandFlag = true;
if ((other.flags & Body2D.e_islandFlag) == Body2D.e_islandFlag) {
continue;
}
assert (stackCount < stackSize);
stack[stackCount++] = other;
other.flags |= Body2D.e_islandFlag;
}
}
island.solve(m_profile, step, m_gravity, m_allowSleep);
// Post solve cleanup.
for (int i = 0; i < island.m_bodyCount; ++i) {
// Allow static bodies to participate in other islands.
Body2D b = island.bodies[i];
if (b.getType() == BodyType.STATIC) {
b.flags &= ~Body2D.e_islandFlag;
}
}
});
m_profile.solveInit.endAccum();
m_profile.solveVelocity.endAccum();
m_profile.solvePosition.endAccum();
broadphaseTimer.reset();
// Synchronize fixtures, check for out of range bodies.
bodies(b -> {
// If a body was not in an island then it did not move.
if ((b.flags & Body2D.e_islandFlag) == 0 || b.getType() == BodyType.STATIC)
return;
// Update fixtures (for broad-phase).
b.synchronizeFixtures();
b.postUpdate();
});
// Look for new contacts.
contactManager.findNewContacts();
m_profile.broadphase.record(broadphaseTimer.getMilliseconds());
}
Aggregations