Search in sources :

Example 1 with Transform

use of com.almasb.fxgl.physics.box2d.common.Transform in project FXGL by AlmasB.

the class Contact method update.

public void update(ContactListener listener) {
    oldManifold.set(m_manifold);
    // Re-enable this contact.
    m_flags |= ENABLED_FLAG;
    boolean wasTouching = (m_flags & TOUCHING_FLAG) == TOUCHING_FLAG;
    boolean sensorA = m_fixtureA.isSensor();
    boolean sensorB = m_fixtureB.isSensor();
    boolean sensor = sensorA || sensorB;
    Body bodyA = m_fixtureA.getBody();
    Body bodyB = m_fixtureB.getBody();
    Transform xfA = bodyA.getTransform();
    Transform xfB = bodyB.getTransform();
    boolean touching;
    if (sensor) {
        Shape shapeA = m_fixtureA.getShape();
        Shape shapeB = m_fixtureB.getShape();
        touching = GenericCollision.testOverlap(pool, shapeA, m_indexA, shapeB, m_indexB, xfA, xfB);
        // Sensors don't generate manifolds.
        m_manifold.pointCount = 0;
    } else {
        evaluate(m_manifold, xfA, xfB);
        touching = m_manifold.pointCount > 0;
        // stored impulses to warm start the solver.
        for (int i = 0; i < m_manifold.pointCount; ++i) {
            ManifoldPoint mp2 = m_manifold.points[i];
            mp2.normalImpulse = 0.0f;
            mp2.tangentImpulse = 0.0f;
            ContactID id2 = mp2.id;
            for (int j = 0; j < oldManifold.pointCount; ++j) {
                ManifoldPoint mp1 = oldManifold.points[j];
                if (mp1.id.isEqual(id2)) {
                    mp2.normalImpulse = mp1.normalImpulse;
                    mp2.tangentImpulse = mp1.tangentImpulse;
                    break;
                }
            }
        }
        if (touching != wasTouching) {
            bodyA.setAwake(true);
            bodyB.setAwake(true);
        }
    }
    if (touching) {
        m_flags |= TOUCHING_FLAG;
    } else {
        m_flags &= ~TOUCHING_FLAG;
    }
    if (listener == null) {
        return;
    }
    if (!wasTouching && touching) {
        listener.beginContact(this);
    }
    if (wasTouching && !touching) {
        listener.endContact(this);
    }
    if (!sensor && touching) {
        listener.preSolve(this, oldManifold);
    }
}
Also used : Shape(com.almasb.fxgl.physics.box2d.collision.shapes.Shape) ManifoldPoint(com.almasb.fxgl.physics.box2d.collision.ManifoldPoint) ContactID(com.almasb.fxgl.physics.box2d.collision.ContactID) Transform(com.almasb.fxgl.physics.box2d.common.Transform) Body(com.almasb.fxgl.physics.box2d.dynamics.Body) ManifoldPoint(com.almasb.fxgl.physics.box2d.collision.ManifoldPoint)

Example 2 with Transform

use of com.almasb.fxgl.physics.box2d.common.Transform in project FXGL by AlmasB.

the class Distance method distance.

/**
 * Compute the closest points between two shapes. Supports any combination of: CircleShape and
 * PolygonShape. The simplex cache is input/output. On the first call set SimplexCache.count to
 * zero.
 */
