Beispiel #1
0
    // Algorithm:
    // 1. Classify v1 and v2
    // 2. Classify polygon centroid as front or back
    // 3. Flip normal if necessary
    // 4. Initialize normal range to [-pi, pi] about face normal
    // 5. Adjust normal range according to adjacent edges
    // 6. Visit each separating axes, only accept axes within the range
    // 7. Return if _any_ axis indicates separation
    // 8. Clip
    public void Collide(b2Manifold manifold, b2EdgeShape edgeA, b2Transform xfA, b2PolygonShape polygonB, b2Transform xfB)
    {
        m_xf = Utils.b2MulT(xfA, xfB);

        m_centroidB = Utils.b2Mul(m_xf, polygonB.m_centroid);

        m_v0 = edgeA.m_vertex0;
        m_v1 = edgeA.m_vertex1;
        m_v2 = edgeA.m_vertex2;
        m_v3 = edgeA.m_vertex3;

        bool hasVertex0 = edgeA.m_hasVertex0;
        bool hasVertex3 = edgeA.m_hasVertex3;

        b2Vec2 edge1 = m_v2 - m_v1;

        edge1.Normalize();
        m_normal1.Set(edge1.y, -edge1.x);
        float offset1 = Utils.b2Dot(m_normal1, m_centroidB - m_v1);
        float offset0 = 0.0f;
        float offset2 = 0.0f;
        bool  convex1 = false;
        bool  convex2 = false;

        // Is there a preceding edge?
        if (hasVertex0)
        {
            b2Vec2 edge0 = m_v1 - m_v0;
            edge0.Normalize();
            m_normal0.Set(edge0.y, -edge0.x);
            convex1 = Utils.b2Cross(edge0, edge1) >= 0.0f;
            offset0 = Utils.b2Dot(m_normal0, m_centroidB - m_v0);
        }

        // Is there a following edge?
        if (hasVertex3)
        {
            b2Vec2 edge2 = m_v3 - m_v2;
            edge2.Normalize();
            m_normal2.Set(edge2.y, -edge2.x);
            convex2 = Utils.b2Cross(edge1, edge2) > 0.0f;
            offset2 = Utils.b2Dot(m_normal2, m_centroidB - m_v2);
        }

        // Determine front or back collision. Determine collision normal limits.
        if (hasVertex0 && hasVertex3)
        {
            if (convex1 && convex2)
            {
                m_front = offset0 >= 0.0f || offset1 >= 0.0f || offset2 >= 0.0f;
                if (m_front)
                {
                    m_normal     = m_normal1;
                    m_lowerLimit = m_normal0;
                    m_upperLimit = m_normal2;
                }
                else
                {
                    m_normal     = -m_normal1;
                    m_lowerLimit = -m_normal1;
                    m_upperLimit = -m_normal1;
                }
            }
            else if (convex1)
            {
                m_front = offset0 >= 0.0f || (offset1 >= 0.0f && offset2 >= 0.0f);
                if (m_front)
                {
                    m_normal     = m_normal1;
                    m_lowerLimit = m_normal0;
                    m_upperLimit = m_normal1;
                }
                else
                {
                    m_normal     = -m_normal1;
                    m_lowerLimit = -m_normal2;
                    m_upperLimit = -m_normal1;
                }
            }
            else if (convex2)
            {
                m_front = offset2 >= 0.0f || (offset0 >= 0.0f && offset1 >= 0.0f);
                if (m_front)
                {
                    m_normal     = m_normal1;
                    m_lowerLimit = m_normal1;
                    m_upperLimit = m_normal2;
                }
                else
                {
                    m_normal     = -m_normal1;
                    m_lowerLimit = -m_normal1;
                    m_upperLimit = -m_normal0;
                }
            }
            else
            {
                m_front = offset0 >= 0.0f && offset1 >= 0.0f && offset2 >= 0.0f;
                if (m_front)
                {
                    m_normal     = m_normal1;
                    m_lowerLimit = m_normal1;
                    m_upperLimit = m_normal1;
                }
                else
                {
                    m_normal     = -m_normal1;
                    m_lowerLimit = -m_normal2;
                    m_upperLimit = -m_normal0;
                }
            }
        }
        else if (hasVertex0)
        {
            if (convex1)
            {
                m_front = offset0 >= 0.0f || offset1 >= 0.0f;
                if (m_front)
                {
                    m_normal     = m_normal1;
                    m_lowerLimit = m_normal0;
                    m_upperLimit = -m_normal1;
                }
                else
                {
                    m_normal     = -m_normal1;
                    m_lowerLimit = m_normal1;
                    m_upperLimit = -m_normal1;
                }
            }
            else
            {
                m_front = offset0 >= 0.0f && offset1 >= 0.0f;
                if (m_front)
                {
                    m_normal     = m_normal1;
                    m_lowerLimit = m_normal1;
                    m_upperLimit = -m_normal1;
                }
                else
                {
                    m_normal     = -m_normal1;
                    m_lowerLimit = m_normal1;
                    m_upperLimit = -m_normal0;
                }
            }
        }
        else if (hasVertex3)
        {
            if (convex2)
            {
                m_front = offset1 >= 0.0f || offset2 >= 0.0f;
                if (m_front)
                {
                    m_normal     = m_normal1;
                    m_lowerLimit = -m_normal1;
                    m_upperLimit = m_normal2;
                }
                else
                {
                    m_normal     = -m_normal1;
                    m_lowerLimit = -m_normal1;
                    m_upperLimit = m_normal1;
                }
            }
            else
            {
                m_front = offset1 >= 0.0f && offset2 >= 0.0f;
                if (m_front)
                {
                    m_normal     = m_normal1;
                    m_lowerLimit = -m_normal1;
                    m_upperLimit = m_normal1;
                }
                else
                {
                    m_normal     = -m_normal1;
                    m_lowerLimit = -m_normal2;
                    m_upperLimit = m_normal1;
                }
            }
        }
        else
        {
            m_front = offset1 >= 0.0f;
            if (m_front)
            {
                m_normal     = m_normal1;
                m_lowerLimit = -m_normal1;
                m_upperLimit = -m_normal1;
            }
            else
            {
                m_normal     = -m_normal1;
                m_lowerLimit = m_normal1;
                m_upperLimit = m_normal1;
            }
        }

        // Get polygonB in frameA
        m_polygonB.count = polygonB.m_count;
        for (int i = 0; i < polygonB.m_count; ++i)
        {
            m_polygonB.vertices[i] = Utils.b2Mul(m_xf, polygonB.m_vertices[i]);
            m_polygonB.normals[i]  = Utils.b2Mul(m_xf.q, polygonB.m_normals[i]);
        }

        m_radius = polygonB.m_radius + edgeA.m_radius;

        manifold.pointCount = 0;

        b2EPAxis edgeAxis = ComputeEdgeSeparation();

        // If no valid normal can be found than this edge should not collide.
        if (edgeAxis.type == b2EPAxis.Type.e_unknown)
        {
            return;
        }

        if (edgeAxis.separation > m_radius)
        {
            return;
        }

        b2EPAxis polygonAxis = ComputePolygonSeparation();

        if (polygonAxis.type != b2EPAxis.Type.e_unknown && polygonAxis.separation > m_radius)
        {
            return;
        }

        // Use hysteresis for jitter reduction.
        const float k_relativeTol = 0.98f;
        const float k_absoluteTol = 0.001f;

        b2EPAxis primaryAxis = new b2EPAxis();

        if (polygonAxis.type == b2EPAxis.Type.e_unknown)
        {
            primaryAxis = edgeAxis;
        }
        else if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol)
        {
            primaryAxis = polygonAxis;
        }
        else
        {
            primaryAxis = edgeAxis;
        }

        b2ClipVertex[]  ie = Arrays.InitializeWithDefaultInstances <b2ClipVertex>(2);
        b2ReferenceFace rf = new b2ReferenceFace();

        if (primaryAxis.type == b2EPAxis.Type.e_edgeA)
        {
            manifold.type = b2Manifold.Type.e_faceA;

            // Search for the polygon normal that is most anti-parallel to the edge normal.
            int   bestIndex = 0;
            float bestValue = Utils.b2Dot(m_normal, m_polygonB.normals[0]);
            for (int i = 1; i < m_polygonB.count; ++i)
            {
                float value = Utils.b2Dot(m_normal, m_polygonB.normals[i]);
                if (value < bestValue)
                {
                    bestValue = value;
                    bestIndex = i;
                }
            }

            int i1 = bestIndex;
            int i2 = i1 + 1 < m_polygonB.count ? i1 + 1 : 0;

            ie[0].v            = m_polygonB.vertices[i1];
            ie[0].id.cf.indexA = 0;
            ie[0].id.cf.indexB = (byte)i1;
            ie[0].id.cf.typeA  = (int)b2ContactFeature.Type.e_face;
            ie[0].id.cf.typeB  = (int)b2ContactFeature.Type.e_vertex;

            ie[1].v            = m_polygonB.vertices[i2];
            ie[1].id.cf.indexA = 0;
            ie[1].id.cf.indexB = (byte)i2;
            ie[1].id.cf.typeA  = (int)b2ContactFeature.Type.e_face;
            ie[1].id.cf.typeB  = (int)b2ContactFeature.Type.e_vertex;

            if (m_front)
            {
                rf.i1     = 0;
                rf.i2     = 1;
                rf.v1     = m_v1;
                rf.v2     = m_v2;
                rf.normal = m_normal1;
            }
            else
            {
                rf.i1     = 1;
                rf.i2     = 0;
                rf.v1     = m_v2;
                rf.v2     = m_v1;
                rf.normal = -m_normal1;
            }
        }
        else
        {
            manifold.type = b2Manifold.Type.e_faceB;

            ie[0].v            = m_v1;
            ie[0].id.cf.indexA = 0;
            ie[0].id.cf.indexB = (byte)primaryAxis.index;
            ie[0].id.cf.typeA  = (int)b2ContactFeature.Type.e_vertex;
            ie[0].id.cf.typeB  = (int)b2ContactFeature.Type.e_face;

            ie[1].v            = m_v2;
            ie[1].id.cf.indexA = 0;
            ie[1].id.cf.indexB = (byte)primaryAxis.index;
            ie[1].id.cf.typeA  = (int)b2ContactFeature.Type.e_vertex;
            ie[1].id.cf.typeB  = (int)b2ContactFeature.Type.e_face;

            rf.i1     = primaryAxis.index;
            rf.i2     = rf.i1 + 1 < m_polygonB.count ? rf.i1 + 1 : 0;
            rf.v1     = m_polygonB.vertices[rf.i1];
            rf.v2     = m_polygonB.vertices[rf.i2];
            rf.normal = m_polygonB.normals[rf.i1];
        }

        rf.sideNormal1.Set(rf.normal.y, -rf.normal.x);
        rf.sideNormal2 = -rf.sideNormal1;
        rf.sideOffset1 = Utils.b2Dot(rf.sideNormal1, rf.v1);
        rf.sideOffset2 = Utils.b2Dot(rf.sideNormal2, rf.v2);

        // Clip incident edge against extruded edge1 side edges.
        b2ClipVertex[] clipPoints1 = Arrays.InitializeWithDefaultInstances <b2ClipVertex>(2);
        b2ClipVertex[] clipPoints2 = Arrays.InitializeWithDefaultInstances <b2ClipVertex>(2);
        int            np;

        // Clip to box side 1
        np = Utils.b2ClipSegmentToLine(clipPoints1, ie, rf.sideNormal1, rf.sideOffset1, rf.i1);

        if (np < Settings.b2_maxManifoldPoints)
        {
            return;
        }

        // Clip to negative box side 1
        np = Utils.b2ClipSegmentToLine(clipPoints2, clipPoints1, rf.sideNormal2, rf.sideOffset2, rf.i2);

        if (np < Settings.b2_maxManifoldPoints)
        {
            return;
        }

        // Now clipPoints2 contains the clipped points.
        if (primaryAxis.type == b2EPAxis.Type.e_edgeA)
        {
            manifold.localNormal = rf.normal;
            manifold.localPoint  = rf.v1;
        }
        else
        {
            manifold.localNormal = polygonB.m_normals[rf.i1];
            manifold.localPoint  = polygonB.m_vertices[rf.i1];
        }

        int pointCount = 0;

        for (int i = 0; i < Settings.b2_maxManifoldPoints; ++i)
        {
            float separation;

            separation = Utils.b2Dot(rf.normal, clipPoints2[i].v - rf.v1);

            if (separation <= m_radius)
            {
                b2ManifoldPoint cp = manifold.points[pointCount];

                if (primaryAxis.type == b2EPAxis.Type.e_edgeA)
                {
                    cp.localPoint = Utils.b2MulT(m_xf, clipPoints2[i].v);
                    cp.id         = clipPoints2[i].id;
                }
                else
                {
                    cp.localPoint   = clipPoints2[i].v;
                    cp.id.cf.typeA  = clipPoints2[i].id.cf.typeB;
                    cp.id.cf.typeB  = clipPoints2[i].id.cf.typeA;
                    cp.id.cf.indexA = clipPoints2[i].id.cf.indexB;
                    cp.id.cf.indexB = clipPoints2[i].id.cf.indexA;
                }

                ++pointCount;
            }
        }

        manifold.pointCount = pointCount;
    }
        public b2ContactSolver(b2ContactSolverDef def)
        {
            m_step  = def.step;
            m_count = def.count;
            m_positionConstraints = new b2ContactPositionConstraint[m_count];
            for (int pc = 0; pc < m_count; pc++)
            {
                m_positionConstraints[pc] = b2ContactPositionConstraint.Create();
            }

            m_velocityConstraints = new b2ContactVelocityConstraint[m_count];
            for (int vc = 0; vc < m_count; vc++)
            {
                m_velocityConstraints[vc] = b2ContactVelocityConstraint.Create();
            }

            m_positions  = def.positions;
            m_velocities = def.velocities;
            m_contacts   = def.contacts;

            // Initialize position independent portions of the constraints.
            for (int i = 0; i < m_count; ++i)
            {
                b2Contact contact = m_contacts[i];

                b2Fixture  fixtureA = contact.FixtureA;
                b2Fixture  fixtureB = contact.FixtureB;
                b2Shape    shapeA   = fixtureA.Shape;
                b2Shape    shapeB   = fixtureB.Shape;
                float      radiusA  = shapeA.Radius;
                float      radiusB  = shapeB.Radius;
                b2Body     bodyA    = fixtureA.Body;
                b2Body     bodyB    = fixtureB.Body;
                b2Manifold manifold = contact.GetManifold();

                int pointCount = manifold.pointCount;
                Debug.Assert(pointCount > 0);

                b2ContactVelocityConstraint vc = m_velocityConstraints[i];
                vc.friction     = contact.Friction;
                vc.restitution  = contact.Restitution;
                vc.indexA       = bodyA.IslandIndex;
                vc.indexB       = bodyB.IslandIndex;
                vc.invMassA     = bodyA.InvertedMass;
                vc.invMassB     = bodyB.InvertedMass;
                vc.invIA        = bodyA.InvertedI;
                vc.invIB        = bodyB.InvertedI;
                vc.contactIndex = i;
                vc.pointCount   = pointCount;
                vc.K.SetZero();
                vc.normalMass.SetZero();

                b2ContactPositionConstraint pc = m_positionConstraints[i];
                pc.indexA       = bodyA.IslandIndex;
                pc.indexB       = bodyB.IslandIndex;
                pc.invMassA     = bodyA.InvertedMass;
                pc.invMassB     = bodyB.InvertedMass;
                pc.localCenterA = bodyA.Sweep.localCenter;
                pc.localCenterB = bodyB.Sweep.localCenter;
                pc.invIA        = bodyA.InvertedI;
                pc.invIB        = bodyB.InvertedI;
                pc.localNormal  = manifold.localNormal;
                pc.localPoint   = manifold.localPoint;
                pc.pointCount   = pointCount;
                pc.radiusA      = radiusA;
                pc.radiusB      = radiusB;
                pc.type         = manifold.type;

                for (int j = 0; j < pointCount; ++j)
                {
                    b2ManifoldPoint           cp  = manifold.points[j];
                    b2VelocityConstraintPoint vcp = vc.points[j];

                    if (m_step.warmStarting)
                    {
                        vcp.normalImpulse  = m_step.dtRatio * cp.normalImpulse;
                        vcp.tangentImpulse = m_step.dtRatio * cp.tangentImpulse;
                    }
                    else
                    {
                        vcp.normalImpulse  = 0.0f;
                        vcp.tangentImpulse = 0.0f;
                    }

                    vcp.rA.SetZero();
                    vcp.rB.SetZero();
                    vcp.normalMass   = 0.0f;
                    vcp.tangentMass  = 0.0f;
                    vcp.velocityBias = 0.0f;

                    pc.localPoints[j] = cp.localPoint;
                    vc.points[j]      = vcp;
                }
                //Put back the struct data since struct data is copied by value
                m_positionConstraints[i] = pc;
                m_velocityConstraints[i] = vc;
            }
        }
