예제 #1
0
        private void Reset(FSFixture fA, int indexA, FSFixture fB, int indexB)
        {
            Flags = ContactFlags.Enabled;

            FixtureA = fA;
            FixtureB = fB;

            ChildIndexA = indexA;
            ChildIndexB = indexB;

            Manifold.PointCount = 0;

            NodeA.Contact = null;
            NodeA.Prev    = null;
            NodeA.Next    = null;
            NodeA.Other   = null;

            NodeB.Contact = null;
            NodeB.Prev    = null;
            NodeB.Next    = null;
            NodeB.Other   = null;

            TOICount = 0;

            //FPE: We only set the friction and restitution if we are not destroying the contact
            if (FixtureA != null && FixtureB != null)
            {
                Friction    = FSSettings.MixFriction(FixtureA.Friction, FixtureB.Friction);
                Restitution = FSSettings.MixRestitution(FixtureA.Restitution, FixtureB.Restitution);
            }

            TangentSpeed = 0;
        }
예제 #2
0
        private void PreSolve(Contact contact, ref Manifold oldManifold)
        {
            if ((Flags & DebugViewFlags.ContactPoints) == DebugViewFlags.ContactPoints)
            {
                Manifold manifold = contact.Manifold;

                if (manifold.PointCount == 0)
                {
                    return;
                }

                FSFixture fixtureA = contact.FixtureA;

                FixedArray2 <PointState> state1, state2;
                Collision.Collision.GetPointStates(out state1, out state2, ref oldManifold, ref manifold);

                FixedArray2 <FVector2> points;
                FVector2 normal;
                contact.GetWorldManifold(out normal, out points);

                for (int i = 0; i < manifold.PointCount && _pointCount < MaxContactPoints; ++i)
                {
                    if (fixtureA == null)
                    {
                        _points[i] = new ContactPoint();
                    }
                    ContactPoint cp = _points[_pointCount];
                    cp.Position          = points[i];
                    cp.Normal            = normal;
                    cp.State             = state2[i];
                    _points[_pointCount] = cp;
                    ++_pointCount;
                }
            }
        }
 private bool OnCollisionEvent(FSFixture fixtureA, FSFixture fixtureB, Contact contact)
 {
     if (!lastContacts.Contains(contact))
     {
         lastContacts.Add(contact);
     }
     return(true);
 }
예제 #4
0
        public void DrawShape(FSFixture fixture, Transform xf, Color color)
        {
            switch (fixture.ShapeType)
            {
            case ShapeType.Circle:
            {
                CircleShape circle = (CircleShape)fixture.Shape;

                FVector2 center = MathUtils.Mul(ref xf, circle.Position);
                float    radius = circle.Radius;
                FVector2 axis   = MathUtils.Mul(xf.q, new FVector2(1.0f, 0.0f));

                DrawSolidCircle(center, radius, axis, color);
            }
            break;

            case ShapeType.Polygon:
            {
                PolygonShape poly        = (PolygonShape)fixture.Shape;
                int          vertexCount = poly.Vertices.Count;
                Debug.Assert(vertexCount <= FSSettings.MaxPolygonVertices);

                for (int i = 0; i < vertexCount; ++i)
                {
                    _tempVertices[i] = MathUtils.Mul(ref xf, poly.Vertices[i]);
                }

                DrawSolidPolygon(_tempVertices, vertexCount, color);
            }
            break;


            case ShapeType.Edge:
            {
                EdgeShape edge = (EdgeShape)fixture.Shape;
                FVector2  v1   = MathUtils.Mul(ref xf, edge.Vertex1);
                FVector2  v2   = MathUtils.Mul(ref xf, edge.Vertex2);
                DrawSegment(v1, v2, color);
            }
            break;

            case ShapeType.Chain:
            {
                ChainShape chain = (ChainShape)fixture.Shape;
                int        count = chain.Vertices.Count;

                FVector2 v1 = MathUtils.Mul(ref xf, chain.Vertices[count - 1]);
                DrawCircle(v1, 0.05f, color);
                for (int i = 0; i < count; ++i)
                {
                    FVector2 v2 = MathUtils.Mul(ref xf, chain.Vertices[i]);
                    DrawSegment(v1, v2, color);
                    v1 = v2;
                }
            }
            break;
            }
        }
예제 #5
0
    private bool OnCollisionEvent(FSFixture fixtureA, FSFixture fixtureB, Contact contact)
    {
        FSBody bodyB = fixtureB.Body;
        //if (bodyB.UserTag == "Respawn") {
        FVector2 normal;

        FarseerPhysics.Common.FixedArray2 <FVector2> contactPoints;
        contact.GetWorldManifold(out normal, out contactPoints);
        bodyB.ApplyLinearImpulse(normal * (-1 * Force));
        //}
        return(true);
    }
예제 #6
0
    private bool OnCollisionEvent(FSFixture fixtureA, FSFixture fixtureB, Contact contact)
    {
        FSBody bodyB = fixtureB.Body;
        //if (bodyB.UserTag == "Respawn") {
        FVector2 normal;

        FarseerPhysics.Common.FixedArray2 <FVector2> contactPoints;
        contact.GetWorldManifold(out normal, out contactPoints);
        bodyB.SetTransform(FSHelper.Vector3ToFVector2(RespawnPosition.position), 0f);
        bodyB.ResetDynamics();
        //}
        return(true);
    }
예제 #7
0
        internal static Contact Create(FSFixture fixtureA, int indexA, FSFixture fixtureB, int indexB)
        {
            ShapeType type1 = fixtureA.ShapeType;
            ShapeType type2 = fixtureB.ShapeType;

            Debug.Assert(ShapeType.Unknown < type1 && type1 < ShapeType.TypeCount);
            Debug.Assert(ShapeType.Unknown < type2 && type2 < ShapeType.TypeCount);

            Contact         c;
            Queue <Contact> pool = fixtureA.Body.World.ContactPool;

            if (pool.Count > 0)
            {
                c = pool.Dequeue();
                if ((type1 >= type2 || (type1 == ShapeType.Edge && type2 == ShapeType.Polygon))
                    &&
                    !(type2 == ShapeType.Edge && type1 == ShapeType.Polygon))
                {
                    c.Reset(fixtureA, indexA, fixtureB, indexB);
                }
                else
                {
                    c.Reset(fixtureB, indexB, fixtureA, indexA);
                }
            }
            else
            {
                // Edge+Polygon is non-symetrical due to the way Erin handles collision type registration.
                if ((type1 >= type2 || (type1 == ShapeType.Edge && type2 == ShapeType.Polygon))
                    &&
                    !(type2 == ShapeType.Edge && type1 == ShapeType.Polygon))
                {
                    c = new Contact(fixtureA, indexA, fixtureB, indexB);
                }
                else
                {
                    c = new Contact(fixtureB, indexB, fixtureA, indexA);
                }
            }

            c._type = _registers[(int)type1, (int)type2];

            return(c);
        }
