Example #1
0
        public static int Orthographic(double sign, double e, int axis, byte clipEdge, ClipVertex[] input, int inCount, ClipVertex[] result)
        {
            int        resultCount = 0;
            ClipVertex a           = input[inCount - 1];

            for (int i = 0; i < inCount; ++i)
            {
                ClipVertex b = input[i];

                double da = sign * a.v[axis] - e;
                double db = sign * b.v[axis] - e;

                ClipVertex cv = new ClipVertex();

                // B
                if (((InFront(da) && InFront(db)) || On(da) || On(db)))
                {
                    Assert(resultCount < 8);
                    result[resultCount++] = b;
                }

                // I
                else if (InFront(da) && Behind(db))
                {
                    cv.f      = b.f;
                    cv.v      = a.v + (b.v - a.v) * (da / (da - db));
                    cv.f.outR = clipEdge;
                    cv.f.outI = 0;

                    Assert(resultCount < 8);
                    result[resultCount++] = cv;
                }

                // I, B
                else if (Behind(da) && InFront(db))
                {
                    cv.f     = a.f;
                    cv.v     = a.v + (b.v - a.v) * (da / (da - db));
                    cv.f.inR = clipEdge;
                    cv.f.inI = 0;

                    Assert(resultCount < 8);
                    result[resultCount++] = cv;


                    Assert(resultCount < 8);
                    result[resultCount++] = b;
                }

                a = b;
            }

            return(resultCount);
        }
        public static void FindIncidentEdge(out ClipVertex[] c, PolygonShape poly1, XForm xf1, int edge1, PolygonShape poly2, XForm xf2)
        {
            int count1 = poly1.VertexCount;

            Vector2[] normals1 = poly1.Normals;

            int count2 = poly2.VertexCount;

            Vector2[] vertices2 = poly2.GetVertices();
            Vector2[] normals2  = poly2.Normals;

            //Box2DXDebug.Assert(0 <= edge1 && edge1 < count1);

            // Get the normal of the reference edge in poly2's frame.
            Vector2 normal1 = CommonMath.MulT(xf2.R, CommonMath.Mul(xf1.R, normals1[edge1]));

            // Find the incident edge on poly2.
            int   index  = 0;
            float minDot = Settings.FLT_MAX;

            for (int i = 0; i < count2; ++i)
            {
                float dot = Vector2.Dot(normal1, normals2[i]);
                if (dot < minDot)
                {
                    minDot = dot;
                    index  = i;
                }
            }

            // Build the clip vertices for the incident edge.
            int i1 = index;
            int i2 = i1 + 1 < count2 ? i1 + 1 : 0;

            c = new ClipVertex[2];

            c[0].V = CommonMath.Mul(xf2, vertices2[i1]);
            c[0].ID.Features.ReferenceEdge  = (byte)edge1;
            c[0].ID.Features.IncidentEdge   = (byte)i1;
            c[0].ID.Features.IncidentVertex = 0;

            c[1].V = CommonMath.Mul(xf2, vertices2[i2]);
            c[1].ID.Features.ReferenceEdge  = (byte)edge1;
            c[1].ID.Features.IncidentEdge   = (byte)i2;
            c[1].ID.Features.IncidentVertex = 1;
        }
        public static int ClipSegmentToLine(out ClipVertex[] vOut, ClipVertex[] vIn, Vector2 normal, float offset)
        {
            if (vIn.Length != 2)
            {
                //Box2DXDebug.ThrowBox2DXException("vIn should contain 2 element, but contains " + vIn.Length.ToString());
            }
            vOut = new ClipVertex[2];

            // Start with no output points
            int numOut = 0;

            // Calculate the distance of end points to the line
            float distance0 = Vector2.Dot(normal, vIn[0].V) - offset;
            float distance1 = Vector2.Dot(normal, vIn[1].V) - offset;

            // If the points are behind the plane
            if (distance0 <= 0.0f)
            {
                vOut[numOut++] = vIn[0];
            }
            if (distance1 <= 0.0f)
            {
                vOut[numOut++] = vIn[1];
            }

            // If the points are on different sides of the plane
            if (distance0 * distance1 < 0.0f)
            {
                // Find intersection point of edge and plane
                float interp = distance0 / (distance0 - distance1);
                vOut[numOut].V = vIn[0].V + interp * (vIn[1].V - vIn[0].V);
                if (distance0 > 0.0f)
                {
                    vOut[numOut].ID = vIn[0].ID;
                }
                else
                {
                    vOut[numOut].ID = vIn[1].ID;
                }
                ++numOut;
            }

            return(numOut);
        }
