/// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)"> /// </seealso> public virtual int Collide(Contact[] contacts, Body bodyA, Body bodyB) { int numContacts = 0; Line line = (Line) bodyA.Shape; Box box = (Box) bodyB.Shape; Vector2f lineVec = new Vector2f(line.DX, line.DY); lineVec.Normalise(); Vector2f axis = new Vector2f(- line.DY, line.DX); axis.Normalise(); Vector2f res = new Vector2f(); line.Start.ProjectOntoUnit(axis, res); float linePos = GetProp(res, axis); Vector2f c = MathUtil.Sub(bodyB.GetPosition(), bodyA.GetPosition()); c.ProjectOntoUnit(axis, res); float centre = GetProp(res, axis); Vector2f[] pts = box.GetPoints(bodyB.GetPosition(), bodyB.Rotation); float[] tangent = new float[4]; float[] proj = new float[4]; int outOfRange = 0; for (int i = 0; i < 4; i++) { pts[i].Sub(bodyA.GetPosition()); pts[i].ProjectOntoUnit(axis, res); tangent[i] = GetProp(res, axis); pts[i].ProjectOntoUnit(lineVec, res); proj[i] = GetProp(res, new Vector2f(line.DX, line.DY)); if ((proj[i] >= 1) || (proj[i] <= 0)) { outOfRange++; } } if (outOfRange == 4) { return 0; } Vector2f normal = new Vector2f(axis); if (centre < linePos) { if (!line.BlocksInnerEdge) { return 0; } normal.Scale(- 1); for (int i = 0; i < 4; i++) { if (tangent[i] > linePos) { if (proj[i] < 0) { Vector2f onAxis = new Vector2f(); Line leftLine = new Line(GetPt(pts, i - 1), pts[i]); Line rightLine = new Line(GetPt(pts, i + 1), pts[i]); leftLine.getClosestPoint(line.Start, res); res.ProjectOntoUnit(axis, onAxis); float left = GetProp(onAxis, axis); rightLine.getClosestPoint(line.Start, res); res.ProjectOntoUnit(axis, onAxis); float right = GetProp(onAxis, axis); if ((left > 0) && (right > 0)) { Vector2f pos = new Vector2f(bodyA.GetPosition()); pos.Add(line.Start); ResolveEndPointCollision(pos, bodyA, bodyB, normal, leftLine, rightLine, contacts[numContacts], i); numContacts++; } } else if (proj[i] > 1) { Vector2f onAxis = new Vector2f(); Line leftLine = new Line(GetPt(pts, i - 1), pts[i]); Line rightLine = new Line(GetPt(pts, i + 1), pts[i]); leftLine.getClosestPoint(line.End, res); res.ProjectOntoUnit(axis, onAxis); float left = GetProp(onAxis, axis); rightLine.getClosestPoint(line.End, res); res.ProjectOntoUnit(axis, onAxis); float right = GetProp(onAxis, axis); if ((left > 0) && (right > 0)) { Vector2f pos = new Vector2f(bodyA.GetPosition()); pos.Add(line.End); ResolveEndPointCollision(pos, bodyA, bodyB, normal, leftLine, rightLine, contacts[numContacts], i); numContacts++; } } else { pts[i].ProjectOntoUnit(lineVec, res); res.Add(bodyA.GetPosition()); contacts[numContacts].Separation = - (tangent[i] - linePos); contacts[numContacts].Position = new Vector2f(res); contacts[numContacts].Normal = normal; contacts[numContacts].Feature = new FeaturePair(i); numContacts++; } } } } else { if (!line.BlocksOuterEdge) { return 0; } for (int i = 0; i < 4; i++) { if (tangent[i] < linePos) { if (proj[i] < 0) { Vector2f onAxis = new Vector2f(); Line leftLine = new Line(GetPt(pts, i - 1), pts[i]); Line rightLine = new Line(GetPt(pts, i + 1), pts[i]); leftLine.getClosestPoint(line.Start, res); res.ProjectOntoUnit(axis, onAxis); float left = GetProp(onAxis, axis); rightLine.getClosestPoint(line.Start, res); res.ProjectOntoUnit(axis, onAxis); float right = GetProp(onAxis, axis); if ((left < 0) && (right < 0)) { Vector2f pos = new Vector2f(bodyA.GetPosition()); pos.Add(line.Start); ResolveEndPointCollision(pos, bodyA, bodyB, normal, leftLine, rightLine, contacts[numContacts], i); numContacts++; } } else if (proj[i] > 1) { Vector2f onAxis = new Vector2f(); Line leftLine = new Line(GetPt(pts, i - 1), pts[i]); Line rightLine = new Line(GetPt(pts, i + 1), pts[i]); leftLine.getClosestPoint(line.End, res); res.ProjectOntoUnit(axis, onAxis); float left = GetProp(onAxis, axis); rightLine.getClosestPoint(line.End, res); res.ProjectOntoUnit(axis, onAxis); float right = GetProp(onAxis, axis); if ((left < 0) && (right < 0)) { Vector2f pos = new Vector2f(bodyA.GetPosition()); pos.Add(line.End); ResolveEndPointCollision(pos, bodyA, bodyB, normal, leftLine, rightLine, contacts[numContacts], i); numContacts++; } } else { pts[i].ProjectOntoUnit(lineVec, res); res.Add(bodyA.GetPosition()); contacts[numContacts].Separation = - (linePos - tangent[i]); contacts[numContacts].Position = new Vector2f(res); contacts[numContacts].Normal = normal; contacts[numContacts].Feature = new FeaturePair(); numContacts++; } } } } if (numContacts > 2) { throw new System.SystemException("LineBoxCollision: > 2 contacts"); } return numContacts; }