예제 #8
0
        public override void Start()
        {
            base.Start();

            FSBody body;

            // Create 'basket'
            {
                body          = BodyFactory.CreateBody(FSWorldComponent.PhysicsWorld, new FVector2(150f / physScale, -100f / physScale));
                body.BodyType = BodyType.Dynamic;
                body.IsBullet = true;

                // bottom fixture
                FSFixture f = FixtureFactory.AttachRectangle(90f / physScale, 9f / physScale, 4f, FVector2.Zero, body);
                f.Restitution = 1.4f;

                // left fixture
                f             = FixtureFactory.AttachRectangle(9f / physScale, 90f / physScale, 4f, new FVector2(-43.5f / physScale, 50.5f / physScale), body);
                f.Restitution = 1.4f;

                // right fixture
                f             = FixtureFactory.AttachRectangle(9f / physScale, 90f / physScale, 4f, new FVector2(43.5f / physScale, 50.5f / physScale), body);
                f.Restitution = 1.4f;
            }

            // add some small circles for effect
            for (int i = 0; i < 5; i++)
            {
                body = BodyFactory.CreateBody(FSWorldComponent.PhysicsWorld, new FVector2((Random.value * 300f + 250f) / physScale, (Random.value * -320f - 20f) / physScale));
                FSFixture f = FixtureFactory.AttachCircle((Random.value * 10f + 5f) / physScale, 1f, body);
                f.Friction    = 0.3f;
                f.Restitution = 1.1f;
                body.BodyType = BodyType.Dynamic;
                body.IsBullet = true;
            }
        }
    public virtual void Start()
    {
        if (initialized)
        {
            return;
        }
        initialized = true;
        //Body = BodyFactory.CreateRectangle(FSWorldComponent.PhysicsWorld, 1f, 1f, Density);
        body = new FSBody(FSWorldComponent.PhysicsWorld);
        FSShapeComponent[] shapecs = GetComponentsInChildren <FSShapeComponent>();
        //print("shapes " + name + ": " + shapecs.Length);
        foreach (FSShapeComponent shp in shapecs)
        {
            FSFixture fixture = body.CreateFixture(shp.GetShape());
            fixture.Friction    = shp.Friction;
            fixture.Restitution = shp.Restitution;
            if (shp.tag.Length > 0)
            {
                fixture.UserTag = shp.tag;
            }

            if (shp.CollisionFilter == CollisionGroupDef.Manually)
            {
                fixture.CollisionCategories = shp.BelongsTo;
                fixture.CollidesWith        = shp.CollidesWith;
            }
            else if (shp.CollisionFilter == CollisionGroupDef.PresetFile)
            {
                if (shp.CollisionGroup != null)
                {
                    fixture.CollisionCategories = shp.CollisionGroup.BelongsTo;
                    fixture.CollidesWith        = shp.CollisionGroup.CollidesWith;
                }
            }
        }
        // try to get a single shape at the same level
        // if theres no children
        if (shapecs.Length < 1)
        {
            var shape = GetComponent <FSShapeComponent>();
            if (shape != null)
            {
                var fixture = body.CreateFixture(shape.GetShape());
                fixture.Friction    = shape.Friction;
                fixture.Restitution = shape.Restitution;
                if (shape.tag.Length > 0)
                {
                    fixture.UserTag = shape.tag;
                }
                if (shape.CollisionFilter == CollisionGroupDef.Manually)
                {
                    fixture.CollisionCategories = shape.BelongsTo;
                    fixture.CollidesWith        = shape.CollidesWith;
                }
                else if (shape.CollisionFilter == CollisionGroupDef.PresetFile)
                {
                    if (shape.CollisionGroup != null)
                    {
                        fixture.CollisionCategories = shape.CollisionGroup.BelongsTo;
                        fixture.CollidesWith        = shape.CollisionGroup.CollidesWith;
                    }
                }
            }
        }

        body.BodyType = Type;
        body.Position = new FVector2(transform.position.x, transform.position.y);
        body.Rotation = transform.rotation.eulerAngles.z * Mathf.Deg2Rad;
        if (this.tag.Length > 0)
        {
            body.UserTag = this.tag;
        }
        body.UserFSBodyComponent = this;
    }
예제 #10
0
        public override void Update(float dt)
        {
            _uniqueBodies.Clear();
            World.QueryAABB(fixture =>
            {
                if (fixture.Body.IsStatic || !fixture.Body.Awake)
                {
                    return(true);
                }

                if (!_uniqueBodies.ContainsKey(fixture.Body.BodyId))
                {
                    _uniqueBodies.Add(fixture.Body.BodyId, fixture.Body);
                }

                return(true);
            }, ref _container);

            foreach (KeyValuePair <int, FSBody> kv in _uniqueBodies)
            {
                FSBody body = kv.Value;

                FVector2 areac = FVector2.Zero;
                FVector2 massc = FVector2.Zero;
                float    area  = 0;
                float    mass  = 0;

                for (int j = 0; j < body.FixtureList.Count; j++)
                {
                    FSFixture fixture = body.FixtureList[j];

                    if (fixture.Shape.ShapeType != ShapeType.Polygon && fixture.Shape.ShapeType != ShapeType.Circle)
                    {
                        continue;
                    }

                    Shape shape = fixture.Shape;

                    FVector2 sc;
                    float    sarea = shape.ComputeSubmergedArea(_normal, _offset, body.Xf, out sc);
                    area    += sarea;
                    areac.X += sarea * sc.X;
                    areac.Y += sarea * sc.Y;

                    mass    += sarea * shape.Density;
                    massc.X += sarea * sc.X * shape.Density;
                    massc.Y += sarea * sc.Y * shape.Density;
                }

                areac.X /= area;
                areac.Y /= area;
                massc.X /= mass;
                massc.Y /= mass;

                if (area < FSSettings.Epsilon)
                {
                    continue;
                }

                //Buoyancy
                FVector2 buoyancyForce = -Density * area * _gravity;
                body.ApplyForce(buoyancyForce, massc);

                //Linear drag
                FVector2 dragForce = body.GetLinearVelocityFromWorldPoint(areac) - Velocity;
                dragForce *= -LinearDragCoefficient * area;
                body.ApplyForce(dragForce, areac);

                //Angular drag
                body.ApplyTorque(-body.Inertia / body.Mass * area * body.AngularVelocity * AngularDragCoefficient);
            }
        }