@SuppressWarnings("PMD.EmptyIfStmt")
public final void distance(final DistanceOutput output, final SimplexCache cache, final DistanceInput input) {
    final DistanceProxy proxyA = input.proxyA;
    final DistanceProxy proxyB = input.proxyB;
    Transform transformA = input.transformA;
    Transform transformB = input.transformB;
    // Initialize the simplex.
    simplex.readCache(cache, proxyA, transformA, proxyB, transformB);
    // Get simplex vertices as an array.
    SimplexVertex[] vertices = simplex.vertices;
    // These store the vertices of the last simplex so that we
    // can check for duplicates and prevent cycling.
    // (pooled above)
    int saveCount = 0;
    simplex.getClosestPoint(closestPoint);
    float distanceSqr1 = closestPoint.lengthSquared();
    float distanceSqr2 = distanceSqr1;
    // Main iteration loop
    int iter = 0;
    while (iter < MAX_ITERS) {
        // Copy simplex so we can identify duplicates.
        saveCount = simplex.m_count;
        for (int i = 0; i < saveCount; i++) {
            saveA[i] = vertices[i].indexA;
            saveB[i] = vertices[i].indexB;
        }
        switch(simplex.m_count) {
            case 1:
                break;
            case 2:
                simplex.solve2();
                break;
            case 3:
                simplex.solve3();
                break;
            default:
                assert false;
        }
        // If we have 3 points, then the origin is in the corresponding triangle.
        if (simplex.m_count == 3) {
            break;
        }
        // Compute closest point.
        simplex.getClosestPoint(closestPoint);
        distanceSqr2 = closestPoint.lengthSquared();
        // ensure progress
        if (distanceSqr2 >= distanceSqr1) {
        // break;
        }
        distanceSqr1 = distanceSqr2;
        // get search direction;
        simplex.getSearchDirection(d);
        // Ensure the search direction is numerically fit.
        if (d.lengthSquared() < JBoxSettings.EPSILON * JBoxSettings.EPSILON) {
            // to determine if the origin is contained in the CSO or very close to it.
            break;
        }
        /*
       * SimplexVertex* vertex = vertices + simplex.m_count; vertex.indexA =
       * proxyA.GetSupport(MulT(transformA.R, -d)); vertex.wA = Mul(transformA,
       * proxyA.GetVertex(vertex.indexA)); Vec2 wBLocal; vertex.indexB =
       * proxyB.GetSupport(MulT(transformB.R, d)); vertex.wB = Mul(transformB,
       * proxyB.GetVertex(vertex.indexB)); vertex.w = vertex.wB - vertex.wA;
       */
        // Compute a tentative new simplex vertex using support points.
        SimplexVertex vertex = vertices[simplex.m_count];
        Rotation.mulTransUnsafe(transformA.q, d.negateLocal(), temp);
        vertex.indexA = proxyA.getSupport(temp);
        Transform.mulToOutUnsafe(transformA, proxyA.getVertex(vertex.indexA), vertex.wA);
        // Vec2 wBLocal;
        Rotation.mulTransUnsafe(transformB.q, d.negateLocal(), temp);
        vertex.indexB = proxyB.getSupport(temp);
        Transform.mulToOutUnsafe(transformB, proxyB.getVertex(vertex.indexB), vertex.wB);
        vertex.w.set(vertex.wB).subLocal(vertex.wA);
        // Iteration count is equated to the number of support point calls.
        ++iter;
        // Check for duplicate support points. This is the main termination criteria.
        boolean duplicate = false;
        for (int i = 0; i < saveCount; ++i) {
            if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i]) {
                duplicate = true;
                break;
            }
        }
        // If we found a duplicate support point we must exit to avoid cycling.
        if (duplicate) {
            break;
        }
        // New vertex is ok and needed.
        ++simplex.m_count;
    }
    // Prepare output.
    simplex.getWitnessPoints(output.pointA, output.pointB);
    output.distance = output.pointA.distanceF(output.pointB);
    output.iterations = iter;
    // Cache the simplex.
    simplex.writeCache(cache);
    // Apply radii if requested.
    if (input.useRadii) {
        float rA = proxyA.m_radius;
        float rB = proxyB.m_radius;
        if (output.distance > rA + rB && output.distance > JBoxSettings.EPSILON) {
            // Shapes are still no overlapped.
            // Move the witness points to the outer surface.
            output.distance -= rA + rB;
            normal.set(output.pointB).subLocal(output.pointA);
            normal.getLengthAndNormalize();
            temp.set(normal).mulLocal(rA);
            output.pointA.addLocal(temp);
            temp.set(normal).mulLocal(rB);
            output.pointB.subLocal(temp);
        } else {
            // Shapes are overlapped when radii are considered.
            // Move the witness points to the middle.
            // Vec2 p = 0.5f * (output.pointA + output.pointB);
            output.pointA.addLocal(output.pointB).mulLocal(.5f);
            output.pointB.set(output.pointA);
            output.distance = 0.0f;
        }
    }
}
Also used : Transform(com.almasb.fxgl.physics.box2d.common.Transform)

Example 3 with Transform

use of com.almasb.fxgl.physics.box2d.common.Transform in project FXGL by AlmasB.

the class ParticleSystem method solveRigid.

