Esempio n. 1
0
        /// Implement Shape.
        public override Shape Clone()
        {
            CircleShape shape = new CircleShape();
            shape.ShapeType = ShapeType;
            shape._radius = _radius;
            shape._p = _p;

            return shape;
        }
Esempio n. 2
0
        /// Compute the collision manifold between two circles.
        public static void CollideCircles(ref Manifold manifold,
					          CircleShape circle1, ref XForm xf1,
					          CircleShape circle2, ref XForm xf2)
        {
            manifold._pointCount = 0;

            Vector2 p1 = MathUtils.Multiply(ref xf1, circle1._p);
            Vector2 p2 = MathUtils.Multiply(ref xf2, circle2._p);

            Vector2 d = p2 - p1;
            float distSqr = Vector2.Dot(d, d);
            float radius = circle1._radius + circle2._radius;
            if (distSqr > radius * radius)
            {
                return;
            }

            manifold._type = ManifoldType.Circles;
            manifold._localPoint = circle1._p;
            manifold._localPlaneNormal = Vector2.Zero;
            manifold._pointCount = 1;

            var p0 = manifold._points[0];

            p0.LocalPoint = circle2._p;
            p0.Id.Key = 0;

            manifold._points[0] = p0;
        }
Esempio n. 3
0
        /// Compute the collision manifold between a polygon and a circle.
        public static void CollidePolygonAndCircle(ref Manifold manifold,
							           PolygonShape polygon, ref XForm xf1,
							           CircleShape circle, ref XForm xf2)
        {
            manifold._pointCount = 0;

            // Compute circle position in the frame of the polygon.
            Vector2 c = MathUtils.Multiply(ref xf2, circle._p);
            Vector2 cLocal = MathUtils.MultiplyT(ref xf1, c);

            // Find the min separating edge.
            int normalIndex = 0;
            float separation = -Settings.b2_FLT_MAX;
            float radius = polygon._radius + circle._radius;
            int vertexCount = polygon._vertexCount;

            for (int i = 0; i < vertexCount; ++i)
            {
                float s = Vector2.Dot(polygon._normals[i], cLocal - polygon._vertices[i]);

                if (s > radius)
                {
                    // Early out.
                    return;
                }

                if (s > separation)
                {
                    separation = s;
                    normalIndex = i;
                }
            }

            // Vertices that subtend the incident face.
            int vertIndex1 = normalIndex;
            int vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
            Vector2 v1 = polygon._vertices[vertIndex1];
            Vector2 v2 = polygon._vertices[vertIndex2];

            // If the center is inside the polygon ...
            if (separation < Settings.b2_FLT_EPSILON)
            {
                manifold._pointCount = 1;
                manifold._type = ManifoldType.FaceA;
                manifold._localPlaneNormal = polygon._normals[normalIndex];
                manifold._localPoint = 0.5f * (v1 + v2);

                var p0 = manifold._points[0];

                p0.LocalPoint = circle._p;
                p0.Id.Key = 0;

                manifold._points[0] = p0;

                return;
            }

            // Compute barycentric coordinates
            float u1 = Vector2.Dot(cLocal - v1, v2 - v1);
            float u2 = Vector2.Dot(cLocal - v2, v1 - v2);
            if (u1 <= 0.0f)
            {
                if (Vector2.DistanceSquared(cLocal, v1) > radius * radius)
                {
                    return;
                }

                manifold._pointCount = 1;
                manifold._type = ManifoldType.FaceA;
                manifold._localPlaneNormal = cLocal - v1;
                manifold._localPlaneNormal.Normalize();
                manifold._localPoint = v1;

                var p0b = manifold._points[0];

                p0b.LocalPoint = circle._p;
                p0b.Id.Key = 0;

                manifold._points[0] = p0b;

            }
            else if (u2 <= 0.0f)
            {
                if (Vector2.DistanceSquared(cLocal, v2) > radius * radius)
                {
                    return;
                }

                manifold._pointCount = 1;
                manifold._type = ManifoldType.FaceA;
                manifold._localPlaneNormal = cLocal - v2;
                manifold._localPlaneNormal.Normalize();
                manifold._localPoint = v2;

                var p0c = manifold._points[0];

                p0c.LocalPoint = circle._p;
                p0c.Id.Key = 0;

                manifold._points[0] = p0c;
            }
            else
            {
                Vector2 faceCenter = 0.5f * (v1 + v2);
                float separation2 = Vector2.Dot(cLocal - faceCenter, polygon._normals[vertIndex1]);
                if (separation2 > radius)
                {
                    return;
                }

                manifold._pointCount = 1;
                manifold._type = ManifoldType.FaceA;
                manifold._localPlaneNormal = polygon._normals[vertIndex1];
                manifold._localPoint = faceCenter;

                var p0d = manifold._points[0];

                p0d.LocalPoint = circle._p;
                p0d.Id.Key = 0;

                manifold._points[0] = p0d;
            }
        }