Example #4
0
 public Collision(IWorldPool argPool)
 {
     incidentEdge[0] = new ClipVertex();
     incidentEdge[1] = new ClipVertex();
     clipPoints1[0] = new ClipVertex();
     clipPoints1[1] = new ClipVertex();
     clipPoints2[0] = new ClipVertex();
     clipPoints2[1] = new ClipVertex();
     pool = argPool;
 }
Example #5
0
        // djm pooling from above
        public void findIncidentEdge(ClipVertex[] c, PolygonShape poly1, Transform xf1, int edge1, PolygonShape poly2, Transform xf2)
        {
            int count1 = poly1.m_count;
            Vec2[] normals1 = poly1.m_normals;

            int count2 = poly2.m_count;
            Vec2[] vertices2 = poly2.m_vertices;
            Vec2[] normals2 = poly2.m_normals;

            Debug.Assert(0 <= edge1 && edge1 < count1);

            // Get the normal of the reference edge in poly2's frame.
            Rot.mulToOutUnsafe(xf1.q, normals1[edge1], normal1); // temporary
            // Vec2 normal1 = MulT(xf2.R, Mul(xf1.R, normals1[edge1]));
            Rot.mulTrans(xf2.q, normal1, normal1);

            // Find the incident edge on poly2.
            int index = 0;
            float minDot = Single.MaxValue;
            for (int i = 0; i < count2; ++i)
            {
                float dot = Vec2.dot(normal1, normals2[i]);
                if (dot < minDot)
                {
                    minDot = dot;
                    index = i;
                }
            }

            // Build the clip vertices for the incident edge.
            int i1 = index;
            int i2 = i1 + 1 < count2 ? i1 + 1 : 0;

            Transform.mulToOutUnsafe(xf2, vertices2[i1], c[0].v); // = Mul(xf2, vertices2[i1]);
            c[0].id.indexA = (sbyte)edge1;
            c[0].id.indexB = (sbyte)i1;
            c[0].id.typeA = (sbyte)ContactID.Type.FACE;
            c[0].id.typeB = (sbyte)ContactID.Type.VERTEX;

            Transform.mulToOutUnsafe(xf2, vertices2[i2], c[1].v); // = Mul(xf2, vertices2[i2]);
            c[1].id.indexA = (sbyte)edge1;
            c[1].id.indexB = (sbyte)i2;
            c[1].id.typeA = (sbyte)ContactID.Type.FACE;
            c[1].id.typeB = (sbyte)ContactID.Type.VERTEX;
        }
Example #6
0
        /// <summary>
        /// Clipping for contact manifolds. Sutherland-Hodgman clipping.
        /// </summary>
        /// <param name="vOut"></param>
        /// <param name="vIn"></param>
        /// <param name="normal"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        public static int clipSegmentToLine(ClipVertex[] vOut, ClipVertex[] vIn, Vec2 normal, float offset, int vertexIndexA)
        {
            // Start with no output points
            int numOut = 0;

            // Calculate the distance of end points to the line
            float distance0 = Vec2.dot(normal, vIn[0].v) - offset;
            float distance1 = Vec2.dot(normal, vIn[1].v) - offset;

            // If the points are behind the plane
            if (distance0 <= 0.0f)
            {
                vOut[numOut++].set_Renamed(vIn[0]);
            }
            if (distance1 <= 0.0f)
            {
                vOut[numOut++].set_Renamed(vIn[1]);
            }

            // If the points are on different sides of the plane
            if (distance0 * distance1 < 0.0f)
            {
                // Find intersection point of edge and plane
                float interp = distance0 / (distance0 - distance1);
                // vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
                vOut[numOut].v.set_Renamed(vIn[1].v).subLocal(vIn[0].v).mulLocal(interp).addLocal(vIn[0].v);

                // VertexA is hitting edgeB.
                vOut[numOut].id.indexA = (sbyte)vertexIndexA;
                vOut[numOut].id.indexB = vIn[0].id.indexB;
                vOut[numOut].id.typeA = (sbyte)ContactID.Type.VERTEX;
                vOut[numOut].id.typeB = (sbyte)ContactID.Type.FACE;
                ++numOut;
            }

            return numOut;
        }
Example #7
0
 public EPCollider()
 {
     for (int i = 0; i < 2; i++)
     {
         ie[i] = new ClipVertex();
         clipPoints1[i] = new ClipVertex();
         clipPoints2[i] = new ClipVertex();
     }
 }