private void solveRigid(final TimeStep step) {
    for (ParticleGroup group = m_groupList; group != null; group = group.getNext()) {
        if ((group.m_groupFlags & ParticleGroupType.b2_rigidParticleGroup) != 0) {
            group.updateStatistics();
            Vec2 temp = tempVec;
            Vec2 cross = tempVec2;
            Rotation rotation = tempRotation;
            rotation.set(step.dt * group.m_angularVelocity);
            Rotation.mulToOutUnsafe(rotation, group.m_center, cross);
            temp.set(group.m_linearVelocity).mulLocal(step.dt).addLocal(group.m_center).subLocal(cross);
            tempXf.p.set(temp);
            tempXf.q.set(rotation);
            Transform.mulToOut(tempXf, group.m_transform, group.m_transform);
            final Transform velocityTransform = tempXf2;
            velocityTransform.p.x = step.inv_dt * tempXf.p.x;
            velocityTransform.p.y = step.inv_dt * tempXf.p.y;
            velocityTransform.q.s = step.inv_dt * tempXf.q.s;
            velocityTransform.q.c = step.inv_dt * (tempXf.q.c - 1);
            for (int i = group.m_firstIndex; i < group.m_lastIndex; i++) {
                Transform.mulToOutUnsafe(velocityTransform, m_positionBuffer.data[i], m_velocityBuffer.data[i]);
            }
        }
    }
}
Also used : Vec2(com.almasb.fxgl.core.math.Vec2) Transform(com.almasb.fxgl.physics.box2d.common.Transform) Rotation(com.almasb.fxgl.physics.box2d.common.Rotation)

Example 4 with Transform

use of com.almasb.fxgl.physics.box2d.common.Transform in project FXGL by AlmasB.

the class ParticleSystem method createParticleGroup.

@SuppressWarnings("PMD.DontUseFloatTypeForLoopIndices")
public ParticleGroup createParticleGroup(ParticleGroupDef groupDef) {
    float stride = getParticleStride();
    final Transform identity = tempTransform;
    identity.setIdentity();
    Transform transform = tempTransform2;
    transform.setIdentity();
    int firstIndex = m_count;
    if (groupDef.getShape() != null) {
        final ParticleDef particleDef = tempParticleDef;
        particleDef.setTypeFlags(groupDef.getTypeFlags());
        particleDef.color = groupDef.getColor();
        particleDef.setUserData(groupDef.getUserData());
        Shape shape = groupDef.getShape();
        transform.set(groupDef.getPosition(), groupDef.getAngle());
        AABB aabb = temp;
        int childCount = shape.getChildCount();
        for (int childIndex = 0; childIndex < childCount; childIndex++) {
            if (childIndex == 0) {
                shape.computeAABB(aabb, identity, childIndex);
            } else {
                AABB childAABB = temp2;
                shape.computeAABB(childAABB, identity, childIndex);
                aabb.combine(childAABB);
            }
        }
        final float upperBoundY = aabb.upperBound.y;
        final float upperBoundX = aabb.upperBound.x;
        for (float y = FXGLMath.floor(aabb.lowerBound.y / stride) * stride; y < upperBoundY; y += stride) {
            for (float x = FXGLMath.floor(aabb.lowerBound.x / stride) * stride; x < upperBoundX; x += stride) {
                Vec2 p = tempVec;
                p.x = x;
                p.y = y;
                if (shape.containsPoint(identity, p)) {
                    Transform.mulToOut(transform, p, p);
                    particleDef.position.x = p.x;
                    particleDef.position.y = p.y;
                    p.subLocal(groupDef.getPosition());
                    Vec2.crossToOutUnsafe(groupDef.getAngularVelocity(), p, particleDef.velocity);
                    particleDef.velocity.addLocal(groupDef.getLinearVelocity());
                    createParticle(particleDef);
                }
            }
        }
    }
    int lastIndex = m_count;
    ParticleGroup group = new ParticleGroup();
    group.m_system = this;
    group.m_firstIndex = firstIndex;
    group.m_lastIndex = lastIndex;
    group.m_groupFlags = groupDef.getGroupFlags();
    group.m_strength = groupDef.getStrength();
    group.m_userData = groupDef.getUserData();
    group.m_transform.set(transform);
    group.m_destroyAutomatically = groupDef.isDestroyAutomatically();
    group.m_prev = null;
    group.m_next = m_groupList;
    if (m_groupList != null) {
        m_groupList.m_prev = group;
    }
    m_groupList = group;
    ++m_groupCount;
    for (int i = firstIndex; i < lastIndex; i++) {
        m_groupBuffer[i] = group;
    }
    updateContacts(true);
    if ((groupDef.getTypeFlags() & k_pairFlags) != 0) {
        for (int k = 0; k < m_contactCount; k++) {
            ParticleContact contact = m_contactBuffer[k];
            int a = contact.indexA;
            int b = contact.indexB;
            if (a > b) {
                int temp = a;
                a = b;
                b = temp;
            }
            if (firstIndex <= a && b < lastIndex) {
                if (m_pairCount >= m_pairCapacity) {
                    int oldCapacity = m_pairCapacity;
                    int newCapacity = m_pairCount != 0 ? 2 * m_pairCount : JBoxSettings.minParticleBufferCapacity;
                    m_pairBuffer = reallocateBuffer(Pair.class, m_pairBuffer, oldCapacity, newCapacity);
                    m_pairCapacity = newCapacity;
                }
                Pair pair = m_pairBuffer[m_pairCount];
                pair.indexA = a;
                pair.indexB = b;
                pair.flags = contact.flags;
                pair.strength = groupDef.getStrength();
                pair.distance = m_positionBuffer.data[a].distanceF(m_positionBuffer.data[b]);
                m_pairCount++;
            }
        }
    }
    if ((groupDef.getTypeFlags() & k_triadFlags) != 0) {
        VoronoiDiagram diagram = new VoronoiDiagram(lastIndex - firstIndex);
        for (int i = firstIndex; i < lastIndex; i++) {
            diagram.addGenerator(m_positionBuffer.data[i], i);
        }
        diagram.generate(stride / 2);
        createParticleGroupCallback.system = this;
        createParticleGroupCallback.def = groupDef;
        createParticleGroupCallback.firstIndex = firstIndex;
        diagram.getNodes(createParticleGroupCallback);
    }
    if ((groupDef.getGroupFlags() & ParticleGroupType.b2_solidParticleGroup) != 0) {
        computeDepthForGroup(group);
    }
    return group;
}
Also used : Shape(com.almasb.fxgl.physics.box2d.collision.shapes.Shape) Vec2(com.almasb.fxgl.core.math.Vec2) Transform(com.almasb.fxgl.physics.box2d.common.Transform) AABB(com.almasb.fxgl.physics.box2d.collision.AABB)

