예제 #1
0
 /// Implement Shape.
 public override Shape Clone()
 {
     var edge = new EdgeShape();
     edge._hasVertex0 = _hasVertex0;
     edge._hasVertex3 = _hasVertex3;
     edge._radius = _radius;
     edge._vertex0 = _vertex0;
     edge._vertex1 = _vertex1;
     edge._vertex2 = _vertex2;
     edge._vertex3 = _vertex3;
     return edge;
 }
예제 #2
0
        /// <summary> Get a child edge.
        /// </summary>
        public void GetChildEdge(ref EdgeShape edge, int index)
        {
            Debug.Assert(2 <= _count);
            Debug.Assert(0 <= index && index < _count);
            edge.ShapeType   = ShapeType.Edge;
            edge._radius     = _radius;
            edge._hasVertex0 = true;
            edge._hasVertex3 = true;

            int i0 = index - 1 >= 0 ? index - 1 : _count - 1;
            int i1 = index;
            int i2 = index + 1 < _count ? index + 1 : 0;
            int i3 = index + 2;

            while (i3 >= _count)
            {
                i3 -= _count;
            }

            edge._vertex0 = _vertices[i0];
            edge._vertex1 = _vertices[i1];
            edge._vertex2 = _vertices[i2];
            edge._vertex3 = _vertices[i3];
        }
예제 #3
0
파일: Edge.cs 프로젝트: GretelF/squircle
    public EdgeTest()
    {
        {
            BodyDef bd = new BodyDef();
            Body ground = _world.CreateBody(bd);

            Vector2 v1 = new Vector2(-10.0f, 0.0f);
            Vector2 v2 = new Vector2(-7.0f, -1.0f);
            Vector2 v3 = new Vector2(-4.0f, 0.0f);
            Vector2 v4 = new Vector2(0.0f, 0.0f);
            Vector2 v5 = new Vector2(4.0f, 0.0f);
            Vector2 v6 = new Vector2(7.0f, 1.0f);
            Vector2 v7 = new Vector2(10.0f, 0.0f);

            EdgeShape shape = new EdgeShape();

            shape.Set(v1, v2);
            //shape._index1 = 0;
            //shape._index2 = 1;
            shape._hasVertex3 = true;
            shape._vertex3 = v3;
            ground.CreateFixture(shape, 0.0f);

            shape.Set(v2, v3);
            //shape._index1 = 1;
            //shape._index2 = 2;
            shape._hasVertex0 = true;
            shape._hasVertex3 = true;
            shape._vertex0 = v1;
            shape._vertex3 = v4;
            ground.CreateFixture(shape, 0.0f);

            shape.Set(v3, v4);
            //shape._index1 = 2;
            //shape._index2 = 3;
            shape._hasVertex0 = true;
            shape._hasVertex3 = true;
            shape._vertex0 = v2;
            shape._vertex3 = v5;
            ground.CreateFixture(shape, 0.0f);

            shape.Set(v4, v5);
            //shape._index1 = 3;
            //shape._index2 = 4;
            shape._hasVertex0 = true;
            shape._hasVertex3 = true;
            shape._vertex0 = v3;
            shape._vertex3 = v6;
            ground.CreateFixture(shape, 0.0f);

            shape.Set(v5, v6);
            //shape._index1 = 4;
            //shape._index2 = 5;
            shape._hasVertex0 = true;
            shape._hasVertex3 = true;
            shape._vertex0 = v4;
            shape._vertex3 = v7;
            ground.CreateFixture(shape, 0.0f);

            shape.Set(v6, v7);
            //shape._index1 = 5;
            //shape._index2 = 6;
            shape._hasVertex0 = true;
            shape._vertex0 = v5;
            ground.CreateFixture(shape, 0.0f);
        }

        {
            BodyDef bd = new BodyDef();
            bd.type = BodyType.Dynamic;
            bd.position = new Vector2(-0.5f, 0.5f);
            bd.allowSleep = false;
            Body body = _world.CreateBody(bd);

            CircleShape shape = new CircleShape();
            shape._radius = 0.5f;

            body.CreateFixture(shape, 1.0f);
        }

        {
            BodyDef bd = new BodyDef();
            bd.type = BodyType.Dynamic;
            bd.position = new Vector2(0.5f, 0.5f);
            bd.allowSleep = false;
            Body body = _world.CreateBody(bd);

            PolygonShape shape = new PolygonShape();
            shape.SetAsBox(0.5f, 0.5f);

            body.CreateFixture(shape, 1.0f);
        }
    }