Example #8
0
 public virtual void set_Renamed(ClipVertex cv)
 {
     v.set_Renamed(cv.v);
     id.set_Renamed(cv.id);
 }
Example #9
0
        public void findIncidentEdge(ClipVertex[] c, PolygonShape poly1,
            Transform xf1, int edge1, PolygonShape poly2, Transform xf2)
        {
            int count1 = poly1.m_count;
            Vec2[] normals1 = poly1.m_normals;

            int count2 = poly2.m_count;
            Vec2[] vertices2 = poly2.m_vertices;
            Vec2[] normals2 = poly2.m_normals;

            Debug.Assert(0 <= edge1 && edge1 < count1);

            ClipVertex c0 = c[0];
            ClipVertex c1 = c[1];
            Rot xf1q = xf1.q;
            Rot xf2q = xf2.q;

            // Get the normal of the reference edge in poly2's frame.
            // Vec2 normal1 = MulT(xf2.R, Mul(xf1.R, normals1[edge1]));
            // before inline:
            // Rot.mulToOutUnsafe(xf1.q, normals1[edge1], normal1); // temporary
            // Rot.mulTrans(xf2.q, normal1, normal1);
            // after inline:
            Vec2 v = normals1[edge1];
            float tempx = xf1q.c*v.x - xf1q.s*v.y;
            float tempy = xf1q.s*v.x + xf1q.c*v.y;
            float normal1x = xf2q.c*tempx + xf2q.s*tempy;
            float normal1y = -xf2q.s*tempx + xf2q.c*tempy;

            // end inline

            // Find the incident edge on poly2.
            int index = 0;
            float minDot = float.MaxValue;
            for (int i = 0; i < count2; ++i)
            {
                Vec2 b = normals2[i];
                float dot = normal1x*b.x + normal1y*b.y;
                if (dot < minDot)
                {
                    minDot = dot;
                    index = i;
                }
            }

            // Build the clip vertices for the incident edge.
            int i1 = index;
            int i2 = i1 + 1 < count2 ? i1 + 1 : 0;

            // c0.v = Mul(xf2, vertices2[i1]);
            Vec2 v1 = vertices2[i1];
            Vec2 @ref = c0.v;
            @ref.x = (xf2q.c*v1.x - xf2q.s*v1.y) + xf2.p.x;
            @ref.y = (xf2q.s*v1.x + xf2q.c*v1.y) + xf2.p.y;

            c0.v = @ref;
            c0.id.indexA = (byte) edge1;
            c0.id.indexB = (byte) i1;
            c0.id.typeA = (byte) ContactID.Type.FACE;
            c0.id.typeB = (byte) ContactID.Type.VERTEX;

            // c1.v = Mul(xf2, vertices2[i2]);
            Vec2 v2 = vertices2[i2];
            Vec2 out1 = c1.v;
            out1.x = (xf2q.c*v2.x - xf2q.s*v2.y) + xf2.p.x;
            out1.y = (xf2q.s*v2.x + xf2q.c*v2.y) + xf2.p.y;
            c1.id.indexA = (byte) edge1;
            c1.id.indexB = (byte) i2;
            c1.id.typeA = (byte) ContactID.Type.FACE;
            c1.id.typeB = (byte) ContactID.Type.VERTEX;
        }
Example #10
0
        /**
        * Clipping for contact manifolds. Sutherland-Hodgman clipping.
        *
        * @param vOut
        * @param vIn
        * @param normal
        * @param offset
        * @return
        */
        public static int clipSegmentToLine(ClipVertex[] vOut, ClipVertex[] vIn,
            Vec2 normal, float offset, int vertexIndexA)
        {
            // Start with no output points
            int numOut = 0;
            ClipVertex vIn0 = vIn[0];
            ClipVertex vIn1 = vIn[1];
            Vec2 vIn0v = vIn0.v;
            Vec2 vIn1v = vIn1.v;

            // Calculate the distance of end points to the line
            float distance0 = Vec2.dot(normal, vIn0v) - offset;
            float distance1 = Vec2.dot(normal, vIn1v) - offset;

            // If the points are behind the plane
            if (distance0 <= 0.0f)
            {
                vOut[numOut++].set(vIn0);
            }
            if (distance1 <= 0.0f)
            {
                vOut[numOut++].set(vIn1);
            }

            // If the points are on different sides of the plane
            if (distance0*distance1 < 0.0f)
            {
                // Find intersection point of edge and plane
                float interp = distance0/(distance0 - distance1);

                ClipVertex vOutNO = vOut[numOut];
                // vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
                vOutNO.v.x = vIn0v.x + interp*(vIn1v.x - vIn0v.x);
                vOutNO.v.y = vIn0v.y + interp*(vIn1v.y - vIn0v.y);

                // VertexA is hitting edgeB.
                vOutNO.id.indexA = (byte) vertexIndexA;
                vOutNO.id.indexB = vIn0.id.indexB;
                vOutNO.id.typeA = (byte) ContactID.Type.VERTEX;
                vOutNO.id.typeB = (byte) ContactID.Type.FACE;
                ++numOut;
            }

            return numOut;
        }