Example 5 with Transform

use of com.almasb.fxgl.physics.box2d.common.Transform in project FXGL by AlmasB.

the class Body method synchronizeFixtures.

void synchronizeFixtures() {
    final Transform xf1 = pxf;
    // xf1.position = m_sweep.c0 - Mul(xf1.R, m_sweep.localCenter);
    // xf1.q.set(m_sweep.a0);
    // Rot.mulToOutUnsafe(xf1.q, m_sweep.localCenter, xf1.p);
    // xf1.p.mulLocal(-1).addLocal(m_sweep.c0);
    // inlined:
    xf1.q.set(m_sweep.a0);
    xf1.p.x = m_sweep.c0.x - xf1.q.c * m_sweep.localCenter.x + xf1.q.s * m_sweep.localCenter.y;
    xf1.p.y = m_sweep.c0.y - xf1.q.s * m_sweep.localCenter.x - xf1.q.c * m_sweep.localCenter.y;
    for (Fixture f : fixtures) {
        f.synchronize(world.getContactManager().broadPhase, xf1, m_xf);
    }
}
Also used : Transform(com.almasb.fxgl.physics.box2d.common.Transform)

Aggregations

Transform (com.almasb.fxgl.physics.box2d.common.Transform)7 Vec2 (com.almasb.fxgl.core.math.Vec2)3 Shape (com.almasb.fxgl.physics.box2d.collision.shapes.Shape)2 Rotation (com.almasb.fxgl.physics.box2d.common.Rotation)2 AABB (com.almasb.fxgl.physics.box2d.collision.AABB)1 ContactID (com.almasb.fxgl.physics.box2d.collision.ContactID)1 ManifoldPoint (com.almasb.fxgl.physics.box2d.collision.ManifoldPoint)1 PolygonShape (com.almasb.fxgl.physics.box2d.collision.shapes.PolygonShape)1 Body (com.almasb.fxgl.physics.box2d.dynamics.Body)1