예제 #11
0
        public override void Start()
        {
            base.Start();

            CircleShape     circ;
            PolygonShape    box;
            FSFixture       fixture;
            FSRevoluteJoint joint;

            // Add 2 ragdolls along the top
            for (int i = 0; i < 2; i++)
            {
                float startX = 70f + Random.value * 20f + 480f * (float)i;
                float startY = (20f + Random.value * 50f) * -1f;

                // Head
                FSBody head = new FSBody(FSWorldComponent.PhysicsWorld);
                circ                = new CircleShape(12.5f / physScale, 1f);
                fixture             = new FSFixture(head, circ);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.3f;
                head.Position       = new FVector2(startX / physScale, startY / physScale);
                head.ApplyLinearImpulse(new FVector2(Random.value * 100f - 50f, Random.value * 100f - 50f), head.Position);
                head.BodyType = BodyType.Dynamic;

                // Torso 1
                FSBody torso1 = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(15f / physScale, 10f / physScale);
                fixture             = new FSFixture(torso1, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                torso1.Position     = new FVector2(startX / physScale, (startY - 28f) / physScale);
                torso1.BodyType     = BodyType.Dynamic;

                // Torso 2
                FSBody torso2 = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(15f / physScale, 10f / physScale);
                fixture             = new FSFixture(torso2, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                torso2.Position     = new FVector2(startX / physScale, (startY - 43f) / physScale);
                torso2.BodyType     = BodyType.Dynamic;

                // Torso 3
                FSBody torso3 = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(15f / physScale, 10f / physScale);
                fixture             = new FSFixture(torso3, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                torso3.Position     = new FVector2(startX / physScale, (startY - 58f) / physScale);
                torso3.BodyType     = BodyType.Dynamic;

                // UpperArm
                // L
                FSBody upperArmL = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(18f / physScale, 6.5f / physScale);
                fixture             = new FSFixture(upperArmL, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                upperArmL.Position  = new FVector2((startX - 30f) / physScale, (startY - 20f) / physScale);
                upperArmL.BodyType  = BodyType.Dynamic;
                // R
                FSBody upperArmR = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(18f / physScale, 6.5f / physScale);
                fixture             = new FSFixture(upperArmR, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                upperArmR.Position  = new FVector2((startX + 30f) / physScale, (startY - 20f) / physScale);
                upperArmR.BodyType  = BodyType.Dynamic;

                // LowerArm
                // L
                FSBody lowerArmL = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(17f / physScale, 6f / physScale);
                fixture             = new FSFixture(lowerArmL, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                lowerArmL.Position  = new FVector2((startX - 57f) / physScale, (startY - 20f) / physScale);
                lowerArmL.BodyType  = BodyType.Dynamic;
                // R
                FSBody lowerArmR = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(17f / physScale, 6f / physScale);
                fixture             = new FSFixture(lowerArmR, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                lowerArmR.Position  = new FVector2((startX + 57f) / physScale, (startY - 20f) / physScale);
                lowerArmR.BodyType  = BodyType.Dynamic;

                // UpperLeg
                // L
                FSBody upperLegL = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(7.5f / physScale, 22f / physScale);
                fixture             = new FSFixture(upperLegL, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                upperLegL.Position  = new FVector2((startX - 8f) / physScale, (startY - 85f) / physScale);
                upperLegL.BodyType  = BodyType.Dynamic;
                // R
                FSBody upperLegR = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(7.5f / physScale, 22f / physScale);
                fixture             = new FSFixture(upperLegR, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                upperLegR.Position  = new FVector2((startX + 8f) / physScale, (startY - 85f) / physScale);
                upperLegR.BodyType  = BodyType.Dynamic;

                // LowerLeg
                // L
                FSBody lowerLegL = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(7.5f / physScale, 22f / physScale);
                fixture             = new FSFixture(lowerLegL, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                lowerLegL.Position  = new FVector2((startX - 8f) / physScale, (startY - 120f) / physScale);
                lowerLegL.BodyType  = BodyType.Dynamic;
                // R
                FSBody lowerLegR = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox(7.5f / physScale, 22f / physScale);
                fixture             = new FSFixture(lowerLegR, box);
                fixture.Friction    = 0.4f;
                fixture.Restitution = 0.1f;
                lowerLegR.Position  = new FVector2((startX + 8f) / physScale, (startY - 120f) / physScale);
                lowerLegR.BodyType  = BodyType.Dynamic;

                // JOINTS

                // Head to shoulders
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, torso1, head, head.GetLocalPoint(new FVector2(startX / physScale, (startY - 15f) / physScale)));
                joint.LowerLimit       = -40f * Mathf.Deg2Rad;
                joint.UpperLimit       = 40f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;

                // Upper arm to shoulders
                // L
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, torso1, upperArmL, upperArmL.GetLocalPoint(new FVector2((startX - 18f) / physScale, (startY - 20f) / physScale)));
                joint.LowerLimit       = -85f * Mathf.Deg2Rad;
                joint.UpperLimit       = 130f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;
                // R
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, torso1, upperArmR, upperArmR.GetLocalPoint(new FVector2((startX + 18f) / physScale, (startY - 20f) / physScale)));
                joint.LowerLimit       = -130f * Mathf.Deg2Rad;
                joint.UpperLimit       = 85f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;

                // Lower arm to upper arm
                // L
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, upperArmL, lowerArmL, lowerArmL.GetLocalPoint(new FVector2((startX - 45f) / physScale, (startY - 20f) / physScale)));
                joint.LowerLimit       = -130f * Mathf.Deg2Rad;
                joint.UpperLimit       = 10f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;
                // R
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, upperArmR, lowerArmR, lowerArmR.GetLocalPoint(new FVector2((startX + 45f) / physScale, (startY - 20f) / physScale)));
                joint.LowerLimit       = -10f * Mathf.Deg2Rad;
                joint.UpperLimit       = 130f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;

                // Shoulders/stomach
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, torso1, torso2, torso2.GetLocalPoint(new FVector2((startX + 0f) / physScale, (startY - 35f) / physScale)));
                joint.LowerLimit       = -15f * Mathf.Deg2Rad;
                joint.UpperLimit       = 15f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;
                // Stomach/hips
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, torso2, torso3, torso3.GetLocalPoint(new FVector2((startX + 0f) / physScale, (startY - 50f) / physScale)));
                joint.LowerLimit       = -15f * Mathf.Deg2Rad;
                joint.UpperLimit       = 15f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;

                // Torso to upper leg
                // L
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, torso3, upperLegL, upperLegL.GetLocalPoint(new FVector2((startX - 8f) / physScale, (startY - 72f) / physScale)));
                joint.LowerLimit       = -25f * Mathf.Deg2Rad;
                joint.UpperLimit       = 45f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;
                // R
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, torso3, upperLegR, upperLegR.GetLocalPoint(new FVector2((startX + 8f) / physScale, (startY - 72f) / physScale)));
                joint.LowerLimit       = -45f * Mathf.Deg2Rad;
                joint.UpperLimit       = 25f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;

                // Upper leg to lower leg
                // L
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, upperLegL, lowerLegL, lowerLegL.GetLocalPoint(new FVector2((startX - 8f) / physScale, (startY - 105f) / physScale)));
                joint.LowerLimit       = -25f * Mathf.Deg2Rad;
                joint.UpperLimit       = 115f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;
                // R
                joint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, upperLegR, lowerLegR, lowerLegR.GetLocalPoint(new FVector2((startX + 8f) / physScale, (startY - 105f) / physScale)));
                joint.LowerLimit       = -115f * Mathf.Deg2Rad;
                joint.UpperLimit       = 25f * Mathf.Deg2Rad;
                joint.LimitEnabled     = true;
                joint.CollideConnected = false;
            }

            // Add stairs on the left, these are static bodies so set the type accordingly
            for (int j = 1; j <= 10; j++)
            {
                FSBody body = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox((10f * (float)j) / physScale, 10f / physScale);
                fixture       = new FSFixture(body, box);
                body.Position = new FVector2((10f * (float)j) / physScale, ((150f + 20f * (float)j) / physScale) * -1f);
            }
            // Add stairs on the right
            for (int k = 1; k <= 10; k++)
            {
                FSBody body = new FSBody(FSWorldComponent.PhysicsWorld);
                box = new PolygonShape(1f);
                box.SetAsBox((10f * (float)k) / physScale, 10f / physScale);
                fixture       = new FSFixture(body, box);
                body.Position = new FVector2((640f - 10f * (float)k) / physScale, ((150f + 20f * (float)k) / physScale) * -1f);
            }

            FSBody ground = new FSBody(FSWorldComponent.PhysicsWorld);

            box = new PolygonShape(1f);
            box.SetAsBox(30f / physScale, 40f / physScale);
            fixture         = new FSFixture(ground, box);
            ground.Position = new FVector2(320f / physScale, (320f / physScale) * -1f);
        }
