/// <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) { Polygon poly = (Polygon) bodyA.Shape; Box box = (Box) bodyB.Shape; // TODO: this can be optimized using matrix multiplications and moving only one shape // specifically the box, because it has fewer vertices. Vector2f[] vertsA = poly.GetVertices(bodyA.GetPosition(), bodyA.Rotation); Vector2f[] vertsB = box.GetPoints(bodyB.GetPosition(), bodyB.Rotation); // TODO: use a sweepline that has the smallest projection of the box // now we use just an arbitrary one Vector2f sweepline = new Vector2f(vertsB[1]); sweepline.Sub(vertsB[2]); EdgeSweep sweep = new EdgeSweep(sweepline); sweep.AddVerticesToSweep(true, vertsA); sweep.AddVerticesToSweep(false, vertsB); int[][] collEdgeCands = sweep.OverlappingEdges; // FeaturePair[] featurePairs = getFeaturePairs(contacts.Length, vertsA, vertsB, collEdgeCands); // return PopulateContacts(contacts, vertsA, vertsB, featurePairs); Intersection[][] intersections = GetIntersectionPairs(vertsA, vertsB, collEdgeCands); return PopulateContacts(contacts, vertsA, vertsB, intersections); }
/// <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; }