Example #11
0
 public void set(ClipVertex cv)
 {
     Vec2 v1 = cv.v;
     v.x = v1.x;
     v.y = v1.y;
     ContactID c = cv.id;
     id.indexA = c.indexA;
     id.indexB = c.indexB;
     id.typeA = c.typeA;
     id.typeB = c.typeB;
 }
Example #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="contacts"> A 和 B 的接触点</param>
        /// <param name="bodyA"></param>
        /// <param name="bodyB"></param>
        /// <returns></returns>
        public static int Collide(ref Contact[] contacts, Body bodyA, Body bodyB)
        {
            // 初始化
            Vector2f hA = 0.5f * bodyA.width_height;
            Vector2f hB = 0.5f * bodyB.width_height;

            Vector2f posA = bodyA.position;
            Vector2f posB = bodyB.position;

            Mat22 RotA  = new Mat22(bodyA.rotation);
            Mat22 RotB  = new Mat22(bodyB.rotation);
            Mat22 RotAT = RotA.Transpose();
            Mat22 RotBT = RotB.Transpose();

            Vector2f dp = posB - posA;
            Vector2f dA = RotAT * dp;
            Vector2f dB = RotBT * dp;

            Mat22 C     = RotAT * RotB;
            Mat22 absC  = MyMath.Abs(C);
            Mat22 absCT = absC.Transpose();

            //dA是两个矩形终点连线的向量,做了Abs运算后,dA表示的只是数值意义。
            //实际上,下面的代码是Abs(dA) - (hA + absC * hB)
            //hA就是矩形A右上角的点,absC * hB就是求出B点在A矩形的局部坐标系下的四个顶点中
            //x,y方向上的最大值,因为dA,hA,hB都是从(0,0)点出发的向量,所以向量中的数值仅仅
            //表示数值意义
            //Abs(dA) - (hA + absC * hB)对于这个式子,如果只看x轴
            //实际上就是dA的x坐标表示两个矩形的中心连线在x轴投影长度为s,
            //hA是矩形A的x方向在中心连线的最大投影长度a,absC*hB就是矩形B的x方向在中心连线的最大投影长度b
            //如果s-a-b大于0,这说明投影不相交。
            // Box A faces
            Vector2f faceA = MyMath.Abs(dA) - hA - absC * hB;

            if (faceA.x > 0.0f || faceA.y > 0.0f)
            {
                return(0);
            }
            // Box B facesa
            Vector2f faceB = MyMath.Abs(dB) - absCT * hA - hB;

            if (faceB.x > 0.0f || faceB.y > 0.0f)
            {
                return(0);
            }
            // 找到最佳碰撞轴
            Axis  axis;
            float separation;


            // Box A faces
            axis       = Axis.FACE_A_X;
            separation = faceA.x;
            Vector2f normal = dA.x > 0.0f ? RotA.ex : -RotA.ex;

            const float relativeTol = 0.95f;
            const float absoluteTol = 0.05f;

            if (faceA.y > relativeTol * separation + absoluteTol * hA.y)
            {
                axis       = Axis.FACE_A_Y;
                separation = faceA.y;
                normal     = dA.y > 0.0f ? RotA.ey : -RotA.ey;
            }
            // Box B faces
            if (faceB.x > relativeTol * separation + absoluteTol * hB.x)
            {
                axis       = Axis.FACE_B_X;
                separation = faceB.x;
                normal     = dB.x > 0.0f ? RotB.ex : -RotB.ex;
            }

            if (faceB.y > relativeTol * separation + absoluteTol * hB.y)
            {
                axis       = Axis.FACE_B_Y;
                separation = faceB.y;
                normal     = dB.y > 0.0f ? RotB.ey : -RotB.ey;
            }
            // 根据分离轴初始化分离平面
            Vector2f frontNormal = new Vector2f();
            Vector2f sideNormal  = new Vector2f();

            ClipVertex[] incidentEdge = new ClipVertex[2];
            incidentEdge[0] = new ClipVertex();
            incidentEdge[1] = new ClipVertex();

            float front = 0.0f, negSide = 0.0f, posSide = 0.0f;
            char  negEdge = (char)EdgeNumbers.NO_EDGE, posEdge = (char)EdgeNumbers.NO_EDGE;

            // 计算分离线和要分离的线段
            switch (axis)
            {
            case Axis.FACE_A_X:
            {
                frontNormal = normal;
                front       = MyMath.Dot(posA, frontNormal) + hA.x;
                sideNormal  = RotA.ey;
                float side = MyMath.Dot(posA, sideNormal);
                negSide = -side + hA.y;
                posSide = side + hA.y;
                negEdge = (char)EdgeNumbers.EDGE3;
                posEdge = (char)EdgeNumbers.EDGE1;
                ComputeIncidentEdge(ref incidentEdge, hB, posB, RotB, frontNormal);
            }
            break;

            case Axis.FACE_A_Y:
            {
                frontNormal = normal;
                front       = MyMath.Dot(posA, frontNormal) + hA.y;
                sideNormal  = RotA.ex;
                float side = MyMath.Dot(posA, sideNormal);
                negSide = -side + hA.x;
                posSide = side + hA.x;
                negEdge = (char)EdgeNumbers.EDGE2;
                posEdge = (char)EdgeNumbers.EDGE4;
                ComputeIncidentEdge(ref incidentEdge, hB, posB, RotB, frontNormal);
            }
            break;

            case Axis.FACE_B_X:
            {
                frontNormal = -normal;
                front       = MyMath.Dot(posB, frontNormal) + hB.x;
                sideNormal  = RotB.ey;
                float side = MyMath.Dot(posB, sideNormal);
                negSide = -side + hB.y;
                posSide = side + hB.y;
                negEdge = (char)EdgeNumbers.EDGE3;
                posEdge = (char)EdgeNumbers.EDGE1;
                ComputeIncidentEdge(ref incidentEdge, hA, posA, RotA, frontNormal);
            }
            break;

            case Axis.FACE_B_Y:
            {
                frontNormal = -normal;
                front       = MyMath.Dot(posB, frontNormal) + hB.y;
                sideNormal  = RotB.ex;
                float side = MyMath.Dot(posB, sideNormal);
                negSide = -side + hB.x;
                posSide = side + hB.x;
                negEdge = (char)EdgeNumbers.EDGE2;
                posEdge = (char)EdgeNumbers.EDGE4;
                ComputeIncidentEdge(ref incidentEdge, hA, posA, RotA, frontNormal);
            }
            break;
            }
            // 分离其他面
            ClipVertex[] clipPoints1 = new ClipVertex[2];
            clipPoints1[0] = new ClipVertex();
            clipPoints1[1] = new ClipVertex();
            ClipVertex[] clipPoints2 = new ClipVertex[2];
            clipPoints2[0] = new ClipVertex();
            clipPoints2[1] = new ClipVertex();
            int np;

            // Clip to box side 1
            np = ClipSegmentToLine(ref clipPoints1, ref incidentEdge, -sideNormal, negSide, negEdge);

            if (np < 2)
            {
                return(0);
            }

            // Clip to negative box side 1
            np = ClipSegmentToLine(ref clipPoints2, ref clipPoints1, sideNormal, posSide, posEdge);

            if (np < 2)
            {
                return(0);
            }

            // Now clipPoints2 contains the clipping points.
            // 由于舍入,分离可能删去所有点

            int numContacts = 0;

            for (int i = 0; i < 2; ++i)
            {
                separation = MyMath.Dot(frontNormal, clipPoints2[i].v) - front;

                if (separation <= 0)
                {
                    contacts[numContacts].separation = separation;
                    contacts[numContacts].normal     = normal;
                    // slide contact point onto reference face (easy to cull)
                    contacts[numContacts].position = clipPoints2[i].v - separation * frontNormal;
                    contacts[numContacts].feature  = clipPoints2[i].fp;
                    if (axis == Axis.FACE_B_X || axis == Axis.FACE_B_Y)
                    {
                        Flip(contacts[numContacts].feature);
                    }
                    ++numContacts;
                }
            }
            return(numContacts);
        }
Example #13
0
 public void Set(ClipVertex cv)
 {
     V.Set(cv.V);
     Id.Set(cv.Id);
 }