예제 #1
0
        /// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public override int Collide(Contact[] contacts, Body bodyA, Body bodyB)
        {
            Line line = (Line) bodyA.Shape;
            Polygon poly = (Polygon) bodyB.Shape;

            // TODO: this can be optimized using matrix multiplications and moving only one shape
            // specifically the line, because it has only two vertices
            Vector2f[] vertsA = line.getVertices(bodyA.GetPosition(), bodyA.Rotation);
            Vector2f[] vertsB = poly.GetVertices(bodyB.GetPosition(), bodyB.Rotation);

            Vector2f pos = poly.GetCentroid(bodyB.GetPosition(), bodyB.Rotation);

            // using the z axis of a 3d Cross product we determine on what side B is
            bool isLeftOf = 0 > (pos.x - vertsA[0].x) * (vertsA[1].y - vertsA[0].y) - (vertsA[1].x - vertsA[0].x) * (pos.y - vertsA[0].y);

            // to get the proper intersection pairs we make sure
            // the line's normal is pointing towards the polygon
            // TODO: verify that it's not actually pointing in the opposite direction
            if (isLeftOf)
            {
                Vector2f tmp = vertsA[0];
                vertsA[0] = vertsA[1];
                vertsA[1] = tmp;
            }

            // we use the line's normal for our sweepline projection
            Vector2f normal = new Vector2f(vertsA[1]);
            normal.Sub(vertsA[0]);
            normal.Reconfigure(normal.y, - normal.x);
            EdgeSweep sweep = new EdgeSweep(normal);
            sweep.Insert(0, true, vertsA[0].Dot(normal));
            sweep.Insert(0, true, vertsA[1].Dot(normal));
            sweep.AddVerticesToSweep(false, vertsB);
            int[][] collEdgeCands = sweep.OverlappingEdges;

            IntersectionGatherer intGath = new IntersectionGatherer(vertsA, vertsB);
            for (int i = 0; i < collEdgeCands.Length; i++)
                intGath.Intersect(collEdgeCands[i][0], collEdgeCands[i][1]);

            Intersection[] intersections = intGath.Intersections;

            return PopulateContacts(contacts, vertsA, vertsB, intersections);
        }
        /// <summary> Get the edges from a list of vertices that can Collide with the given circle.
        /// This uses a sweepline algorithm which is only efficient if some assumptions
        /// are indeed true. See CPolygonCPolygonCollider for more information.
        /// 
        /// </summary>
        /// <param name="vertsA">The vertices of a polygon that is Collided with a circle
        /// </param>
        /// <param name="centroid">The center of the polygon
        /// </param>
        /// <param name="radius">The radius of the circle
        /// </param>
        /// <param name="circlePos">The position (center) of the circle
        /// </param>
        /// <returns> The list of edges that can Collide with the circle
        /// </returns>
        protected internal virtual int[][] GetCollisionCandidates(Vector2f[] vertsA, ROVector2f centroid, float radius, ROVector2f circlePos)
        {
            Vector2f sweepDir = new Vector2f(centroid);
            sweepDir.Sub(circlePos);
            sweepDir.Normalise(); //TODO: this normalization might not be necessary

            EdgeSweep sweep = new EdgeSweep(sweepDir); //vertsA[0], true, true, dist);

            sweep.AddVerticesToSweep(true, vertsA);

            float circProj = circlePos.Dot(sweepDir);

            sweep.Insert(0, false, - radius + circProj);
            sweep.Insert(0, false, radius + circProj);

            return sweep.OverlappingEdges;
        }