Beispiel #3
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(b2Manifold obj)
 {
     return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr);
 }
 public override void Evaluate(ref b2Manifold manifold, ref b2Transform xfA, ref b2Transform xfB)
 {
     b2Collision.b2CollideCircles(ref manifold,
                                  (b2CircleShape)m_fixtureA.Shape, ref xfA,
                                  (b2CircleShape)m_fixtureB.Shape, ref xfB);
 }
Beispiel #5
0
 public virtual void SetManifold(b2Manifold m)
 {
     m_manifold = m;
 }
Beispiel #6
0
    // Update the contact manifold and touching status.
    // Note: do not assume the fixture AABBs are overlapping or are valid.
    internal void Update(b2ContactListener listener)
    {
        b2Manifold oldManifold = m_manifold;

        // Re-enable this contact.
        m_flags |= ContactFlags.e_enabledFlag;

        bool touching    = false;
        bool wasTouching = (m_flags & ContactFlags.e_touchingFlag) == ContactFlags.e_touchingFlag;

        bool sensorA = m_fixtureA.IsSensor();
        bool sensorB = m_fixtureB.IsSensor();
        bool sensor  = sensorA || sensorB;

        b2Body      bodyA = m_fixtureA.GetBody();
        b2Body      bodyB = m_fixtureB.GetBody();
        b2Transform xfA   = bodyA.GetTransform();
        b2Transform xfB   = bodyB.GetTransform();

        // Is this contact a sensor?
        if (sensor)
        {
            b2Shape shapeA = m_fixtureA.GetShape();
            b2Shape shapeB = m_fixtureB.GetShape();
            touching = Utils.b2TestOverlap(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;

            // Match old contact ids to new contact ids and copy the
            // stored impulses to warm start the solver.
            for (int i = 0; i < m_manifold.pointCount; ++i)
            {
                b2ManifoldPoint mp2 = m_manifold.points[i];
                mp2.normalImpulse  = 0.0f;
                mp2.tangentImpulse = 0.0f;
                b2ContactID id2 = mp2.id;

                for (int j = 0; j < oldManifold.pointCount; ++j)
                {
                    b2ManifoldPoint mp1 = oldManifold.points[j];

                    if (mp1.id.key == id2.key)
                    {
                        mp2.normalImpulse  = mp1.normalImpulse;
                        mp2.tangentImpulse = mp1.tangentImpulse;
                        break;
                    }
                }
            }

            if (touching != wasTouching)
            {
                bodyA.SetAwake(true);
                bodyB.SetAwake(true);
            }
        }

        if (touching)
        {
            m_flags |= ContactFlags.e_touchingFlag;
        }
        else
        {
            m_flags &= ~ContactFlags.e_touchingFlag;
        }

        if (wasTouching == false && touching == true && listener != null)
        {
            listener.BeginContact(this);
        }

        if (wasTouching == true && touching == false && listener != null)
        {
            listener.EndContact(this);
        }

        if (sensor == false && touching && listener != null)
        {
            listener.PreSolve(this, oldManifold);
        }
    }
Beispiel #7
0
 /// <summary>
 /// This is called after a contact is updated. This allows you to inspect a
 /// contact before it goes to the solver. If you are careful, you can modify the
 /// contact manifold (e.g. disable contact).
 /// A copy of the old manifold is provided so that you can detect changes.
 /// Note: this is called only for awake bodies.
 /// Note: this is called even when the number of contact points is zero.
 /// Note: this is not called for sensors.
 /// Note: if you set the number of contact points to zero, you will not
 /// get an EndContact callback. However, you may get a BeginContact callback
 /// the next step.
 /// </summary>
 public abstract void PreSolve(b2Contact contact, b2Manifold oldManifold);
 /// <summary>
 /// This is called after a contact is updated. This allows you to inspect a
 /// contact before it goes to the solver. If you are careful, you can modify the
 /// contact manifold (e.g. disable contact).
 /// A copy of the old manifold is provided so that you can detect changes.
 /// Note: this is called only for awake bodies.
 /// Note: this is called even when the number of contact points is zero.
 /// Note: this is not called for sensors.
 /// Note: if you set the number of contact points to zero, you will not
 /// get an EndContact callback. However, you may get a BeginContact callback
 /// the next step.
 /// </summary>
 public virtual void PreSolve(b2Contact contact, b2Manifold oldManifold)
 {
 }
Beispiel #9
0
 public override void PreSolve(b2Contact contact, b2Manifold oldManifold)
 {
 }
        private void b2CollideEdgeAndCircle(b2Manifold manifold,
                                            b2EdgeShape edge,
                                            b2Transform xf1,
                                            b2CircleShape circle,
                                            b2Transform xf2)
        {
            //TODO_BORIS

            /*
             * manifold.m_pointCount = 0;
             * var tMat: b2Mat22;
             * var tVec: b2Vec2;
             * var dX: Number;
             * var dY: Number;
             * var tX: Number;
             * var tY: Number;
             * var tPoint:b2ManifoldPoint;
             *
             * //b2Vec2 c = b2Mul(xf2, circle->GetLocalPosition());
             * tMat = xf2.R;
             * tVec = circle.m_r;
             * var cX: Number = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
             * var cY: Number = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
             *
             * //b2Vec2 cLocal = b2MulT(xf1, c);
             * tMat = xf1.R;
             * tX = cX - xf1.position.x;
             * tY = cY - xf1.position.y;
             * var cLocalX: Number = (tX * tMat.col1.x + tY * tMat.col1.y );
             * var cLocalY: Number = (tX * tMat.col2.x + tY * tMat.col2.y );
             *
             * var n: b2Vec2 = edge.m_normal;
             * var v1: b2Vec2 = edge.m_v1;
             * var v2: b2Vec2 = edge.m_v2;
             * var radius: Number = circle.m_radius;
             * var separation: Number;
             *
             * var dirDist: Number = (cLocalX - v1.x) * edge.m_direction.x +
             *                    (cLocalY - v1.y) * edge.m_direction.y;
             *
             * var normalCalculated: Boolean = false;
             *
             * if (dirDist <= 0) {
             *      dX = cLocalX - v1.x;
             *      dY = cLocalY - v1.y;
             *      if (dX * edge.m_cornerDir1.x + dY * edge.m_cornerDir1.y < 0) {
             *              return;
             *      }
             *      dX = cX - (xf1.position.x + (tMat.col1.x * v1.x + tMat.col2.x * v1.y));
             *      dY = cY - (xf1.position.y + (tMat.col1.y * v1.x + tMat.col2.y * v1.y));
             * } else if (dirDist >= edge.m_length) {
             *      dX = cLocalX - v2.x;
             *      dY = cLocalY - v2.y;
             *      if (dX * edge.m_cornerDir2.x + dY * edge.m_cornerDir2.y > 0) {
             *              return;
             *      }
             *      dX = cX - (xf1.position.x + (tMat.col1.x * v2.x + tMat.col2.x * v2.y));
             *      dY = cY - (xf1.position.y + (tMat.col1.y * v2.x + tMat.col2.y * v2.y));
             * } else {
             *      separation = (cLocalX - v1.x) * n.x + (cLocalY - v1.y) * n.y;
             *      if (separation > radius || separation < -radius) {
             *              return;
             *      }
             *      separation -= radius;
             *
             *      //manifold.normal = b2Mul(xf1.R, n);
             *      tMat = xf1.R;
             *      manifold.normal.x = (tMat.col1.x * n.x + tMat.col2.x * n.y);
             *      manifold.normal.y = (tMat.col1.y * n.x + tMat.col2.y * n.y);
             *
             *      normalCalculated = true;
             * }
             *
             * if (!normalCalculated) {
             *      var distSqr: Number = dX * dX + dY * dY;
             *      if (distSqr > radius * radius)
             *      {
             *              return;
             *      }
             *
             *      if (distSqr < Number.MIN_VALUE)
             *      {
             *              separation = -radius;
             *              manifold.normal.x = (tMat.col1.x * n.x + tMat.col2.x * n.y);
             *              manifold.normal.y = (tMat.col1.y * n.x + tMat.col2.y * n.y);
             *      }
             *      else
             *      {
             *              distSqr = Math.sqrt(distSqr);
             *              dX /= distSqr;
             *              dY /= distSqr;
             *              separation = distSqr - radius;
             *              manifold.normal.x = dX;
             *              manifold.normal.y = dY;
             *      }
             * }
             *
             * tPoint = manifold.points[0];
             * manifold.pointCount = 1;
             * tPoint.id.key = 0;
             * tPoint.separation = separation;
             * cX = cX - radius * manifold.normal.x;
             * cY = cY - radius * manifold.normal.y;
             *
             * tX = cX - xf1.position.x;
             * tY = cY - xf1.position.y;
             * tPoint.localPoint1.x = (tX * tMat.col1.x + tY * tMat.col1.y );
             * tPoint.localPoint1.y = (tX * tMat.col2.x + tY * tMat.col2.y );
             *
             * tMat = xf2.R;
             * tX = cX - xf2.position.x;
             * tY = cY - xf2.position.y;
             * tPoint.localPoint2.x = (tX * tMat.col1.x + tY * tMat.col1.y );
             * tPoint.localPoint2.y = (tX * tMat.col2.x + tY * tMat.col2.y );
             */
        }
Beispiel #11
0
 public void PreSolve(b2Contact contact, b2Manifold oldManifold)
 {
 }
Beispiel #12
0
 public void Initialize(b2Manifold manifold, b2Transform xfA, float radiusA, b2Transform xfB, float radiusB) {
   Box2dPINVOKE.b2WorldManifold_Initialize(swigCPtr, b2Manifold.getCPtr(manifold), b2Transform.getCPtr(xfA), radiusA, b2Transform.getCPtr(xfB), radiusB);
   if (Box2dPINVOKE.SWIGPendingException.Pending) throw Box2dPINVOKE.SWIGPendingException.Retrieve();
 }
Beispiel #13
0
        public void Update(b2ContactListener listener)
        {
            // Swap old & new manifold
            b2Manifold tManifold = m_oldManifold;

            m_oldManifold = m_manifold;
            m_manifold    = tManifold;

            // Re-enable this contact
            m_flags |= e_enabledFlag;

            bool touching    = false;
            bool wasTouching = (m_flags & e_touchingFlag) == e_touchingFlag;

            b2Body bodyA = m_fixtureA.m_body;
            b2Body bodyB = m_fixtureB.m_body;

            bool aabbOverlap = m_fixtureA.m_aabb.TestOverlap(m_fixtureB.m_aabb);

            // Is this contat a sensor?
            if ((m_flags & e_sensorFlag) > 0)
            {
                if (aabbOverlap)
                {
                    b2Shape     shapeA = m_fixtureA.GetShape();
                    b2Shape     shapeB = m_fixtureB.GetShape();
                    b2Transform xfA    = bodyA.GetTransform();
                    b2Transform xfB    = bodyB.GetTransform();
                    touching = b2Shape.TestOverlap(shapeA, xfA, shapeB, xfB);
                }

                // Sensors don't generate manifolds
                m_manifold.m_pointCount = 0;
            }
            else
            {
                // Slow contacts don't generate TOI events.
                if (bodyA.GetType() != b2Body.b2_dynamicBody || bodyA.IsBullet() || bodyB.GetType() != b2Body.b2_dynamicBody || bodyB.IsBullet())
                {
                    m_flags |= e_continuousFlag;
                }
                else
                {
                    m_flags &= ~e_continuousFlag;
                }

                if (aabbOverlap)
                {
                    Evaluate();

                    touching = m_manifold.m_pointCount > 0;

                    // Match old contact ids to new contact ids and copy the
                    // stored impulses to warm start the solver.
                    for (int i = 0; i < m_manifold.m_pointCount; ++i)
                    {
                        b2ManifoldPoint mp2 = m_manifold.m_points[i];
                        mp2.m_normalImpulse  = 0.0f;
                        mp2.m_tangentImpulse = 0.0f;
                        b2ContactID id2 = mp2.m_id;

                        for (int j = 0; j < m_oldManifold.m_pointCount; ++j)
                        {
                            b2ManifoldPoint mp1 = m_oldManifold.m_points[j];

                            if (mp1.m_id.key == id2.key)
                            {
                                mp2.m_normalImpulse  = mp1.m_normalImpulse;
                                mp2.m_tangentImpulse = mp1.m_tangentImpulse;
                                break;
                            }
                        }
                    }
                }
                else
                {
                    m_manifold.m_pointCount = 0;
                }
                if (touching != wasTouching)
                {
                    bodyA.SetAwake(true);
                    bodyB.SetAwake(true);
                }
            }

            if (touching)
            {
                m_flags |= e_touchingFlag;
            }
            else
            {
                m_flags &= ~e_touchingFlag;
            }

            if (wasTouching == false && touching == true)
            {
                listener.BeginContact(this);
            }

            if (wasTouching == true && touching == false)
            {
                listener.EndContact(this);
            }

            if ((m_flags & e_sensorFlag) == 0)
            {
                listener.PreSolve(this, m_oldManifold);
            }
        }
Beispiel #14
0
    // Initialize position dependent portions of the velocity constraints.
    public void InitializeVelocityConstraints()
    {
        for (int i = 0; i < m_count; ++i)
        {
            b2ContactVelocityConstraint vc = m_velocityConstraints[i];
            b2ContactPositionConstraint pc = m_positionConstraints[i];

            float      radiusA  = pc.radiusA;
            float      radiusB  = pc.radiusB;
            b2Manifold manifold = m_contacts[vc.contactIndex].GetManifold();

            int indexA = vc.indexA;
            int indexB = vc.indexB;

            float  mA           = vc.invMassA;
            float  mB           = vc.invMassB;
            float  iA           = vc.invIA;
            float  iB           = vc.invIB;
            b2Vec2 localCenterA = new b2Vec2(pc.localCenterA);
            b2Vec2 localCenterB = new b2Vec2(pc.localCenterB);

            b2Vec2 cA = m_positions[indexA].c;
            float  aA = m_positions[indexA].a;
            b2Vec2 vA = m_velocities[indexA].v;
            float  wA = m_velocities[indexA].w;

            b2Vec2 cB = m_positions[indexB].c;
            float  aB = m_positions[indexB].a;
            b2Vec2 vB = m_velocities[indexB].v;
            float  wB = m_velocities[indexB].w;

            Debug.Assert(manifold.pointCount > 0);

            b2Transform xfA = new b2Transform();
            b2Transform xfB = new b2Transform();
            xfA.q.Set(aA);
            xfB.q.Set(aB);
            xfA.p = cA - Utils.b2Mul(xfA.q, localCenterA);
            xfB.p = cB - Utils.b2Mul(xfB.q, localCenterB);

            b2WorldManifold worldManifold = new b2WorldManifold();
            worldManifold.Initialize(manifold, xfA, radiusA, xfB, radiusB);

            vc.normal = worldManifold.normal;

            int pointCount = vc.pointCount;
            for (int j = 0; j < pointCount; ++j)
            {
                b2VelocityConstraintPoint vcp = vc.points[j];

                vcp.rA = worldManifold.points[j] - cA;
                vcp.rB = worldManifold.points[j] - cB;

                float rnA = Utils.b2Cross(vcp.rA, vc.normal);
                float rnB = Utils.b2Cross(vcp.rB, vc.normal);

                float kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB;

                vcp.normalMass = kNormal > 0.0f ? 1.0f / kNormal : 0.0f;

                b2Vec2 tangent = Utils.b2Cross(vc.normal, 1.0f);

                float rtA = Utils.b2Cross(vcp.rA, tangent);
                float rtB = Utils.b2Cross(vcp.rB, tangent);

                float kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB;

                vcp.tangentMass = kTangent > 0.0f ? 1.0f / kTangent : 0.0f;

                // Setup a velocity bias for restitution.
                vcp.velocityBias = 0.0f;
                float vRel = Utils.b2Dot(vc.normal, vB + Utils.b2Cross(wB, vcp.rB) - vA - Utils.b2Cross(wA, vcp.rA));
                if (vRel < -Settings.b2_velocityThreshold)
                {
                    vcp.velocityBias = -vc.restitution * vRel;
                }
            }

            // If we have two points, then prepare the block solver.
            if (vc.pointCount == 2 && Utils.g_blockSolve)
            {
                b2VelocityConstraintPoint vcp1 = vc.points[0];
                b2VelocityConstraintPoint vcp2 = vc.points[1];

                float rn1A = Utils.b2Cross(vcp1.rA, vc.normal);
                float rn1B = Utils.b2Cross(vcp1.rB, vc.normal);
                float rn2A = Utils.b2Cross(vcp2.rA, vc.normal);
                float rn2B = Utils.b2Cross(vcp2.rB, vc.normal);

                float k11 = mA + mB + iA * rn1A * rn1A + iB * rn1B * rn1B;
                float k22 = mA + mB + iA * rn2A * rn2A + iB * rn2B * rn2B;
                float k12 = mA + mB + iA * rn1A * rn2A + iB * rn1B * rn2B;

                // Ensure a reasonable condition number.
                const float k_maxConditionNumber = 1000.0f;
                if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12))
                {
                    // K is safe to invert.
                    vc.K.ex.Set(k11, k12);
                    vc.K.ey.Set(k12, k22);
                    vc.normalMass = vc.K.GetInverse();
                }
                else
                {
                    // The constraints are redundant, just use one.
                    // TODO_ERIN use deepest?
                    vc.pointCount = 1;
                }
            }
        }
    }