예제 #4
0
        public static void CollideEdgeAndPolygon(ref Manifold manifold,
            EdgeShape edgeA, ref Transform xfA,
            PolygonShape polygonB_in, ref Transform xfB)
        {
            manifold._pointCount = 0;

            Transform xf;
            MathUtils.MultiplyT(ref xfA, ref xfB, out xf);

            // Create a polygon for edge shape A
            s_polygonA.SetAsEdge(edgeA._vertex1, edgeA._vertex2);

            // Build polygonB in frame A
            s_polygonB._radius = polygonB_in._radius;
            s_polygonB._vertexCount = polygonB_in._vertexCount;
            s_polygonB._centroid = MathUtils.Multiply(ref xf, polygonB_in._centroid);
            for (int i = 0; i < s_polygonB._vertexCount; ++i)
            {
                s_polygonB._vertices[i] = MathUtils.Multiply(ref xf, polygonB_in._vertices[i]);
                s_polygonB._normals[i] = MathUtils.Multiply(ref xf.R, polygonB_in._normals[i]);
            }

            float totalRadius = s_polygonA._radius + s_polygonB._radius;

            // Edge geometry
            Vector2 v1 = edgeA._vertex1;
            Vector2 v2 = edgeA._vertex2;
            Vector2 e = v2 - v1;
            Vector2 edgeNormal = new Vector2(e.Y, -e.X);
            edgeNormal.Normalize();

            // Determine side
            bool isFrontSide = Vector2.Dot(edgeNormal, s_polygonB._centroid - v1) >= 0.0f;
            if (isFrontSide == false)
            {
                edgeNormal = -edgeNormal;
            }

            // Compute primary separating axis
            EPAxis edgeAxis = ComputeEdgeSeperation(v1, v2, edgeNormal, s_polygonB, totalRadius);
            if (edgeAxis.separation > totalRadius)
            {
                // Shapes are separated
                return;
            }

            // Classify adjacent edges
            FixedArray2<EdgeType> types = new FixedArray2<EdgeType>();
            //types[0] = EdgeType.Isolated;
            //types[1] = EdgeType.Isolated;
            if (edgeA._hasVertex0)
            {
                Vector2 v0 = edgeA._vertex0;
                float s = Vector2.Dot(edgeNormal, v0 - v1);

                if (s > 0.1f * Settings.b2_linearSlop)
                {
                    types[0] = EdgeType.Concave;
                }
                else if (s >= -0.1f * Settings.b2_linearSlop)
                {
                    types[0] = EdgeType.Flat;
                }
                else
                {
                    types[0] = EdgeType.Convex;
                }
            }

            if (edgeA._hasVertex3)
            {
                Vector2 v3 = edgeA._vertex3;
                float s = Vector2.Dot(edgeNormal, v3 - v2);
                if (s > 0.1f * Settings.b2_linearSlop)
                {
                    types[1] = EdgeType.Concave;
                }
                else if (s >= -0.1f * Settings.b2_linearSlop)
                {
                    types[1] = EdgeType.Flat;
                }
                else
                {
                    types[1] = EdgeType.Convex;
                }
            }

            if (types[0] == EdgeType.Convex)
            {
                // Check separation on previous edge.
                Vector2 v0 = edgeA._vertex0;
                Vector2 e0 = v1 - v0;

                Vector2 n0 = new Vector2(e0.Y, -e0.X);
                n0.Normalize();
                if (isFrontSide == false)
                {
                    n0 = -n0;
                }

                EPAxis axis1 = ComputeEdgeSeperation(v0, v1, n0, s_polygonB, totalRadius);
                if (axis1.separation > edgeAxis.separation)
                {
                    // The polygon should collide with previous edge
                    return;
                }
            }

            if (types[1] == EdgeType.Convex)
            {
                // Check separation on next edge.
                Vector2 v3 = edgeA._vertex3;
                Vector2 e2 = v3 - v2;

                Vector2 n2 = new Vector2(e2.Y, -e2.X);
                n2.Normalize();
                if (isFrontSide == false)
                {
                    n2 = -n2;
                }

                EPAxis axis2 = ComputeEdgeSeperation(v2, v3, n2, s_polygonB, totalRadius);
                if (axis2.separation > edgeAxis.separation)
                {
                    // The polygon should collide with the next edge
                    return;
                }
            }

            EPAxis polygonAxis = ComputePolygonSeperation(v1, v2, edgeNormal, s_polygonB, totalRadius);
            if (polygonAxis.separation > totalRadius)
            {
                return;
            }

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

            EPAxis primaryAxis;
            if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol)
            {
                primaryAxis = polygonAxis;
            }
            else
            {
                primaryAxis = edgeAxis;
            }

            PolygonShape poly1;
            PolygonShape poly2;
            if (primaryAxis.type == EPAxisType.EdgeA)
            {
                poly1 = s_polygonA;
                poly2 = s_polygonB;
                if (isFrontSide == false)
                {
                    primaryAxis.index = 1;
                }
                manifold._type = ManifoldType.FaceA;
            }
            else
            {
                poly1 = s_polygonB;
                poly2 = s_polygonA;
                manifold._type = ManifoldType.FaceB;
            }

            int edge1 = primaryAxis.index;

            FixedArray2<ClipVertex> incidentEdge = new FixedArray2<ClipVertex>();
            FindIncidentEdge(ref incidentEdge, poly1, primaryAxis.index, poly2);
            int count1 = poly1._vertexCount;
            int iv1 = edge1;
            int iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0;

            Vector2 v11 = poly1._vertices[iv1];
            Vector2 v12 = poly1._vertices[iv2];

            Vector2 tangent = v12 - v11;
            tangent.Normalize();

            Vector2 normal = MathUtils.Cross(tangent, 1.0f);
            Vector2 planePoint = 0.5f * (v11 + v12);

            // Face offset.
            float frontOffset = Vector2.Dot(normal, v11);

            // Side offsets, extended by polytope skin thickness.
            float sideOffset1 = -Vector2.Dot(tangent, v11) + totalRadius;
            float sideOffset2 = Vector2.Dot(tangent, v12) + totalRadius;

            // Clip incident edge against extruded edge1 side edges.
            FixedArray2<ClipVertex> clipPoints1;
            FixedArray2<ClipVertex> clipPoints2;
            int np;

            // Clip to box side 1
            np = ClipSegmentToLine(out clipPoints1, ref incidentEdge, -tangent, sideOffset1, iv1);

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

            // Clip to negative box side 1
            np = ClipSegmentToLine(out clipPoints2, ref clipPoints1,  tangent, sideOffset2, iv2);

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

            // Now clipPoints2 contains the clipped points.
            if (primaryAxis.type == EPAxisType.EdgeA)
            {
                manifold._localNormal = normal;
                manifold._localPoint = planePoint;
            }
            else
            {
                manifold._localNormal = MathUtils.MultiplyT(ref xf.R, normal);
                manifold._localPoint = MathUtils.MultiplyT(ref xf, planePoint);
            }

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

                separation = Vector2.Dot(normal, clipPoints2[i].v) - frontOffset;

                if (separation <= totalRadius)
                {
                    ManifoldPoint cp = manifold._points[pointCount];

                    if (primaryAxis.type == EPAxisType.EdgeA)
                    {
                        cp.LocalPoint = MathUtils.MultiplyT(ref xf, clipPoints2[i].v);
                        cp.Id = clipPoints2[i].id;
                    }
                    else
                    {
                        cp.LocalPoint = clipPoints2[i].v;
                        cp.Id.Features.typeA = clipPoints2[i].id.Features.typeB;
                        cp.Id.Features.typeB = clipPoints2[i].id.Features.typeA;
                        cp.Id.Features.indexA = clipPoints2[i].id.Features.indexB;
                        cp.Id.Features.indexB = clipPoints2[i].id.Features.indexA;
                    }

                    manifold._points[pointCount] = cp;
                    if (cp.Id.Features.typeA == (byte)ContactFeatureType.Vertex && types[cp.Id.Features.indexA] == EdgeType.Flat)
                    {
                        continue;
                    }

                    ++pointCount;
                }
            }

            manifold._pointCount = pointCount;
        }
