Search in sources :

Example 1 with Contact

use of spacegraph.space2d.phys.dynamics.contacts.Contact in project narchy by automenta.

the class ContactManager method popContact.

public Contact popContact(Fixture fixtureA, int indexA, Fixture fixtureB, int indexB) {
    final ShapeType type1 = fixtureA.type();
    final ShapeType type2 = fixtureB.type();
    final ContactRegister reg = contactStacks[type1.ordinal()][type2.ordinal()];
    if (reg != null) {
        if (reg.primary) {
            Contact c = reg.creator.pop();
            c.init(fixtureA, indexA, fixtureB, indexB);
            return c;
        } else {
            Contact c = reg.creator.pop();
            c.init(fixtureB, indexB, fixtureA, indexA);
            return c;
        }
    } else {
        return null;
    }
}
Also used : ShapeType(spacegraph.space2d.phys.collision.shapes.ShapeType) ContactRegister(spacegraph.space2d.phys.dynamics.contacts.ContactRegister) Contact(spacegraph.space2d.phys.dynamics.contacts.Contact)

Example 2 with Contact

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

Example 3 with Contact

use of spacegraph.space2d.phys.dynamics.contacts.Contact 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)

Example 4 with Contact

use of spacegraph.space2d.phys.dynamics.contacts.Contact in project narchy by automenta.

the class ContactManager method collide.

/**
 * This is the top level collision call for the time step. Here all the narrow phase collision is
 * processed for the world contact list.
 */
public void collide() {
    // Update awake contacts.
    Contact c = m_contactList;
    while (c != null) {
        Fixture fixtureA = c.aFixture;
        Fixture fixtureB = c.bFixture;
        int indexA = c.aIndex;
        int indexB = c.bIndex;
        Body2D bodyA = fixtureA.getBody();
        Body2D bodyB = fixtureB.getBody();
        // is this contact flagged for filtering?
        if ((c.m_flags & Contact.FILTER_FLAG) == Contact.FILTER_FLAG) {
            // Should these bodies collide?
            if (!bodyB.shouldCollide(bodyA)) {
                Contact cNuke = c;
                c = cNuke.next();
                destroy(cNuke);
                continue;
            }
            // Check user filtering.
            if (m_contactFilter != null && !ContactFilter.shouldCollide(fixtureA, fixtureB)) {
                Contact cNuke = c;
                c = cNuke.next();
                destroy(cNuke);
                continue;
            }
            // Clear the filtering flag.
            c.m_flags &= ~Contact.FILTER_FLAG;
        }
        // At least one body must be awake and it must be dynamic or kinematic.
        if (!(bodyA.isAwake() && bodyA.type != BodyType.STATIC) && !(bodyB.isAwake() && bodyB.type != BodyType.STATIC)) {
            c = c.next();
            continue;
        }
        int proxyIdA = fixtureA.proxies[indexA].id;
        int proxyIdB = fixtureB.proxies[indexB].id;
        boolean overlap = broadPhase.testOverlap(proxyIdA, proxyIdB);
        // Here we destroy contacts that cease to overlap in the broad-phase.
        if (!overlap) {
            Contact cNuke = c;
            c = cNuke.next();
            destroy(cNuke);
            continue;
        }
        // The contact persists.
        c.update(contactListener);
        c = c.next();
    }
}
Also used : Contact(spacegraph.space2d.phys.dynamics.contacts.Contact)

Example 5 with Contact

use of spacegraph.space2d.phys.dynamics.contacts.Contact in project narchy by automenta.

the class Body2D method removeFixture.

/**
 * Destroy a fixture. This removes the fixture from the broad-phase and destroys all contacts
 * associated with this fixture. This will automatically adjust the mass of the body if the body
 * is dynamic and the fixture has positive density. All fixtures attached to a body are implicitly
 * destroyed when the body is destroyed.
 *
 * @param fixture the fixture to be removed.
 * @warning This function is locked during callbacks.
 */
public final void removeFixture(Fixture fixture) {
    W.invoke(() -> {
        assert (fixture.body == this);
        // Remove the fixture from this body's singly linked list.
        assert (fixtureCount > 0);
        // W.invokeLater(() -> {
        Fixture node = fixtures;
        // java change
        Fixture last = null;
        boolean found = false;
        while (node != null) {
            if (node == fixture) {
                node = fixture.next;
                found = true;
                break;
            }
            last = node;
            node = node.next;
        }
        // You tried to remove a shape that is not attached to this body.
        assert (found);
        // java change, remove it from the list
        if (last == null) {
            fixtures = fixture.next;
        } else {
            last.next = fixture.next;
        }
        // Destroy any contacts associated with the fixture.
        ContactEdge edge = contacts;
        while (edge != null) {
            Contact c = edge.contact;
            edge = edge.next;
            Fixture fixtureA = c.aFixture;
            Fixture fixtureB = c.bFixture;
            if (fixture == fixtureA || fixture == fixtureB) {
                // This destroys the contact and removes it from
                // this body's contact list.
                W.contactManager.destroy(c);
            }
        }
        if ((flags & e_activeFlag) == e_activeFlag) {
            BroadPhase broadPhase = W.contactManager.broadPhase;
            fixture.destroyProxies(broadPhase);
        }
        fixture.destroy();
        fixture.body = null;
        fixture.next = null;
        --fixtureCount;
        // Reset the mass data.
        resetMassData();
    });
}
Also used : PolygonFixture(spacegraph.space2d.phys.fracture.PolygonFixture) BroadPhase(spacegraph.space2d.phys.collision.broadphase.BroadPhase) ContactEdge(spacegraph.space2d.phys.dynamics.contacts.ContactEdge) Contact(spacegraph.space2d.phys.dynamics.contacts.Contact)

Aggregations

Contact (spacegraph.space2d.phys.dynamics.contacts.Contact)7 ContactEdge (spacegraph.space2d.phys.dynamics.contacts.ContactEdge)5 BroadPhase (spacegraph.space2d.phys.collision.broadphase.BroadPhase)2 Joint (spacegraph.space2d.phys.dynamics.joints.Joint)2 PolygonFixture (spacegraph.space2d.phys.fracture.PolygonFixture)2 FasterList (jcog.list.FasterList)1 TimeOfImpact (spacegraph.space2d.phys.collision.TimeOfImpact)1 ShapeType (spacegraph.space2d.phys.collision.shapes.ShapeType)1 ContactRegister (spacegraph.space2d.phys.dynamics.contacts.ContactRegister)1 JointEdge (spacegraph.space2d.phys.dynamics.joints.JointEdge)1