Beispiel #15
0
 public virtual void PreSolve(b2Contact contact, b2Manifold oldManifold)
 {
     Box2DPINVOKE.b2ContactListener_PreSolve(swigCPtr, b2Contact.getCPtr(contact), b2Manifold.getCPtr(oldManifold));
 }
Beispiel #16
0
    public b2ContactSolver(b2ContactSolverDef def)
    {
        m_step  = def.step;
        m_count = def.count;
        m_positionConstraints = Arrays.InitializeWithDefaultInstances <b2ContactPositionConstraint>(m_count);
        m_velocityConstraints = Arrays.InitializeWithDefaultInstances <b2ContactVelocityConstraint>(m_count);
        m_positions           = def.positions;
        m_velocities          = def.velocities;
        m_contacts            = def.contacts;

        // Initialize position independent portions of the constraints.
        for (int i = 0; i < m_count; ++i)
        {
            b2Contact contact = m_contacts[i];

            b2Fixture  fixtureA = contact.m_fixtureA;
            b2Fixture  fixtureB = contact.m_fixtureB;
            b2Shape    shapeA   = fixtureA.GetShape();
            b2Shape    shapeB   = fixtureB.GetShape();
            float      radiusA  = shapeA.m_radius;
            float      radiusB  = shapeB.m_radius;
            b2Body     bodyA    = fixtureA.GetBody();
            b2Body     bodyB    = fixtureB.GetBody();
            b2Manifold manifold = contact.GetManifold();

            int pointCount = manifold.pointCount;
            Debug.Assert(pointCount > 0);

            b2ContactVelocityConstraint vc = m_velocityConstraints[i];
            vc.friction     = contact.m_friction;
            vc.restitution  = contact.m_restitution;
            vc.tangentSpeed = contact.m_tangentSpeed;
            vc.indexA       = bodyA.m_islandIndex;
            vc.indexB       = bodyB.m_islandIndex;
            vc.invMassA     = bodyA.m_invMass;
            vc.invMassB     = bodyB.m_invMass;
            vc.invIA        = bodyA.m_invI;
            vc.invIB        = bodyB.m_invI;
            vc.contactIndex = i;
            vc.pointCount   = pointCount;
            vc.K.SetZero();
            vc.normalMass.SetZero();

            b2ContactPositionConstraint pc = m_positionConstraints[i];
            pc.indexA       = bodyA.m_islandIndex;
            pc.indexB       = bodyB.m_islandIndex;
            pc.invMassA     = bodyA.m_invMass;
            pc.invMassB     = bodyB.m_invMass;
            pc.localCenterA = bodyA.m_sweep.localCenter;
            pc.localCenterB = bodyB.m_sweep.localCenter;
            pc.invIA        = bodyA.m_invI;
            pc.invIB        = bodyB.m_invI;
            pc.localNormal  = manifold.localNormal;
            pc.localPoint   = manifold.localPoint;
            pc.pointCount   = pointCount;
            pc.radiusA      = radiusA;
            pc.radiusB      = radiusB;
            pc.type         = manifold.type;

            for (int j = 0; j < pointCount; ++j)
            {
                b2ManifoldPoint           cp  = manifold.points[j];
                b2VelocityConstraintPoint vcp = vc.points[j];

                if (m_step.warmStarting)
                {
                    vcp.normalImpulse  = m_step.dtRatio * cp.normalImpulse;
                    vcp.tangentImpulse = m_step.dtRatio * cp.tangentImpulse;
                }
                else
                {
                    vcp.normalImpulse  = 0.0f;
                    vcp.tangentImpulse = 0.0f;
                }

                vcp.rA.SetZero();
                vcp.rB.SetZero();
                vcp.normalMass   = 0.0f;
                vcp.tangentMass  = 0.0f;
                vcp.velocityBias = 0.0f;

                pc.localPoints[j] = cp.localPoint;
            }
        }
    }