예제 #12
0
 private Contact(FSFixture fA, int indexA, FSFixture fB, int indexB)
 {
     Reset(fA, indexA, fB, indexB);
 }
예제 #13
0
        //Cutting a shape into two is based on the work of Daid and his prototype BoxCutter: http://www.box2d.org/forum/viewtopic.php?f=3&t=1473

        /// <summary>
        /// Split a fixture into 2 vertice collections using the given entry and exit-point.
        /// </summary>
        /// <param name="fixture">The Fixture to split</param>
        /// <param name="entryPoint">The entry point - The start point</param>
        /// <param name="exitPoint">The exit point - The end point</param>
        /// <param name="splitSize">The size of the split. Think of this as the laser-width</param>
        /// <param name="first">The first collection of vertexes</param>
        /// <param name="second">The second collection of vertexes</param>
        public static void SplitShape(FSFixture fixture, FVector2 entryPoint, FVector2 exitPoint, float splitSize,
                                      out Vertices first, out Vertices second)
        {
            FVector2 localEntryPoint = fixture.Body.GetLocalPoint(ref entryPoint);
            FVector2 localExitPoint  = fixture.Body.GetLocalPoint(ref exitPoint);

            PolygonShape shape = fixture.Shape as PolygonShape;

            if (shape == null)
            {
                first  = new Vertices();
                second = new Vertices();
                return;
            }

            Vertices vertices = new Vertices(shape.Vertices);

            Vertices[] newPolygon = new Vertices[2];

            for (int i = 0; i < newPolygon.Length; i++)
            {
                newPolygon[i] = new Vertices(vertices.Count);
            }

            int[] cutAdded = { -1, -1 };
            int   last     = -1;

            for (int i = 0; i < vertices.Count; i++)
            {
                int n;
                //Find out if this vertex is on the old or new shape.
                if (FVector2.Dot(MathUtils.Cross(localExitPoint - localEntryPoint, 1), vertices[i] - localEntryPoint) > FSSettings.Epsilon)
                {
                    n = 0;
                }
                else
                {
                    n = 1;
                }

                if (last != n)
                {
                    //If we switch from one shape to the other add the cut vertices.
                    if (last == 0)
                    {
                        Debug.Assert(cutAdded[0] == -1);
                        cutAdded[0] = newPolygon[last].Count;
                        newPolygon[last].Add(localExitPoint);
                        newPolygon[last].Add(localEntryPoint);
                    }
                    if (last == 1)
                    {
                        Debug.Assert(cutAdded[last] == -1);
                        cutAdded[last] = newPolygon[last].Count;
                        newPolygon[last].Add(localEntryPoint);
                        newPolygon[last].Add(localExitPoint);
                    }
                }

                newPolygon[n].Add(vertices[i]);
                last = n;
            }

            //Add the cut in case it has not been added yet.
            if (cutAdded[0] == -1)
            {
                cutAdded[0] = newPolygon[0].Count;
                newPolygon[0].Add(localExitPoint);
                newPolygon[0].Add(localEntryPoint);
            }
            if (cutAdded[1] == -1)
            {
                cutAdded[1] = newPolygon[1].Count;
                newPolygon[1].Add(localEntryPoint);
                newPolygon[1].Add(localExitPoint);
            }

            for (int n = 0; n < 2; n++)
            {
                FVector2 offset;
                if (cutAdded[n] > 0)
                {
                    offset = (newPolygon[n][cutAdded[n] - 1] - newPolygon[n][cutAdded[n]]);
                }
                else
                {
                    offset = (newPolygon[n][newPolygon[n].Count - 1] - newPolygon[n][0]);
                }
                offset.Normalize();

                newPolygon[n][cutAdded[n]] += splitSize * offset;

                if (cutAdded[n] < newPolygon[n].Count - 2)
                {
                    offset = (newPolygon[n][cutAdded[n] + 2] - newPolygon[n][cutAdded[n] + 1]);
                }
                else
                {
                    offset = (newPolygon[n][0] - newPolygon[n][newPolygon[n].Count - 1]);
                }
                offset.Normalize();

                newPolygon[n][cutAdded[n] + 1] += splitSize * offset;
            }

            first  = newPolygon[0];
            second = newPolygon[1];
        }
