예제 #1
0
        private bool CheckPolygonGrid(IShape A, Vector2 APos, IShape B, Vector2 BPos, out Contact[] contacts)
        {
            PolygonShape polygonShapeA = A as PolygonShape;
            GridShape    gridB         = B as GridShape;

            Rectangle polygonBoundingBox = polygonShapeA.BoundingBox + APos,
                      gridBoundingBox    = gridB.BoundingBox + BPos;

            // test grid bounds
            if (!gridBoundingBox.Intersects(polygonBoundingBox))
            {
                contacts = null;
                return(false);
            }

            Polygon polygonA = new Polygon(polygonShapeA.Shape);

            polygonA.Translate(APos);

            List <Contact> gridContacts = TestGrid(gridB, BPos, polygonBoundingBox,
                                                   (Polygon tilePolygon) => {
                SAT.Test(polygonA, tilePolygon, out Contact? tileContact);
                return(tileContact);
            }
                                                   );

            if (gridContacts.Count > 0)
            {
                contacts = gridContacts.ToArray();
                return(true);
            }

            contacts = null;
            return(false);
        }
예제 #2
0
        private bool CheckBoxCircle(IShape A, Vector2 APos, IShape B, Vector2 BPos, out Contact[] contacts)
        {
            BoxShape    boxA    = A as BoxShape;
            CircleShape circleB = B as CircleShape;

            Vector2 closestPoint = boxA.ClosestPoint(APos, BPos);
            Vector2 diff         = closestPoint - BPos;

            if (Vector2.Dot(diff, diff) > circleB.Radius * circleB.Radius)
            {
                contacts = null;
                return(false);
            }

            if (SAT.Test(boxA, APos, circleB, BPos, boxA.Axes, out Contact? contact))
            {
                if (contact == null)
                {
                    contacts = new Contact[0];
                }
                else
                {
                    contacts = new Contact[] {
                        new Contact(closestPoint, contact.Value.Normal, contact.Value.PenetrationDepth, null)
                    };
                }

                return(true);
            }

            contacts = null;
            return(false);
        }
예제 #3
0
        private bool CheckBoxBox(IShape A, Vector2 APos, IShape B, Vector2 BPos, out Contact[] contacts)
        {
            BoxShape boxA = A as BoxShape,
                  shapeB  = B as BoxShape;

            // AABB x AABB
            if (System.Math.Abs(boxA.Rotation) < Math.Epsilon && System.Math.Abs(shapeB.Rotation) < Math.Epsilon)
            {
                Vector2 translation = BPos - APos;
                Vector2 overlap     = (boxA.HalwidthExtents + shapeB.HalwidthExtents) - Math.Abs(translation);

                if (overlap.X < 0f || overlap.Y < 0f)
                {
                    contacts = null;
                    return(false);
                }

                contacts = new Contact[1];

                if (overlap.X < overlap.Y)
                {
                    float sign = Math.Sign(translation.X);
                    contacts[0] = new Contact {
                        Position         = new Vector2(APos.X + boxA.HalwidthExtents.X * sign, BPos.Y),
                        Normal           = new Vector2(sign, 0f),
                        PenetrationDepth = Math.Abs(overlap.X)
                    };
                }
                else
                {
                    float sign = Math.Sign(translation.Y);
                    contacts[0] = new Contact {
                        Position         = new Vector2(BPos.X, APos.Y + boxA.HalwidthExtents.Y * sign),
                        Normal           = new Vector2(0f, sign),
                        PenetrationDepth = Math.Abs(overlap.Y)
                    };
                }

                return(true);
            }

            // OBB x OBB
            Polygon polygonA = new Polygon(boxA.Shape), polygonB = new Polygon(shapeB.Shape);

            polygonA.Translate(APos);
            polygonB.Translate(BPos);

            if (SAT.Test(polygonA, polygonB, out Contact? contact))
            {
                contacts = new Contact[] {
                    contact.Value
                };

                return(true);
            }

            contacts = null;
            return(false);
        }
예제 #4
0
        private bool CheckPolygonPolygon(IShape A, Vector2 APos, IShape B, Vector2 BPos, out Contact[] contacts)
        {
            PolygonShape shapeA = A as PolygonShape,
                  shapeB        = B as PolygonShape;

            Polygon polygonA = new Polygon(shapeA.Shape),
                    polygonB = new Polygon(shapeB.Shape);

            polygonA.Translate(APos);
            polygonB.Translate(BPos);

            if (SAT.Test(polygonA, polygonB, out Contact? contact))
            {
                contacts = new Contact[] {
                    contact.Value
                };

                return(true);
            }

            contacts = null;
            return(false);
        }
예제 #5
0
        private bool CheckCircleGrid(IShape A, Vector2 APos, IShape B, Vector2 BPos, out Contact[] contacts)
        {
            CircleShape circleA = A as CircleShape;
            GridShape   gridB   = B as GridShape;

            // test grid bounds
            Vector2 closestPoint = new Rectangle(BPos, gridB.Size).ClosestPoint(APos);
            Vector2 diff         = closestPoint - APos;

            if (Vector2.Dot(diff, diff) > circleA.Radius * circleA.Radius)
            {
                contacts = null;
                return(false);
            }

            List <Contact> gridContacts = TestGrid(gridB, BPos, new Rectangle(APos - circleA.Radius, APos + circleA.Radius),
                                                   (Polygon tilePolygon) => {
                SAT.Test(circleA, APos, tilePolygon, out Contact? tileContact);

                if (tileContact == null)
                {
                    return(null);
                }

                return(new Contact(closestPoint, tileContact.Value.Normal, tileContact.Value.PenetrationDepth, null));
            }
                                                   );

            if (gridContacts.Count > 0)
            {
                contacts = gridContacts.ToArray();
                return(true);
            }

            contacts = null;
            return(false);
        }
예제 #6
0
        private bool CheckCirclePolygon(IShape A, Vector2 APos, IShape B, Vector2 BPos, out Contact[] contacts)
        {
            CircleShape  circleA = A as CircleShape;
            PolygonShape polyB   = B as PolygonShape;

            Polygon polygonB = new Polygon(polyB.Shape);

            polygonB.Translate(BPos);

            Vector2 closestPoint = polygonB.ClosestPoint(APos);
            Vector2 d            = closestPoint - APos;

            if (Vector2.Dot(d, d) > circleA.Radius * circleA.Radius)
            {
                contacts = null;
                return(false);
            }

            if (SAT.Test(circleA, APos, polygonB, out Contact? contact))
            {
                if (contact == null)
                {
                    contacts = new Contact[0];
                }
                else
                {
                    contacts = new Contact[] {
                        new Contact(closestPoint, contact.Value.Normal, contact.Value.PenetrationDepth, null)
                    };
                }

                return(true);
            }

            contacts = null;
            return(false);
        }