Search in sources :

Example 1 with ContactEdge

use of com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge in project FXGL by AlmasB.

the class Fixture method refilter.

/**
 * Call this if you want to establish collision that was previously disabled by
 * ContactFilter::ShouldCollide.
 */
public void refilter() {
    // Flag associated contacts for filtering.
    ContactEdge edge = body.getContactList();
    while (edge != null) {
        Contact contact = edge.contact;
        Fixture fixtureA = contact.getFixtureA();
        Fixture fixtureB = contact.getFixtureB();
        if (fixtureA == this || fixtureB == this) {
            contact.flagForFiltering();
        }
        edge = edge.next;
    }
    World world = body.getWorld();
    if (world == null) {
        return;
    }
    // Touch each proxy so that new pairs may be created
    BroadPhase broadPhase = world.getContactManager().broadPhase;
    for (int i = 0; i < proxyCount; ++i) {
        broadPhase.touchProxy(proxies[i].proxyId);
    }
}
Also used : BroadPhase(com.almasb.fxgl.physics.box2d.collision.broadphase.BroadPhase) ContactEdge(com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge) Contact(com.almasb.fxgl.physics.box2d.dynamics.contacts.Contact)

Example 2 with ContactEdge

use of com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge in project FXGL by AlmasB.

the class World method destroyJoint.

/**
 * Destroy a joint. This may cause the connected bodies to begin colliding.
 * This function is locked during callbacks.
 *
 * @param j joint
 */
public void destroyJoint(Joint j) {
    assertNotLocked();
    boolean collideConnected = j.getCollideConnected();
    // Remove from the doubly linked list.
    if (j.m_prev != null) {
        j.m_prev.m_next = j.m_next;
    }
    if (j.m_next != null) {
        j.m_next.m_prev = j.m_prev;
    }
    if (j == m_jointList) {
        m_jointList = j.m_next;
    }
    // Disconnect from island graph.
    Body bodyA = j.getBodyA();
    Body bodyB = j.getBodyB();
    // Wake up connected bodies.
    bodyA.setAwake(true);
    bodyB.setAwake(true);
    // Remove from body 1.
    if (j.m_edgeA.prev != null) {
        j.m_edgeA.prev.next = j.m_edgeA.next;
    }
    if (j.m_edgeA.next != null) {
        j.m_edgeA.next.prev = j.m_edgeA.prev;
    }
    if (j.m_edgeA == bodyA.m_jointList) {
        bodyA.m_jointList = j.m_edgeA.next;
    }
    j.m_edgeA.prev = null;
    j.m_edgeA.next = null;
    // Remove from body 2
    if (j.m_edgeB.prev != null) {
        j.m_edgeB.prev.next = j.m_edgeB.next;
    }
    if (j.m_edgeB.next != null) {
        j.m_edgeB.next.prev = j.m_edgeB.prev;
    }
    if (j.m_edgeB == bodyB.m_jointList) {
        bodyB.m_jointList = j.m_edgeB.next;
    }
    j.m_edgeB.prev = null;
    j.m_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.getContactList();
        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;
        }
    }
}
Also used : ContactEdge(com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge)

Example 3 with ContactEdge

use of com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge in project FXGL by AlmasB.

the class World method solve.

