Box2D.Collision.Collision.EPCollider.Collide C# (CSharp) Метод

Collide() публичный Метод

public Collide ( Manifold manifold, EdgeShape edgeA, Transform xfA, PolygonShape polygonB, Transform xfB ) : void
manifold Manifold
edgeA Box2D.Collision.Shapes.EdgeShape
xfA Box2D.Common.Transform
polygonB Box2D.Collision.Shapes.PolygonShape
xfB Box2D.Common.Transform
Результат void
            public void Collide(Manifold manifold, EdgeShape edgeA, Transform xfA, PolygonShape polygonB, Transform xfB)
            {
                Transform.MulTransToOutUnsafe(xfA, xfB, xf);
                Transform.MulToOutUnsafe(xf, polygonB.Centroid, centroidB);

                v0 = edgeA.Vertex0;
                v1 = edgeA.Vertex1;
                v2 = edgeA.Vertex2;
                v3 = edgeA.Vertex3;

                bool hasVertex0 = edgeA.HasVertex0;
                bool hasVertex3 = edgeA.HasVertex3;

                edge1.Set(v2).SubLocal(v1);
                edge1.Normalize();
                normal1.Set(edge1.Y, -edge1.X);
                float offset1 = Vec2.Dot(normal1, temp.Set(centroidB).SubLocal(v1));
                float offset0 = 0.0f, offset2 = 0.0f;
                bool convex1 = false, convex2 = false;

                // Is there a preceding edge?
                if (hasVertex0)
                {
                    edge0.Set(v1).SubLocal(v0);
                    edge0.Normalize();
                    normal0.Set(edge0.Y, -edge0.X);
                    convex1 = Vec2.Cross(edge0, edge1) >= 0.0f;
                    offset0 = Vec2.Dot(normal0, temp.Set(centroidB).SubLocal(v0));
                }

                // Is there a following edge?
                if (hasVertex3)
                {
                    edge2.Set(v3).SubLocal(v2);
                    edge2.Normalize();
                    normal2.Set(edge2.Y, -edge2.X);
                    convex2 = Vec2.Cross(edge1, edge2) > 0.0f;
                    offset2 = Vec2.Dot(normal2, temp.Set(centroidB).SubLocal(v2));
                }

                // Determine front or back collision. Determine collision normal limits.
                if (hasVertex0 && hasVertex3)
                {
                    if (convex1 && convex2)
                    {
                        front = offset0 >= 0.0f || offset1 >= 0.0f || offset2 >= 0.0f;
                        if (front)
                        {
                            normal.Set(normal1);
                            lowerLimit.Set(normal0);
                            upperLimit.Set(normal2);
                        }
                        else
                        {
                            normal.Set(normal1).NegateLocal();
                            lowerLimit.Set(normal1).NegateLocal();
                            upperLimit.Set(normal1).NegateLocal();
                        }
                    }
                    else if (convex1)
                    {
                        front = offset0 >= 0.0f || (offset1 >= 0.0f && offset2 >= 0.0f);
                        if (front)
                        {
                            normal.Set(normal1);
                            lowerLimit.Set(normal0);
                            upperLimit.Set(normal1);
                        }
                        else
                        {
                            normal.Set(normal1).NegateLocal();
                            lowerLimit.Set(normal2).NegateLocal();
                            upperLimit.Set(normal1).NegateLocal();
                        }
                    }
                    else if (convex2)
                    {
                        front = offset2 >= 0.0f || (offset0 >= 0.0f && offset1 >= 0.0f);
                        if (front)
                        {
                            normal.Set(normal1);
                            lowerLimit.Set(normal1);
                            upperLimit.Set(normal2);
                        }
                        else
                        {
                            normal.Set(normal1).NegateLocal();
                            lowerLimit.Set(normal1).NegateLocal();
                            upperLimit.Set(normal0).NegateLocal();
                        }
                    }
                    else
                    {
                        front = offset0 >= 0.0f && offset1 >= 0.0f && offset2 >= 0.0f;
                        if (front)
                        {
                            normal.Set(normal1);
                            lowerLimit.Set(normal1);
                            upperLimit.Set(normal1);
                        }
                        else
                        {
                            normal.Set(normal1).NegateLocal();
                            lowerLimit.Set(normal2).NegateLocal();
                            upperLimit.Set(normal0).NegateLocal();
                        }
                    }
                }
                else if (hasVertex0)
                {
                    if (convex1)
                    {
                        front = offset0 >= 0.0f || offset1 >= 0.0f;
                        if (front)
                        {
                            normal.Set(normal1);
                            lowerLimit.Set(normal0);
                            upperLimit.Set(normal1).NegateLocal();
                        }
                        else
                        {
                            normal.Set(normal1).NegateLocal();
                            lowerLimit.Set(normal1);
                            upperLimit.Set(normal1).NegateLocal();
                        }
                    }
                    else
                    {
                        front = offset0 >= 0.0f && offset1 >= 0.0f;
                        if (front)
                        {
                            normal.Set(normal1);
                            lowerLimit.Set(normal1);
                            upperLimit.Set(normal1).NegateLocal();
                        }
                        else
                        {
                            normal.Set(normal1).NegateLocal();
                            lowerLimit.Set(normal1);
                            upperLimit.Set(normal0).NegateLocal();
                        }
                    }
                }
                else if (hasVertex3)
                {
                    if (convex2)
                    {
                        front = offset1 >= 0.0f || offset2 >= 0.0f;
                        if (front)
                        {
                            normal.Set(normal1);
                            lowerLimit.Set(normal1).NegateLocal();
                            upperLimit.Set(normal2);
                        }
                        else
                        {
                            normal.Set(normal1).NegateLocal();
                            lowerLimit.Set(normal1).NegateLocal();
                            upperLimit.Set(normal1);
                        }
                    }
                    else
                    {
                        front = offset1 >= 0.0f && offset2 >= 0.0f;
                        if (front)
                        {
                            normal.Set(normal1);
                            lowerLimit.Set(normal1).NegateLocal();
                            upperLimit.Set(normal1);
                        }
                        else
                        {
                            normal.Set(normal1).NegateLocal();
                            lowerLimit.Set(normal2).NegateLocal();
                            upperLimit.Set(normal1);
                        }
                    }
                }
                else
                {
                    front = offset1 >= 0.0f;
                    if (front)
                    {
                        normal.Set(normal1);
                        lowerLimit.Set(normal1).NegateLocal();
                        upperLimit.Set(normal1).NegateLocal();
                    }
                    else
                    {
                        normal.Set(normal1).NegateLocal();
                        lowerLimit.Set(normal1);
                        upperLimit.Set(normal1);
                    }
                }

                // Get polygonB in frameA
                this.polygonB.Count = polygonB.VertexCount;
                for (int i = 0; i < polygonB.VertexCount; ++i)
                {
                    Transform.MulToOutUnsafe(xf, polygonB.Vertices[i], this.polygonB.Vertices[i]);
                    Rot.MulToOutUnsafe(xf.Q, polygonB.Normals[i], this.polygonB.Normals[i]);
                }

                radius = 2.0f * Settings.POLYGON_RADIUS;

                manifold.PointCount = 0;

                ComputeEdgeSeparation(edgeAxis);

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

                if (edgeAxis.Separation > radius)
                {
                    return;
                }

                ComputePolygonSeparation(polygonAxis);
                if (polygonAxis.Type != EPAxis.EPAxisType.Unknown && polygonAxis.Separation > radius)
                {
                    return;
                }

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

                EPAxis primaryAxis;
                if (polygonAxis.Type == EPAxis.EPAxisType.Unknown)
                {
                    primaryAxis = edgeAxis;
                }
                else if (polygonAxis.Separation > k_relativeTol * edgeAxis.Separation + k_absoluteTol)
                {
                    primaryAxis = polygonAxis;
                }
                else
                {
                    primaryAxis = edgeAxis;
                }

                // ClipVertex[] ie = new ClipVertex[2];
                if (primaryAxis.Type == EPAxis.EPAxisType.EdgeA)
                {
                    manifold.Type = Manifold.ManifoldType.FaceA;

                    // Search for the polygon normal that is most anti-parallel to the edge normal.
                    int bestIndex = 0;
                    float bestValue = Vec2.Dot(normal, this.polygonB.Normals[0]);
                    for (int i = 1; i < this.polygonB.Count; ++i)
                    {
                        float value = Vec2.Dot(normal, this.polygonB.Normals[i]);
                        if (value < bestValue)
                        {
                            bestValue = value;
                            bestIndex = i;
                        }
                    }

                    int i1 = bestIndex;
                    int i2 = i1 + 1 < this.polygonB.Count ? i1 + 1 : 0;

                    ie[0].V.Set(this.polygonB.Vertices[i1]);
                    ie[0].Id.IndexA = 0;
                    ie[0].Id.IndexB = (sbyte)i1;
                    ie[0].Id.TypeA = (sbyte)ContactID.Type.Face;
                    ie[0].Id.TypeB = (sbyte)ContactID.Type.Vertex;

                    ie[1].V.Set(this.polygonB.Vertices[i2]);
                    ie[1].Id.IndexA = 0;
                    ie[1].Id.IndexB = (sbyte)i2;
                    ie[1].Id.TypeA = (sbyte)ContactID.Type.Face;
                    ie[1].Id.TypeB = (sbyte)ContactID.Type.Vertex;

                    if (front)
                    {
                        rf.I1 = 0;
                        rf.I2 = 1;
                        rf.V1.Set(v1);
                        rf.V2.Set(v2);
                        rf.Normal.Set(normal1);
                    }
                    else
                    {
                        rf.I1 = 1;
                        rf.I2 = 0;
                        rf.V1.Set(v2);
                        rf.V2.Set(v1);
                        rf.Normal.Set(normal1).NegateLocal();
                    }
                }
                else
                {
                    manifold.Type = Manifold.ManifoldType.FaceB;

                    ie[0].V.Set(v1);
                    ie[0].Id.IndexA = 0;
                    ie[0].Id.IndexB = (sbyte)primaryAxis.Index;
                    ie[0].Id.TypeA = (sbyte)ContactID.Type.Vertex;
                    ie[0].Id.TypeB = (sbyte)ContactID.Type.Face;

                    ie[1].V.Set(v2);
                    ie[1].Id.IndexA = 0;
                    ie[1].Id.IndexB = (sbyte)primaryAxis.Index;
                    ie[1].Id.TypeA = (sbyte)ContactID.Type.Vertex;
                    ie[1].Id.TypeB = (sbyte)ContactID.Type.Face;

                    rf.I1 = primaryAxis.Index;
                    rf.I2 = rf.I1 + 1 < this.polygonB.Count ? rf.I1 + 1 : 0;
                    rf.V1.Set(this.polygonB.Vertices[rf.I1]);
                    rf.V2.Set(this.polygonB.Vertices[rf.I2]);
                    rf.Normal.Set(this.polygonB.Normals[rf.I1]);
                }

                rf.SideNormal1.Set(rf.Normal.Y, -rf.Normal.X);
                rf.SideNormal2.Set(rf.SideNormal1).NegateLocal();
                rf.SideOffset1 = Vec2.Dot(rf.SideNormal1, rf.V1);
                rf.SideOffset2 = Vec2.Dot(rf.SideNormal2, rf.V2);

                // Clip incident edge against extruded edge1 side edges.
                int np;

                // Clip to box side 1
                np = ClipSegmentToLine(clipPoints1, ie, rf.SideNormal1, rf.SideOffset1, rf.I1);

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

                // Clip to negative box side 1
                np = ClipSegmentToLine(clipPoints2, clipPoints1, rf.SideNormal2, rf.SideOffset2, rf.I2);

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

                // Now clipPoints2 contains the clipped points.
                if (primaryAxis.Type == EPAxis.EPAxisType.EdgeA)
                {
                    manifold.LocalNormal.Set(rf.Normal);
                    manifold.LocalPoint.Set(rf.V1);
                }
                else
                {
                    manifold.LocalNormal.Set(polygonB.Normals[rf.I1]);
                    manifold.LocalPoint.Set(polygonB.Vertices[rf.I1]);
                }

                int pointCount = 0;
                for (int i = 0; i < Settings.MAX_MANIFOLD_POINTS; ++i)
                {
                    float separation = Vec2.Dot(rf.Normal, temp.Set(clipPoints2[i].V).SubLocal(rf.V1));

                    if (separation <= radius)
                    {
                        ManifoldPoint cp = manifold.Points[pointCount];

                        if (primaryAxis.Type == EPAxis.EPAxisType.EdgeA)
                        {
                            // cp.localPoint = MulT(m_xf, clipPoints2[i].v);
                            Transform.MulTransToOutUnsafe(xf, clipPoints2[i].V, cp.LocalPoint);
                            cp.Id.Set(clipPoints2[i].Id);
                        }
                        else
                        {
                            cp.LocalPoint.Set(clipPoints2[i].V);
                            cp.Id.TypeA = clipPoints2[i].Id.TypeB;
                            cp.Id.TypeB = clipPoints2[i].Id.TypeA;
                            cp.Id.IndexA = clipPoints2[i].Id.IndexB;
                            cp.Id.IndexB = clipPoints2[i].Id.IndexA;
                        }

                        ++pointCount;
                    }
                }

                manifold.PointCount = pointCount;
            }