Esempio n. 4
0
        /// Compute the collision manifold between a polygon and a circle.
        public static void CollidePolygonAndCircle(ref Manifold manifold,
                                                   PolygonShape polygon, ref XForm xf1,
                                                   CircleShape circle, ref XForm xf2)
        {
            manifold._pointCount = 0;

            // Compute circle position in the frame of the polygon.
            Vector2 c      = MathUtils.Multiply(ref xf2, circle._p);
            Vector2 cLocal = MathUtils.MultiplyT(ref xf1, c);

            // Find the min separating edge.
            int   normalIndex = 0;
            float separation  = -Settings.b2_FLT_MAX;
            float radius      = polygon._radius + circle._radius;
            int   vertexCount = polygon._vertexCount;

            for (int i = 0; i < vertexCount; ++i)
            {
                float s = Vector2.Dot(polygon._normals[i], cLocal - polygon._vertices[i]);

                if (s > radius)
                {
                    // Early out.
                    return;
                }

                if (s > separation)
                {
                    separation  = s;
                    normalIndex = i;
                }
            }

            // Vertices that subtend the incident face.
            int     vertIndex1 = normalIndex;
            int     vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
            Vector2 v1         = polygon._vertices[vertIndex1];
            Vector2 v2         = polygon._vertices[vertIndex2];

            // If the center is inside the polygon ...
            if (separation < Settings.b2_FLT_EPSILON)
            {
                manifold._pointCount       = 1;
                manifold._type             = ManifoldType.FaceA;
                manifold._localPlaneNormal = polygon._normals[normalIndex];
                manifold._localPoint       = 0.5f * (v1 + v2);

                var p0 = manifold._points[0];

                p0.LocalPoint = circle._p;
                p0.Id.Key     = 0;

                manifold._points[0] = p0;

                return;
            }

            // Compute barycentric coordinates
            float u1 = Vector2.Dot(cLocal - v1, v2 - v1);
            float u2 = Vector2.Dot(cLocal - v2, v1 - v2);

            if (u1 <= 0.0f)
            {
                if (Vector2.DistanceSquared(cLocal, v1) > radius * radius)
                {
                    return;
                }

                manifold._pointCount       = 1;
                manifold._type             = ManifoldType.FaceA;
                manifold._localPlaneNormal = cLocal - v1;
                manifold._localPlaneNormal.Normalize();
                manifold._localPoint = v1;

                var p0b = manifold._points[0];

                p0b.LocalPoint = circle._p;
                p0b.Id.Key     = 0;

                manifold._points[0] = p0b;
            }
            else if (u2 <= 0.0f)
            {
                if (Vector2.DistanceSquared(cLocal, v2) > radius * radius)
                {
                    return;
                }

                manifold._pointCount       = 1;
                manifold._type             = ManifoldType.FaceA;
                manifold._localPlaneNormal = cLocal - v2;
                manifold._localPlaneNormal.Normalize();
                manifold._localPoint = v2;

                var p0c = manifold._points[0];

                p0c.LocalPoint = circle._p;
                p0c.Id.Key     = 0;

                manifold._points[0] = p0c;
            }
            else
            {
                Vector2 faceCenter  = 0.5f * (v1 + v2);
                float   separation2 = Vector2.Dot(cLocal - faceCenter, polygon._normals[vertIndex1]);
                if (separation2 > radius)
                {
                    return;
                }

                manifold._pointCount       = 1;
                manifold._type             = ManifoldType.FaceA;
                manifold._localPlaneNormal = polygon._normals[vertIndex1];
                manifold._localPoint       = faceCenter;

                var p0d = manifold._points[0];

                p0d.LocalPoint = circle._p;
                p0d.Id.Key     = 0;

                manifold._points[0] = p0d;
            }
        }