예제 #5
0
        // Compute contact points for edge versus circle.
        // This accounts for edge connectivity.
        public static void CollideEdgeAndCircle(ref Manifold manifold,
            EdgeShape edgeA, ref Transform xfA,
            CircleShape circleB, ref Transform xfB)
        {
            manifold._pointCount = 0;

            // Compute circle in frame of edge
            Vector2 Q = MathUtils.MultiplyT(ref xfA, MathUtils.Multiply(ref xfB, circleB._p));

            Vector2 A = edgeA._vertex1, B = edgeA._vertex2;
            Vector2 e = B - A;

            // Barycentric coordinates
            float u = Vector2.Dot(e, B - Q);
            float v = Vector2.Dot(e, Q - A);

            float radius = edgeA._radius + circleB._radius;

            ContactFeature cf;
            cf.indexB = 0;
            cf.typeB = (byte)ContactFeatureType.Vertex;

            Vector2 P, d;

            // Region A
            if (v <= 0.0f)
            {
                P = A;
                d = Q - P;
                float dd = Vector2.Dot(d, d);
                if (dd > radius * radius)
                {
                    return;
                }

                // Is there an edge connected to A?
                if (edgeA._hasVertex0)
                {
                    Vector2 A1 = edgeA._vertex0;
                    Vector2 B1 = A;
                    Vector2 e1 = B1 - A1;
                    float u1 = Vector2.Dot(e1, B1 - Q);

                    // Is the circle in Region AB of the previous edge?
                    if (u1 > 0.0f)
                    {
                        return;
                    }
                }

                cf.indexA = 0;
                cf.typeA = (byte)ContactFeatureType.Vertex;
                manifold._pointCount = 1;
                manifold._type = ManifoldType.Circles;
                manifold._localNormal = Vector2.Zero;
                manifold._localPoint = P;
                var mp = new ManifoldPoint();
                mp.Id.Key = 0;
                mp.Id.Features = cf;
                mp.LocalPoint = circleB._p;
                manifold._points[0] = mp;
                return;
            }

            // Region B
            if (u <= 0.0f)
            {
                P = B;
                d = Q - P;
                float dd = Vector2.Dot(d, d);
                if (dd > radius * radius)
                {
                    return;
                }

                // Is there an edge connected to B?
                if (edgeA._hasVertex3)
                {
                    Vector2 B2 = edgeA._vertex3;
                    Vector2 A2 = B;
                    Vector2 e2 = B2 - A2;
                    float v2 = Vector2.Dot(e2, Q - A2);

                    // Is the circle in Region AB of the next edge?
                    if (v2 > 0.0f)
                    {
                        return;
                    }
                }

                cf.indexA = 1;
                cf.typeA = (byte)ContactFeatureType.Vertex;
                manifold._pointCount = 1;
                manifold._type = ManifoldType.Circles;
                manifold._localNormal = Vector2.Zero;
                manifold._localPoint = P;
                var mp = new ManifoldPoint();
                mp.Id.Key = 0;
                mp.Id.Features = cf;
                mp.LocalPoint = circleB._p;
                manifold._points[0] = mp;
                return;
            }

            // Region AB
            float den = Vector2.Dot(e, e);
            Debug.Assert(den > 0.0f);
            P = (1.0f / den) * (u * A + v * B);
            d = Q - P;
            float dd2 = Vector2.Dot(d, d);
            if (dd2 > radius * radius)
            {
                return;
            }

            Vector2 n = new Vector2(-e.Y, e.X);
            if (Vector2.Dot(n, Q - A) < 0.0f)
            {
                n = new Vector2(-n.X, -n.Y);
            }
            n.Normalize();

            cf.indexA = 0;
            cf.typeA = (byte)ContactFeatureType.Face;
            manifold._pointCount = 1;
            manifold._type = ManifoldType.FaceA;
            manifold._localNormal = n;
            manifold._localPoint = A;
            var mp2 = new ManifoldPoint();
            mp2.Id.Key = 0;
            mp2.Id.Features = cf;
            mp2.LocalPoint = circleB._p;
            manifold._points[0] = mp2;
        }