예제 #14
0
        public void Reset(FSTimeStep step, int count, Contact[] contacts, Position[] positions, Velocity[] velocities)
        {
            _step       = step;
            _count      = count;
            _positions  = positions;
            _velocities = velocities;
            _contacts   = contacts;

            // grow the array
            if (_velocityConstraints == null || _velocityConstraints.Length < count)
            {
                _velocityConstraints = new ContactVelocityConstraint[count * 2];
                _positionConstraints = new ContactPositionConstraint[count * 2];

                for (int i = 0; i < _velocityConstraints.Length; i++)
                {
                    _velocityConstraints[i] = new ContactVelocityConstraint();
                }

                for (int i = 0; i < _positionConstraints.Length; i++)
                {
                    _positionConstraints[i] = new ContactPositionConstraint();
                }
            }

            // Initialize position independent portions of the constraints.
            for (int i = 0; i < _count; ++i)
            {
                Contact contact = contacts[i];

                FSFixture fixtureA = contact.FixtureA;
                FSFixture fixtureB = contact.FixtureB;
                Shape     shapeA   = fixtureA.Shape;
                Shape     shapeB   = fixtureB.Shape;
                float     radiusA  = shapeA.Radius;
                float     radiusB  = shapeB.Radius;
                FSBody    bodyA    = fixtureA.Body;
                FSBody    bodyB    = fixtureB.Body;
                Manifold  manifold = contact.Manifold;

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

                ContactVelocityConstraint vc = _velocityConstraints[i];
                vc.friction     = contact.Friction;
                vc.restitution  = contact.Restitution;
                vc.tangentSpeed = contact.TangentSpeed;
                vc.indexA       = bodyA.IslandIndex;
                vc.indexB       = bodyB.IslandIndex;
                vc.invMassA     = bodyA.InvMass;
                vc.invMassB     = bodyB.InvMass;
                vc.invIA        = bodyA.InvI;
                vc.invIB        = bodyB.InvI;
                vc.contactIndex = i;
                vc.pointCount   = pointCount;
                vc.K.SetZero();
                vc.normalMass.SetZero();

                ContactPositionConstraint pc = _positionConstraints[i];
                pc.indexA       = bodyA.IslandIndex;
                pc.indexB       = bodyB.IslandIndex;
                pc.invMassA     = bodyA.InvMass;
                pc.invMassB     = bodyB.InvMass;
                pc.localCenterA = bodyA.Sweep.LocalCenter;
                pc.localCenterB = bodyB.Sweep.LocalCenter;
                pc.invIA        = bodyA.InvI;
                pc.invIB        = bodyB.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)
                {
                    ManifoldPoint           cp  = manifold.Points[j];
                    VelocityConstraintPoint vcp = vc.points[j];

                    if (FSSettings.EnableWarmstarting)
                    {
                        vcp.normalImpulse  = _step.dtRatio * cp.NormalImpulse;
                        vcp.tangentImpulse = _step.dtRatio * cp.TangentImpulse;
                    }
                    else
                    {
                        vcp.normalImpulse  = 0.0f;
                        vcp.tangentImpulse = 0.0f;
                    }

                    vcp.rA           = FVector2.Zero;
                    vcp.rB           = FVector2.Zero;
                    vcp.normalMass   = 0.0f;
                    vcp.tangentMass  = 0.0f;
                    vcp.velocityBias = 0.0f;

                    pc.localPoints[j] = cp.LocalPoint;
                }
            }
        }
예제 #15
0
        public override void Start()
        {
            base.Start();

            FSBody body;

            tScale = physScale * 2f;

            // St position in world space
            m_offset     = new FVector2(180f / physScale, -200f / physScale);
            m_motorSpeed = 2f;
            m_motorOn    = true;

            FVector2 pivot = new FVector2(0f, 24f / tScale);

            for (int i = 0; i < 50; i++)
            {
                body          = BodyFactory.CreateCircle(FSWorldComponent.PhysicsWorld, 3.75f / physScale, 1f, new FVector2((Random.value * 620f + 10f) / physScale, -340f / physScale));
                body.BodyType = BodyType.Dynamic;
            }

            // chassis
            {
                m_chassis          = BodyFactory.CreateBody(FSWorldComponent.PhysicsWorld, FVector2.Add(pivot, m_offset));
                m_chassis.BodyType = BodyType.Dynamic;
                FSFixture m_chassis_f = FixtureFactory.AttachRectangle(150f / tScale, 60f / tScale, 1f, FVector2.Zero, m_chassis);
                //m_chassis_f.CollisionGroup = -1;
                m_chassis_f.CollisionCategories = Category.Cat10;
                m_chassis_f.CollidesWith        = Category.Cat1;
            }
            // wheel
            {
                m_wheel          = BodyFactory.CreateBody(FSWorldComponent.PhysicsWorld, FVector2.Add(pivot, m_offset));
                m_wheel.BodyType = BodyType.Dynamic;
                FSFixture m_wheel_f = FixtureFactory.AttachCircle(48f / tScale, 1f, m_wheel);
                //m_wheel_f.CollisionGroup = -1;
                m_wheel_f.CollisionCategories = Category.Cat10;
                m_wheel_f.CollidesWith        = Category.Cat1;
            }
            // glue chassis & wheel
            {
                m_motorJoint                  = JointFactory.CreateRevoluteJoint(FSWorldComponent.PhysicsWorld, m_wheel, m_chassis, FVector2.Zero);
                m_motorJoint.MotorSpeed       = m_motorSpeed;
                m_motorJoint.MaxMotorTorque   = 400f;
                m_motorJoint.CollideConnected = false;
                m_motorJoint.MotorEnabled     = m_motorOn;
            }

            FVector2 wheelAnchor;

            wheelAnchor = new FVector2(0f, -24f / tScale) + pivot;

            CreateLeg(-1f, wheelAnchor);
            CreateLeg(1f, wheelAnchor);

            m_wheel.Rotation = 120f * Mathf.Deg2Rad;
            CreateLeg(-1f, wheelAnchor);
            CreateLeg(1f, wheelAnchor);

            m_wheel.Rotation = -120f * Mathf.Deg2Rad;
            CreateLeg(-1f, wheelAnchor);
            CreateLeg(1f, wheelAnchor);
        }