private void solve(TimeStep step) {
    // update previous transforms
    for (Body b : bodies) {
        b.m_xf0.set(b.m_xf);
    }
    // Size the island for the worst case.
    island.init(getBodyCount(), contactManager.contactCount, jointCount, contactManager.getContactListener());
    // Clear all the island flags.
    for (Body b : bodies) {
        b.m_flags &= ~Body.e_islandFlag;
    }
    for (Contact c = contactManager.contactList; c != null; c = c.m_next) {
        c.m_flags &= ~Contact.ISLAND_FLAG;
    }
    for (Joint j = m_jointList; j != null; j = j.m_next) {
        j.m_islandFlag = false;
    }
    // Build and simulate all awake islands.
    int stackSize = getBodyCount();
    if (stack.length < stackSize) {
        stack = new Body[stackSize];
    }
    for (Body seed : bodies) {
        if ((seed.m_flags & Body.e_islandFlag) == Body.e_islandFlag) {
            continue;
        }
        if (!seed.isAwake() || !seed.isActive()) {
            continue;
        }
        // The seed can be dynamic or kinematic.
        if (seed.getType() == BodyType.STATIC) {
            continue;
        }
        // Reset island and stack.
        island.clear();
        int stackCount = 0;
        stack[stackCount++] = seed;
        seed.m_flags |= Body.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.
            Body b = stack[--stackCount];
            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.m_contactList; 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.m_fixtureA.isSensor();
                boolean sensorB = contact.m_fixtureB.isSensor();
                if (sensorA || sensorB) {
                    continue;
                }
                island.add(contact);
                contact.m_flags |= Contact.ISLAND_FLAG;
                Body other = ce.other;
                // Was the other body already added to this island?
                if ((other.m_flags & Body.e_islandFlag) == Body.e_islandFlag) {
                    continue;
                }
                assert (stackCount < stackSize);
                stack[stackCount++] = other;
                other.m_flags |= Body.e_islandFlag;
            }
            // Search all joints connect to this body.
            for (JointEdge je = b.m_jointList; je != null; je = je.next) {
                if (je.joint.m_islandFlag) {
                    continue;
                }
                Body other = je.other;
                // Don't simulate joints connected to inactive bodies.
                if (!other.isActive()) {
                    continue;
                }
                island.add(je.joint);
                je.joint.m_islandFlag = true;
                if ((other.m_flags & Body.e_islandFlag) == Body.e_islandFlag) {
                    continue;
                }
                assert (stackCount < stackSize);
                stack[stackCount++] = other;
                other.m_flags |= Body.e_islandFlag;
            }
        }
        island.solve(step, gravity, allowSleep);
        // Post solve cleanup.
        for (int i = 0; i < island.m_bodyCount; ++i) {
            // Allow static bodies to participate in other islands.
            Body b = island.m_bodies[i];
            if (b.getType() == BodyType.STATIC) {
                b.m_flags &= ~Body.e_islandFlag;
            }
        }
    }
    // Synchronize fixtures, check for out of range bodies.
    for (Body b : bodies) {
        // If a body was not in an island then it did not move.
        if ((b.m_flags & Body.e_islandFlag) == 0) {
            continue;
        }
        if (b.getType() == BodyType.STATIC) {
            continue;
        }
        // Update fixtures (for broad-phase).
        b.synchronizeFixtures();
    }
    // Look for new contacts.
    contactManager.findNewContacts();
}
Also used : JointEdge(com.almasb.fxgl.physics.box2d.dynamics.joints.JointEdge) Joint(com.almasb.fxgl.physics.box2d.dynamics.joints.Joint) Joint(com.almasb.fxgl.physics.box2d.dynamics.joints.Joint) Contact(com.almasb.fxgl.physics.box2d.dynamics.contacts.Contact) ContactEdge(com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge)

Example 4 with ContactEdge

use of com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge in project FXGL by AlmasB.

the class Body method destroyAttachedContacts.

private void destroyAttachedContacts() {
    // Delete the attached contacts.
    ContactEdge ce = m_contactList;
    while (ce != null) {
        ContactEdge ce0 = ce;
        ce = ce.next;
        world.getContactManager().destroy(ce0.contact);
    }
    m_contactList = null;
}
Also used : ContactEdge(com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge)

Example 5 with ContactEdge

use of com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge in project FXGL by AlmasB.

the class World method destroyBody.

/**
 * Destroy a rigid body.
 * This automatically deletes all associated shapes and joints.
 * This function is locked during callbacks.
 *
 * @param body body to destroy
 */
public void destroyBody(Body body) {
    assert bodies.contains(body, true);
    assertNotLocked();
    // Delete the attached joints.
    JointEdge je = body.m_jointList;
    while (je != null) {
        JointEdge je0 = je;
        je = je.next;
        if (destructionListener != null) {
            destructionListener.onDestroy(je0.joint);
        }
        destroyJoint(je0.joint);
        body.m_jointList = je;
    }
    body.m_jointList = null;
    // Delete the attached contacts.
    ContactEdge ce = body.m_contactList;
    while (ce != null) {
        ContactEdge ce0 = ce;
        ce = ce.next;
        contactManager.destroy(ce0.contact);
    }
    body.m_contactList = null;
    for (Fixture f : body.getFixtures()) {
        if (destructionListener != null) {
            destructionListener.onDestroy(f);
        }
        f.destroyProxies(contactManager.broadPhase);
        f.destroy();
    // jbox2dTODO djm recycle fixtures (here or in that destroy method)
    }
    body.getFixtures().clear();
    bodies.removeValueByIdentity(body);
// jbox2dTODO djm recycle body
}
Also used : JointEdge(com.almasb.fxgl.physics.box2d.dynamics.joints.JointEdge) ContactEdge(com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge)

Aggregations

ContactEdge (com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge)9 Contact (com.almasb.fxgl.physics.box2d.dynamics.contacts.Contact)5 Joint (com.almasb.fxgl.physics.box2d.dynamics.joints.Joint)3 BroadPhase (com.almasb.fxgl.physics.box2d.collision.broadphase.BroadPhase)2 JointEdge (com.almasb.fxgl.physics.box2d.dynamics.joints.JointEdge)2 TOIInput (com.almasb.fxgl.physics.box2d.collision.TimeOfImpact.TOIInput)1