예제 #6
0
파일: Builder.cs 프로젝트: ASOIU/BlockWars
        private bool IsLegalPosition()
        {
            EdgeShape shape = new EdgeShape();

            bool isLegal = false;
            if (mBuildingObjectType == PlayerData.ObjectType.Gun)
            {
                isLegal = true;
            }
            else
            {
                isLegal = true;
                List<Box> boxes = mGameObjectCollection.Boxes;
                Body buildingBlockBody = ((Box)mBuildingBlock).mBody;
                Shape shape1 = buildingBlockBody.GetFixtureList().GetShape();
                Transform transform1, transform2;
                buildingBlockBody.GetTransform(out transform1);
                for (int i = 0; i < boxes.Count; i++)
                {
                    Body body = boxes[i].mBody;
                    Shape shape2 = body.GetFixtureList().GetShape();
                    body.GetTransform(out transform2);
                    bool isOverlap = AABB.TestOverlap(shape1, 0, shape2, 0, ref transform1, ref transform2);
                    if (isOverlap)
                    {
                        isLegal = false;
                        break;
                    }
                }
            }
            return isLegal;
        }
예제 #7
0
        /// Get a child edge.
        public void GetChildEdge(ref EdgeShape edge, int index)
        {
            Debug.Assert(2 <= _count);
            Debug.Assert(0 <= index && index < _count);
            edge.ShapeType = ShapeType.Edge;
            edge._radius = _radius;
            edge._hasVertex0 = true;
            edge._hasVertex3 = true;

            int i0 = index - 1 >= 0 ? index - 1 : _count - 1;
            int i1 = index;
            int i2 = index + 1 < _count ? index + 1 : 0;
            int i3 = index + 2;
            while (i3 >= _count)
            {
                i3 -= _count;
            }

            edge._vertex0 = _vertices[i0];
            edge._vertex1 = _vertices[i1];
            edge._vertex2 = _vertices[i2];
            edge._vertex3 = _vertices[i3];
        }
예제 #8
0
파일: Level.cs 프로젝트: GretelF/squircle
        private Body CreatePhysicalViewBounds()
        {
            var bodyDef = new BodyDef();
            bodyDef.type = BodyType.Static;
            var body = World.CreateBody(bodyDef);
            var edges = new EdgeShape[]{new EdgeShape(), new EdgeShape(), new EdgeShape(), new EdgeShape()};

            var viewport = game.GraphicsDevice.Viewport;

            var X = ConvertToBox2D(viewport.Width / 2);
            var Y = ConvertToBox2D(viewport.Height / 2);
            edges[0].Set(new Vector2(-X, -Y), new Vector2(+X, -Y));
            edges[1].Set(new Vector2(+X, -Y), new Vector2(+X, +Y));
            edges[2].Set(new Vector2(+X, +Y), new Vector2(-X, +Y));
            edges[3].Set(new Vector2(-X, +Y), new Vector2(-X, -Y));

            foreach (var edge in edges)
            {
                var fixtureDef = new FixtureDef();
                fixtureDef.shape = edge;
                fixtureDef.friction = 0.0f;
                body.CreateFixture(fixtureDef);
            }

            return body;
        }