예제 #16
0
파일: Contact.cs 프로젝트: horsman/survival
        private void Reset(FSFixture fA, int indexA, FSFixture fB, int indexB)
        {
            Flags = ContactFlags.Enabled;

            FixtureA = fA;
            FixtureB = fB;

            ChildIndexA = indexA;
            ChildIndexB = indexB;

            Manifold.PointCount = 0;

            NodeA.Contact = null;
            NodeA.Prev = null;
            NodeA.Next = null;
            NodeA.Other = null;

            NodeB.Contact = null;
            NodeB.Prev = null;
            NodeB.Next = null;
            NodeB.Other = null;

            TOICount = 0;

            //FPE: We only set the friction and restitution if we are not destroying the contact
            if (FixtureA != null && FixtureB != null)
            {
                Friction = FSSettings.MixFriction(FixtureA.Friction, FixtureB.Friction);
                Restitution = FSSettings.MixRestitution(FixtureA.Restitution, FixtureB.Restitution);
            }

            TangentSpeed = 0;
        }
예제 #17
0
파일: Contact.cs 프로젝트: horsman/survival
        internal static Contact Create(FSFixture fixtureA, int indexA, FSFixture fixtureB, int indexB)
        {
            ShapeType type1 = fixtureA.ShapeType;
            ShapeType type2 = fixtureB.ShapeType;

            Debug.Assert(ShapeType.Unknown < type1 && type1 < ShapeType.TypeCount);
            Debug.Assert(ShapeType.Unknown < type2 && type2 < ShapeType.TypeCount);

            Contact c;
            Queue<Contact> pool = fixtureA.Body.World.ContactPool;
            if (pool.Count > 0)
            {
                c = pool.Dequeue();
                if ((type1 >= type2 || (type1 == ShapeType.Edge && type2 == ShapeType.Polygon))
                    &&
                    !(type2 == ShapeType.Edge && type1 == ShapeType.Polygon))
                {
                    c.Reset(fixtureA, indexA, fixtureB, indexB);
                }
                else
                {
                    c.Reset(fixtureB, indexB, fixtureA, indexA);
                }
            }
            else
            {
                // Edge+Polygon is non-symetrical due to the way Erin handles collision type registration.
                if ((type1 >= type2 || (type1 == ShapeType.Edge && type2 == ShapeType.Polygon))
                    &&
                    !(type2 == ShapeType.Edge && type1 == ShapeType.Polygon))
                {
                    c = new Contact(fixtureA, indexA, fixtureB, indexB);
                }
                else
                {
                    c = new Contact(fixtureB, indexB, fixtureA, indexA);
                }
            }

            c._type = _registers[(int)type1, (int)type2];

            return c;
        }
예제 #18
0
파일: Contact.cs 프로젝트: horsman/survival
 private Contact(FSFixture fA, int indexA, FSFixture fB, int indexB)
 {
     Reset(fA, indexA, fB, indexB);
 }
예제 #19
0
        /// <summary>
        /// Call this to draw shapes and other debug draw data.
        /// </summary>
        private void DrawDebugData()
        {
            if ((Flags & DebugViewFlags.Shape) == DebugViewFlags.Shape)
            {
                foreach (FSBody b in World.BodyList)
                {
                    Transform xf;
                    b.GetTransform(out xf);
                    foreach (FSFixture f in b.FixtureList)
                    {
                        if (b.Enabled == false)
                        {
                            DrawShape(f, xf, InactiveShapeColor);
                        }
                        else if (b.BodyType == BodyType.Static)
                        {
                            DrawShape(f, xf, StaticShapeColor);
                        }
                        else if (b.BodyType == BodyType.Kinematic)
                        {
                            DrawShape(f, xf, KinematicShapeColor);
                        }
                        else if (b.Awake == false)
                        {
                            DrawShape(f, xf, SleepingShapeColor);
                        }
                        else
                        {
                            DrawShape(f, xf, DefaultShapeColor);
                        }
                    }
                }
            }
            if ((Flags & DebugViewFlags.ContactPoints) == DebugViewFlags.ContactPoints)
            {
                const float axisScale = 0.3f;

                for (int i = 0; i < _pointCount; ++i)
                {
                    ContactPoint point = _points[i];

                    if (point.State == PointState.Add)
                    {
                        // Add
                        DrawPoint(point.Position, 0.1f, new Color(0.3f, 0.95f, 0.3f));
                    }
                    else if (point.State == PointState.Persist)
                    {
                        // Persist
                        DrawPoint(point.Position, 0.1f, new Color(0.3f, 0.3f, 0.95f));
                    }

                    if ((Flags & DebugViewFlags.ContactNormals) == DebugViewFlags.ContactNormals)
                    {
                        FVector2 p1 = point.Position;
                        FVector2 p2 = p1 + axisScale * point.Normal;
                        DrawSegment(p1, p2, new Color(0.4f, 0.9f, 0.4f));
                    }
                }
                _pointCount = 0;
            }
            if ((Flags & DebugViewFlags.PolygonPoints) == DebugViewFlags.PolygonPoints)
            {
                foreach (FSBody body in World.BodyList)
                {
                    foreach (FSFixture f in body.FixtureList)
                    {
                        PolygonShape polygon = f.Shape as PolygonShape;
                        if (polygon != null)
                        {
                            Transform xf;
                            body.GetTransform(out xf);

                            for (int i = 0; i < polygon.Vertices.Count; i++)
                            {
                                FVector2 tmp = MathUtils.Mul(ref xf, polygon.Vertices[i]);
                                DrawPoint(tmp, 0.1f, Color.red);
                            }
                        }
                    }
                }
            }
            if ((Flags & DebugViewFlags.Joint) == DebugViewFlags.Joint)
            {
                foreach (FarseerJoint j in World.JointList)
                {
                    DrawJoint(j);
                }
            }
            if ((Flags & DebugViewFlags.Pair) == DebugViewFlags.Pair)
            {
                Color color = new Color(0.3f, 0.9f, 0.9f);
                for (int i = 0; i < World.ContactManager.ContactList.Count; i++)
                {
                    Contact   c        = World.ContactManager.ContactList[i];
                    FSFixture fixtureA = c.FixtureA;
                    FSFixture fixtureB = c.FixtureB;

                    AABB aabbA;
                    fixtureA.GetAABB(out aabbA, 0);
                    AABB aabbB;
                    fixtureB.GetAABB(out aabbB, 0);

                    FVector2 cA = aabbA.Center;
                    FVector2 cB = aabbB.Center;

                    DrawSegment(cA, cB, color);
                }
            }
            if ((Flags & DebugViewFlags.AABB) == DebugViewFlags.AABB)
            {
                Color       color = new Color(0.9f, 0.3f, 0.9f);
                IBroadPhase bp    = World.ContactManager.BroadPhase;

                foreach (FSBody b in World.BodyList)
                {
                    if (b.Enabled == false)
                    {
                        continue;
                    }

                    foreach (FSFixture f in b.FixtureList)
                    {
                        for (int t = 0; t < f.ProxyCount; ++t)
                        {
                            FixtureProxy proxy = f.Proxies[t];
                            AABB         aabb;
                            bp.GetFatAABB(proxy.ProxyId, out aabb);

                            DrawAABB(ref aabb, color);
                        }
                    }
                }
            }
            if ((Flags & DebugViewFlags.CenterOfMass) == DebugViewFlags.CenterOfMass)
            {
                foreach (FSBody b in World.BodyList)
                {
                    Transform xf;
                    b.GetTransform(out xf);
                    xf.p = b.WorldCenter;
                    DrawTransform(ref xf);
                }
            }
            if ((Flags & DebugViewFlags.Controllers) == DebugViewFlags.Controllers)
            {
                for (int i = 0; i < World.ControllerList.Count; i++)
                {
                    Controller controller = World.ControllerList[i];

                    BuoyancyController buoyancy = controller as BuoyancyController;
                    if (buoyancy != null)
                    {
                        AABB container = buoyancy.Container;
                        DrawAABB(ref container, new Color(0.3f, 0.5f, 1.0f));
                    }
                }
            }
        }
