Last active
October 12, 2019 18:28
-
-
Save JoaoBaptMG/8366fcbfc642b003f3baa2e89ba66cb1 to your computer and use it in GitHub Desktop.
Swept rectangle collision with time of impact
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Copyright (c) 2019 João Baptista de Paula e Silva. | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in all | |
// copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
// SOFTWARE. | |
// | |
using System; | |
using Microsoft.Xna.Framework; | |
namespace SweptSAT | |
{ | |
public static class SweptRectangleTest | |
{ | |
/// <summary> | |
/// Returns the Time of Impact of the collision of two rectangles going at different velocities | |
/// </summary> | |
/// <param name="rect1">The first rectangle</param> | |
/// <param name="v1">The velocity of the first rectangle</param> | |
/// <param name="rect2">The second rectangle</param> | |
/// <param name="v2">The velocity of the second rectangle</param> | |
/// <returns>The time of impact of the collision, or NaN if no collision is detected.</returns> | |
public static float TimeOfImpact(Rectangle rect1, Vector2 v1, Rectangle rect2, Vector2 v2) | |
{ | |
// Top left and bottom right coordinates for the first rectangle | |
var tl1 = new Vector2(rect1.X, rect1.Y); | |
var br1 = tl1 + new Vector2(rect1.Width, rect1.Height); | |
// Top left and bottom right coordinates for the second rectangle | |
var tl2 = new Vector2(rect2.X, rect2.Y); | |
var br2 = tl2 + new Vector2(rect2.Width, rect2.Height); | |
// Relative velocities | |
var vr = v2 - v1; | |
// Return the maximum of both calculated times | |
var toiX = TimeOfImpactSingleAxis(tl1.X, br1.X, tl2.X, br2.X, vr.X); | |
var toiY = TimeOfImpactSingleAxis(tl1.Y, br1.Y, tl2.Y, br2.Y, vr.Y); | |
return TimeInterval.Intersection(toiX, toiY).Begin; | |
} | |
/// <summary> | |
/// Returns the Time of Impact of the collision of two intervals. | |
/// The first interval is resting and the second is moving with a velocity v2. | |
/// </summary> | |
/// <param name="a1">First endpoint of first interval</param> | |
/// <param name="b1">Second endpoint of first interval</param> | |
/// <param name="a2">First endpoint of second interval</param> | |
/// <param name="b2">Second endpoint of second interval</param> | |
/// <param name="v2">Velocity of the second interval</param> | |
/// <returns></returns> | |
internal static TimeInterval TimeOfImpactSingleAxis(float a1, float b1, float a2, float b2, float v2) | |
{ | |
// Get the two points in time where the intervals enter and leave intersection | |
var k1 = (b1 - a2) / v2; | |
var k2 = (a1 - b2) / v2; | |
// Sort them to get an interval | |
return new TimeInterval(Math.Min(k1, k2), Math.Max(k1, k2)); | |
} | |
/// <summary> | |
/// Represents a single time interval | |
/// </summary> | |
internal struct TimeInterval | |
{ | |
public float Begin, End; | |
public TimeInterval(float begin, float end) | |
{ | |
Begin = begin; | |
End = end; | |
} | |
public static TimeInterval Intersection(TimeInterval t1, TimeInterval t2) | |
{ | |
var begin = Math.Max(t1.Begin, t2.Begin); | |
var end = Math.Min(t1.End, t2.End); | |
if (begin > end) begin = end = float.NaN; | |
return new TimeInterval(begin, end); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment