Search in sources :

Example 1 with JointEdge

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;
        });
    }
}
Also used : JointEdge(spacegraph.space2d.phys.dynamics.joints.JointEdge) ContactEdge(spacegraph.space2d.phys.dynamics.contacts.ContactEdge)

Example 2 with JointEdge

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());
}
Also used : FasterList(jcog.list.FasterList) JointEdge(spacegraph.space2d.phys.dynamics.joints.JointEdge) Joint(spacegraph.space2d.phys.dynamics.joints.Joint) Contact(spacegraph.space2d.phys.dynamics.contacts.Contact) ContactEdge(spacegraph.space2d.phys.dynamics.contacts.ContactEdge)

Aggregations

ContactEdge (spacegraph.space2d.phys.dynamics.contacts.ContactEdge)2 JointEdge (spacegraph.space2d.phys.dynamics.joints.JointEdge)2 FasterList (jcog.list.FasterList)1 Contact (spacegraph.space2d.phys.dynamics.contacts.Contact)1 Joint (spacegraph.space2d.phys.dynamics.joints.Joint)1