예제 #20
0
        /// <summary>
        /// This makes the explosive explode
        /// </summary>
        /// <param name="pos">
        /// The position where the explosion happens
        /// </param>
        /// <param name="radius">
        /// The explosion radius
        /// </param>
        /// <param name="maxForce">
        /// The explosion force at the explosion point
        /// (then is inversely proportional to the square of the distance)
        /// </param>
        /// <returns>
        /// A dictionnary containing all the "exploded" fixtures
        /// with a list of the applied impulses
        /// </returns>
        public Dictionary <FSFixture, List <FVector2> > Activate(FVector2 pos, float radius, float maxForce)
        {
            _exploded.Clear();

            AABB aabb;

            aabb.LowerBound = pos + new FVector2(-radius, -radius);
            aabb.UpperBound = pos + new FVector2(radius, radius);
            FSFixture[] shapes = new FSFixture[MaxShapes];

            // More than 5 shapes in an explosion could be possible, but still strange.
            FSFixture[] containedShapes = new FSFixture[5];
            bool        exit            = false;

            int shapeCount          = 0;
            int containedShapeCount = 0;

            // Query the world for overlapping shapes.
            World.QueryAABB(
                fixture =>
            {
                if (fixture.TestPoint(ref pos))
                {
                    if (IgnoreWhenInsideShape)
                    {
                        exit = true;
                    }
                    else
                    {
                        containedShapes[containedShapeCount++] = fixture;
                    }
                }
                else
                {
                    shapes[shapeCount++] = fixture;
                }

                // Continue the query.
                return(true);
            }, ref aabb);

            if (exit)
            {
                return(_exploded);
            }

            // Per shape max/min angles for now.
            float[] vals     = new float[shapeCount * 2];
            int     valIndex = 0;

            for (int i = 0; i < shapeCount; ++i)
            {
                PolygonShape ps;
                CircleShape  cs = shapes[i].Shape as CircleShape;
                if (cs != null)
                {
                    // We create a "diamond" approximation of the circle
                    Vertices v   = new Vertices();
                    FVector2 vec = FVector2.Zero + new FVector2(cs.Radius, 0);
                    v.Add(vec);
                    vec = FVector2.Zero + new FVector2(0, cs.Radius);
                    v.Add(vec);
                    vec = FVector2.Zero + new FVector2(-cs.Radius, cs.Radius);
                    v.Add(vec);
                    vec = FVector2.Zero + new FVector2(0, -cs.Radius);
                    v.Add(vec);
                    ps = new PolygonShape(v, 0);
                }
                else
                {
                    ps = shapes[i].Shape as PolygonShape;
                }

                if ((shapes[i].Body.BodyType == BodyType.Dynamic) && ps != null)
                {
                    FVector2 toCentroid      = shapes[i].Body.GetWorldPoint(ps.MassData.Centroid) - pos;
                    float    angleToCentroid = (float)Math.Atan2(toCentroid.Y, toCentroid.X);
                    float    min             = float.MaxValue;
                    float    max             = float.MinValue;
                    float    minAbsolute     = 0.0f;
                    float    maxAbsolute     = 0.0f;

                    for (int j = 0; j < (ps.Vertices.Count()); ++j)
                    {
                        FVector2 toVertex = (shapes[i].Body.GetWorldPoint(ps.Vertices[j]) - pos);
                        float    newAngle = (float)Math.Atan2(toVertex.Y, toVertex.X);
                        float    diff     = (newAngle - angleToCentroid);

                        diff = (diff - MathHelper.Pi) % (2 * MathHelper.Pi);
                        // the minus pi is important. It means cutoff for going other direction is at 180 deg where it needs to be

                        if (diff < 0.0f)
                        {
                            diff += 2 * MathHelper.Pi; // correction for not handling negs
                        }
                        diff -= MathHelper.Pi;

                        if (Math.Abs(diff) > MathHelper.Pi)
                        {
                            throw new ArgumentException("OMG!");
                        }
                        // Something's wrong, point not in shape but exists angle diff > 180

                        if (diff > max)
                        {
                            max         = diff;
                            maxAbsolute = newAngle;
                        }
                        if (diff < min)
                        {
                            min         = diff;
                            minAbsolute = newAngle;
                        }
                    }

                    vals[valIndex] = minAbsolute;
                    ++valIndex;
                    vals[valIndex] = maxAbsolute;
                    ++valIndex;
                }
            }

            Array.Sort(vals, 0, valIndex, _rdc);
            _data.Clear();
            bool rayMissed = true;

            for (int i = 0; i < valIndex; ++i)
            {
                FSFixture shape = null;
                float     midpt;

                int iplus = (i == valIndex - 1 ? 0 : i + 1);
                if (vals[i] == vals[iplus])
                {
                    continue;
                }

                if (i == valIndex - 1)
                {
                    // the single edgecase
                    midpt = (vals[0] + MathHelper.Pi * 2 + vals[i]);
                }
                else
                {
                    midpt = (vals[i + 1] + vals[i]);
                }

                midpt = midpt / 2;

                FVector2 p1 = pos;
                FVector2 p2 = radius * new FVector2((float)Math.Cos(midpt),
                                                    (float)Math.Sin(midpt)) + pos;

                // RaycastOne
                bool hitClosest = false;
                World.RayCast((f, p, n, fr) =>
                {
                    FSBody body = f.Body;

                    if (!IsActiveOn(body))
                    {
                        return(0);
                    }

                    if (body.UserData != null)
                    {
                        int index = (int)body.UserData;
                        if (index == 0)
                        {
                            // filter
                            return(-1.0f);
                        }
                    }

                    hitClosest = true;
                    shape      = f;
                    return(fr);
                }, p1, p2);

                //draws radius points
                if ((hitClosest) && (shape.Body.BodyType == BodyType.Dynamic))
                {
                    if ((_data.Count() > 0) && (_data.Last().Body == shape.Body) && (!rayMissed))
                    {
                        int       laPos = _data.Count - 1;
                        ShapeData la    = _data[laPos];
                        la.Max       = vals[iplus];
                        _data[laPos] = la;
                    }
                    else
                    {
                        // make new
                        ShapeData d;
                        d.Body = shape.Body;
                        d.Min  = vals[i];
                        d.Max  = vals[iplus];
                        _data.Add(d);
                    }

                    if ((_data.Count() > 1) &&
                        (i == valIndex - 1) &&
                        (_data.Last().Body == _data.First().Body) &&
                        (_data.Last().Max == _data.First().Min))
                    {
                        ShapeData fi = _data[0];
                        fi.Min = _data.Last().Min;
                        _data.RemoveAt(_data.Count() - 1);
                        _data[0] = fi;
                        while (_data.First().Min >= _data.First().Max)
                        {
                            fi.Min  -= MathHelper.Pi * 2;
                            _data[0] = fi;
                        }
                    }

                    int       lastPos = _data.Count - 1;
                    ShapeData last    = _data[lastPos];
                    while ((_data.Count() > 0) &&
                           (_data.Last().Min >= _data.Last().Max))    // just making sure min<max
                    {
                        last.Min       = _data.Last().Min - 2 * MathHelper.Pi;
                        _data[lastPos] = last;
                    }
                    rayMissed = false;
                }
                else
                {
                    rayMissed = true; // raycast did not find a shape
                }
            }

            for (int i = 0; i < _data.Count(); ++i)
            {
                if (!IsActiveOn(_data[i].Body))
                {
                    continue;
                }

                float arclen = _data[i].Max - _data[i].Min;

                float first        = MathHelper.Min(MaxEdgeOffset, EdgeRatio * arclen);
                int   insertedRays = (int)Math.Ceiling(((arclen - 2.0f * first) - (MinRays - 1) * MaxAngle) / MaxAngle);

                if (insertedRays < 0)
                {
                    insertedRays = 0;
                }

                float offset = (arclen - first * 2.0f) / ((float)MinRays + insertedRays - 1);

                //Note: This loop can go into infinite as it operates on floats.
                //Added FloatEquals with a large epsilon.
                for (float j = _data[i].Min + first;
                     j < _data[i].Max || MathUtils.FloatEquals(j, _data[i].Max, 0.0001f);
                     j += offset)
                {
                    FVector2 p1        = pos;
                    FVector2 p2        = pos + radius * new FVector2((float)Math.Cos(j), (float)Math.Sin(j));
                    FVector2 hitpoint  = FVector2.Zero;
                    float    minlambda = float.MaxValue;

                    List <FSFixture> fl = _data[i].Body.FixtureList;
                    for (int x = 0; x < fl.Count; x++)
                    {
                        FSFixture    f = fl[x];
                        RayCastInput ri;
                        ri.Point1      = p1;
                        ri.Point2      = p2;
                        ri.MaxFraction = 50f;

                        RayCastOutput ro;
                        if (f.RayCast(out ro, ref ri, 0))
                        {
                            if (minlambda > ro.Fraction)
                            {
                                minlambda = ro.Fraction;
                                hitpoint  = ro.Fraction * p2 + (1 - ro.Fraction) * p1;
                            }
                        }

                        // the force that is to be applied for this particular ray.
                        // offset is angular coverage. lambda*length of segment is distance.
                        float impulse = (arclen / (MinRays + insertedRays)) * maxForce * 180.0f / MathHelper.Pi *
                                        (1.0f - Math.Min(1.0f, minlambda));

                        // We Apply the impulse!!!
                        FVector2 vectImp = FVector2.Dot(impulse * new FVector2((float)Math.Cos(j),
                                                                               (float)Math.Sin(j)), -ro.Normal) *
                                           new FVector2((float)Math.Cos(j),
                                                        (float)Math.Sin(j));

                        _data[i].Body.ApplyLinearImpulse(ref vectImp, ref hitpoint);

                        // We gather the fixtures for returning them
                        FVector2        val = FVector2.Zero;
                        List <FVector2> vectorList;
                        if (_exploded.TryGetValue(f, out vectorList))
                        {
                            val.X += Math.Abs(vectImp.X);
                            val.Y += Math.Abs(vectImp.Y);

                            vectorList.Add(val);
                        }
                        else
                        {
                            vectorList = new List <FVector2>();
                            val.X      = Math.Abs(vectImp.X);
                            val.Y      = Math.Abs(vectImp.Y);

                            vectorList.Add(val);
                            _exploded.Add(f, vectorList);
                        }

                        if (minlambda > 1.0f)
                        {
                            hitpoint = p2;
                        }
                    }
                }
            }

            // We check contained shapes
            for (int i = 0; i < containedShapeCount; ++i)
            {
                FSFixture fix = containedShapes[i];

                if (!IsActiveOn(fix.Body))
                {
                    continue;
                }

                float    impulse = MinRays * maxForce * 180.0f / MathHelper.Pi;
                FVector2 hitPoint;

                CircleShape circShape = fix.Shape as CircleShape;
                if (circShape != null)
                {
                    hitPoint = fix.Body.GetWorldPoint(circShape.Position);
                }
                else
                {
                    PolygonShape shape = fix.Shape as PolygonShape;
                    hitPoint = fix.Body.GetWorldPoint(shape.MassData.Centroid);
                }

                FVector2 vectImp = impulse * (hitPoint - pos);

                List <FVector2> vectorList = new List <FVector2>();
                vectorList.Add(vectImp);

                fix.Body.ApplyLinearImpulse(ref vectImp, ref hitPoint);

                if (!_exploded.ContainsKey(fix))
                {
                    _exploded.Add(fix, vectorList);
                }
            }

            return(_exploded);
        }