Search in sources :

Example 1 with ContactEdge

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

Example 2 with ContactEdge

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);
        }
    }
}
Also used : PolygonFixture(spacegraph.space2d.phys.fracture.PolygonFixture) BroadPhase(spacegraph.space2d.phys.collision.broadphase.BroadPhase) ContactEdge(spacegraph.space2d.phys.dynamics.contacts.ContactEdge)

Example 3 with ContactEdge

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;
        }
    });
}
Also used : PolygonFixture(spacegraph.space2d.phys.fracture.PolygonFixture) BroadPhase(spacegraph.space2d.phys.collision.broadphase.BroadPhase) ContactEdge(spacegraph.space2d.phys.dynamics.contacts.ContactEdge)

Example 4 with ContactEdge

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

Example 5 with ContactEdge

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

Aggregations

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