Beispiel #17
0
 /// Evaluate this contact with your own manifold and transforms.
 public abstract void Evaluate(b2Manifold manifold, b2Transform xfA, b2Transform xfB);
Beispiel #18
0
 public override void Evaluate(b2Manifold manifold, b2Transform xfA, b2Transform xfB)
 {
     Utils.b2CollideCircles(manifold, (b2CircleShape)m_fixtureA.GetShape(), xfA, (b2CircleShape)m_fixtureB.GetShape(), xfB);
 }
Beispiel #19
0
        private void b2CollidePolyAndEdge(b2Manifold manifold,
                                          b2PolygonShape polygon,
                                          b2Transform xf1,
                                          b2EdgeShape edge,
                                          b2Transform xf2)
        {
            //TODO_BORIS

            /*
             * manifold.pointCount = 0;
             * var tMat: b2Mat22;
             * var tVec1: b2Vec2;
             * var tVec2: b2Vec2;
             * var tX: Number;
             * var tY: Number;
             * var tPoint:b2ManifoldPoint;
             * var ratio: Number;
             *
             * //b2Vec2 v1 = b2Mul(xf2, edge->GetVertex1());
             * tMat = xf2.R;
             * tVec1 = edge.m_v1;
             * var v1X: Number = xf2.position.x + (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y);
             * var v1Y: Number = xf2.position.y + (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y);
             *
             * //b2Vec2 v2 = b2Mul(xf2, edge->GetVertex2());
             * tVec1 = edge.m_v2;
             * var v2X: Number = xf2.position.x + (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y);
             * var v2Y: Number = xf2.position.y + (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y);
             *
             * //b2Vec2 n = b2Mul(xf2.R, edge->GetNormalVector());
             * tVec1 = edge.m_normal;
             * var nX: Number = (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y);
             * var nY: Number = (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y);
             *
             * //b2Vec2 v1Local = b2MulT(xf1, v1);
             * tMat = xf1.R;
             * tX = v1X - xf1.position.x;
             * tY = v1Y - xf1.position.y;
             * var v1LocalX: Number = (tX * tMat.col1.x + tY * tMat.col1.y );
             * var v1LocalY: Number = (tX * tMat.col2.x + tY * tMat.col2.y );
             *
             * //b2Vec2 v2Local = b2MulT(xf1, v2);
             * tX = v2X - xf1.position.x;
             * tY = v2Y - xf1.position.y;
             * var v2LocalX: Number = (tX * tMat.col1.x + tY * tMat.col1.y );
             * var v2LocalY: Number = (tX * tMat.col2.x + tY * tMat.col2.y );
             *
             * //b2Vec2 nLocal = b2MulT(xf1.R, n);
             * var nLocalX: Number = (nX * tMat.col1.x + nY * tMat.col1.y );
             * var nLocalY: Number = (nX * tMat.col2.x + nY * tMat.col2.y );
             *
             * var separation1: Number;
             * var separationIndex1: int = -1; // which normal on the poly found the shallowest depth?
             * var separationMax1: Number = -Number.MAX_VALUE; // the shallowest depth of edge in poly
             * var separation2: Number;
             * var separationIndex2: int = -1; // which normal on the poly found the shallowest depth?
             * var separationMax2: Number = -Number.MAX_VALUE; // the shallowest depth of edge in poly
             * var separationMax: Number = -Number.MAX_VALUE; // the shallowest depth of edge in poly
             * var separationV1: Boolean = false; // is the shallowest depth from edge's v1 or v2 vertex?
             * var separationIndex: int = -1; // which normal on the poly found the shallowest depth?
             *
             * var vertexCount: int = polygon.m_vertexCount;
             * var vertices: Array = polygon.m_vertices;
             * var normals: Array = polygon.m_normals;
             *
             * var enterStartIndex: int = -1; // the last poly vertex above the edge
             * var enterEndIndex: int = -1; // the first poly vertex below the edge
             * var exitStartIndex: int = -1; // the last poly vertex below the edge
             * var exitEndIndex: int = -1; // the first poly vertex above the edge
             *
             * // the "N" in the following variables refers to the edge's normal.
             * // these are projections of poly vertices along the edge's normal,
             * // a.k.a. they are the separation of the poly from the edge.
             * var prevSepN: Number = 0.0;
             * var nextSepN: Number = 0.0;
             * var enterSepN: Number = 0.0; // the depth of enterEndIndex under the edge (stored as a separation, so it's negative)
             * var exitSepN: Number = 0.0; // the depth of exitStartIndex under the edge (stored as a separation, so it's negative)
             * var deepestSepN: Number = Number.MAX_VALUE; // the depth of the deepest poly vertex under the end (stored as a separation, so it's negative)
             *
             *
             * // for each poly normal, get the edge's depth into the poly.
             * // for each poly vertex, get the vertex's depth into the edge.
             * // use these calculations to define the remaining variables declared above.
             * tVec1 = vertices[vertexCount-1];
             * prevSepN = (tVec1.x - v1LocalX) * nLocalX + (tVec1.y - v1LocalY) * nLocalY;
             * for (var i: int = 0; i < vertexCount; i++)
             * {
             *      tVec1 = vertices[i];
             *      tVec2 = normals[i];
             *      separation1 = (v1LocalX - tVec1.x) * tVec2.x + (v1LocalY - tVec1.y) * tVec2.y;
             *      separation2 = (v2LocalX - tVec1.x) * tVec2.x + (v2LocalY - tVec1.y) * tVec2.y;
             *      if (separation2 < separation1) {
             *              if (separation2 > separationMax) {
             *                      separationMax = separation2;
             *                      separationV1 = false;
             *                      separationIndex = i;
             *              }
             *      } else {
             *              if (separation1 > separationMax) {
             *                      separationMax = separation1;
             *                      separationV1 = true;
             *                      separationIndex = i;
             *              }
             *      }
             *      if (separation1 > separationMax1) {
             *              separationMax1 = separation1;
             *              separationIndex1 = i;
             *      }
             *      if (separation2 > separationMax2) {
             *              separationMax2 = separation2;
             *              separationIndex2 = i;
             *      }
             *
             *      nextSepN = (tVec1.x - v1LocalX) * nLocalX + (tVec1.y - v1LocalY) * nLocalY;
             *      if (nextSepN >= 0.0 && prevSepN < 0.0) {
             *              exitStartIndex = (i == 0) ? vertexCount-1 : i-1;
             *              exitEndIndex = i;
             *              exitSepN = prevSepN;
             *      } else if (nextSepN < 0.0 && prevSepN >= 0.0) {
             *              enterStartIndex = (i == 0) ? vertexCount-1 : i-1;
             *              enterEndIndex = i;
             *              enterSepN = nextSepN;
             *      }
             *      if (nextSepN < deepestSepN) {
             *              deepestSepN = nextSepN;
             *      }
             *      prevSepN = nextSepN;
             * }
             *
             * if (enterStartIndex == -1) {
             *      // poly is entirely below or entirely above edge, return with no contact:
             *      return;
             * }
             * if (separationMax > 0.0) {
             *      // poly is laterally disjoint with edge, return with no contact:
             *      return;
             * }
             *
             * // if the poly is near a convex corner on the edge
             * if ((separationV1 && edge.m_cornerConvex1) || (!separationV1 && edge.m_cornerConvex2)) {
             *      // if shallowest depth was from edge into poly,
             *      // use the edge's vertex as the contact point:
             *      if (separationMax > deepestSepN + b2Settings.b2_linearSlop) {
             *              // if -normal angle is closer to adjacent edge than this edge,
             *              // let the adjacent edge handle it and return with no contact:
             *              if (separationV1) {
             *                      tMat = xf2.R;
             *                      tVec1 = edge.m_cornerDir1;
             *                      tX = (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y);
             *                      tY = (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y);
             *                      tMat = xf1.R;
             *                      v1X = (tMat.col1.x * tX + tMat.col2.x * tY); // note abuse of v1...
             *                      v1Y = (tMat.col1.y * tX + tMat.col2.y * tY);
             *                      tVec2 = normals[separationIndex1];
             *                      if (tVec2.x * v1X + tVec2.y * v1Y >= 0.0) {
             *                              return;
             *                      }
             *              } else {
             *                      tMat = xf2.R;
             *                      tVec1 = edge.m_cornerDir2;
             *                      tX = (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y);
             *                      tY = (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y);
             *                      tMat = xf1.R;
             *                      v1X = (tMat.col1.x * tX + tMat.col2.x * tY); // note abuse of v1...
             *                      v1Y = (tMat.col1.y * tX + tMat.col2.y * tY);
             *                      tVec2 = normals[separationIndex2];
             *                      if (tVec2.x * v1X + tVec2.y * v1Y <= 0.0) {
             *                              return;
             *                      }
             *              }
             *
             *              tPoint = manifold.points[0];
             *              manifold.pointCount = 1;
             *
             *              //manifold->normal = b2Mul(xf1.R, normals[separationIndex]);
             *              tMat = xf1.R;
             *              tVec2 = normals[separationIndex];
             *              manifold.normal.x = (tMat.col1.x * tVec2.x + tMat.col2.x * tVec2.y);
             *              manifold.normal.y = (tMat.col1.y * tVec2.x + tMat.col2.y * tVec2.y);
             *
             *              tPoint.separation = separationMax;
             *              tPoint.id.features.incidentEdge = separationIndex;
             *              tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
             *              tPoint.id.features.referenceEdge = 0;
             *              tPoint.id.features.flip = 0;
             *              if (separationV1) {
             *                      tPoint.localPoint1.x = v1LocalX;
             *                      tPoint.localPoint1.y = v1LocalY;
             *                      tPoint.localPoint2.x = edge.m_v1.x;
             *                      tPoint.localPoint2.y = edge.m_v1.y;
             *              } else {
             *                      tPoint.localPoint1.x = v2LocalX;
             *                      tPoint.localPoint1.y = v2LocalY;
             *                      tPoint.localPoint2.x = edge.m_v2.x;
             *                      tPoint.localPoint2.y = edge.m_v2.y;
             *              }
             *              return;
             *      }
             * }
             *
             * // We're going to use the edge's normal now.
             * manifold.normal.x = -nX;
             * manifold.normal.y = -nY;
             *
             * // Check whether we only need one contact point.
             * if (enterEndIndex == exitStartIndex) {
             *      tPoint = manifold.points[0];
             *      manifold.pointCount = 1;
             *      tPoint.id.features.incidentEdge = enterEndIndex;
             *      tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
             *      tPoint.id.features.referenceEdge = 0;
             *      tPoint.id.features.flip = 0;
             *      tVec1 = vertices[enterEndIndex];
             *      tPoint.localPoint1.x = tVec1.x;
             *      tPoint.localPoint1.y = tVec1.y;
             *
             *      tMat = xf1.R;
             *      tX = xf1.position.x + (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y) - xf2.position.x;
             *      tY = xf1.position.y + (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y) - xf2.position.y;
             *      tMat = xf2.R;
             *      tPoint.localPoint2.x = (tX * tMat.col1.x + tY * tMat.col1.y );
             *      tPoint.localPoint2.y = (tX * tMat.col2.x + tY * tMat.col2.y );
             *
             *      tPoint.separation = enterSepN;
             *      return;
             * }
             *
             * manifold.pointCount = 2;
             *
             * // the edge's direction vector, but in the frame of the polygon:
             * tX = -nLocalY;
             * tY = nLocalX;
             *
             * tVec1 = vertices[enterEndIndex];
             * var dirProj1: Number = tX * (tVec1.x - v1LocalX) + tY * (tVec1.y - v1LocalY);
             * var dirProj2: Number;
             *
             * // The contact resolution is more robust if the two manifold points are
             * // adjacent to each other on the polygon. So pick the first two poly
             * // vertices that are under the edge:
             * exitEndIndex = (enterEndIndex == vertexCount - 1) ? 0 : enterEndIndex + 1;
             * tVec1 = vertices[exitStartIndex];
             * if (exitEndIndex != exitStartIndex) {
             *      exitStartIndex = exitEndIndex;
             *
             *      exitSepN = nLocalX * (tVec1.x - v1LocalX) + nLocalY * (tVec1.y - v1LocalY);
             * }
             * dirProj2 = tX * (tVec1.x - v1LocalX) + tY * (tVec1.y - v1LocalY);
             *
             * tPoint = manifold.points[0];
             * tPoint.id.features.incidentEdge = enterEndIndex;
             * tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
             * tPoint.id.features.referenceEdge = 0;
             * tPoint.id.features.flip = 0;
             *
             * if (dirProj1 > edge.m_length) {
             *      tPoint.localPoint1.x = v2LocalX;
             *      tPoint.localPoint1.y = v2LocalY;
             *      tPoint.localPoint2.x = edge.m_v2.x;
             *      tPoint.localPoint2.y = edge.m_v2.y;
             *      ratio = (edge.m_length - dirProj2) / (dirProj1 - dirProj2);
             *      if (ratio > 100.0 * Number.MIN_VALUE && ratio < 1.0) {
             *              tPoint.separation = exitSepN * (1.0 - ratio) + enterSepN * ratio;
             *      } else {
             *              tPoint.separation = enterSepN;
             *      }
             * } else {
             *      tVec1 = vertices[enterEndIndex];
             *      tPoint.localPoint1.x = tVec1.x;
             *      tPoint.localPoint1.y = tVec1.y;
             *
             *      tMat = xf1.R;
             *      tX = xf1.position.x + (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y) - xf2.position.x;
             *      tY = xf1.position.y + (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y) - xf2.position.y;
             *      tMat = xf2.R;
             *      tPoint.localPoint2.x = (tX * tMat.col1.x + tY * tMat.col1.y);
             *      tPoint.localPoint2.y = (tX * tMat.col2.x + tY * tMat.col2.y);
             *
             *      tPoint.separation = enterSepN;
             * }
             *
             * tPoint = manifold.points[1];
             * tPoint.id.features.incidentEdge = exitStartIndex;
             * tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
             * tPoint.id.features.referenceEdge = 0;
             * tPoint.id.features.flip = 0;
             *
             * if (dirProj2 < 0.0) {
             *      tPoint.localPoint1.x = v1LocalX;
             *      tPoint.localPoint1.y = v1LocalY;
             *      tPoint.localPoint2.x = edge.m_v1.x;
             *      tPoint.localPoint2.y = edge.m_v1.y;
             *      ratio = (-dirProj1) / (dirProj2 - dirProj1);
             *      if (ratio > 100.0 * Number.MIN_VALUE && ratio < 1.0) {
             *              tPoint.separation = enterSepN * (1.0 - ratio) + exitSepN * ratio;
             *      } else {
             *              tPoint.separation = exitSepN;
             *      }
             * } else {
             *      tVec1 = vertices[exitStartIndex];
             *      tPoint.localPoint1.x = tVec1.x;
             *      tPoint.localPoint1.y = tVec1.y;
             *
             *      tMat = xf1.R;
             *      tX = xf1.position.x + (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y) - xf2.position.x;
             *      tY = xf1.position.y + (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y) - xf2.position.y;
             *      tMat = xf2.R;
             *      tPoint.localPoint2.x = (tX * tMat.col1.x + tY * tMat.col1.y);
             *      tPoint.localPoint2.y = (tX * tMat.col2.x + tY * tMat.col2.y);
             *
             *      tPoint.separation = exitSepN;
             * }
             */
        }