Мне потребовалось несколько часов, но я, наконец, понял это. Идея состоит в том, что вы определяете, какая точка на ограничивающей коробке ближе всего к лучу, а затем вычисляет расстояние от этой точки до луча. Он также может вычислять барицентрическую координату на луче (t), но если он пересекает ограничивающий прямоугольник, он будет в некоторой произвольной точке внутри него.
float rayAABBdist (vec2 p, vec2 v, float tt, float ll, float bb, float rr)
{
float tx1 = (ll - p.x)/v.x;
float tx2 = (rr - p.x)/v.x;
float ty1 = (tt - p.y)/v.y;
float ty2 = (bb - p.y)/v.y;
float p1 = max (0.0, max (min (tx1, tx2), min (ty1, ty2)));
float p2 = max (0.0, min (max (tx1, tx2), max (ty1, ty2)));
float x = max (min ((p.x + v.x * p1 + p.x + v.x * p2)/2, rr), ll);
float y = max (min ((p.y + v.y * p1 + p.y + v.y * p2)/2, bb), tt);
float t = max (0.0, ((x - p.x) * v.x + (y - p.y) * v.y)/(v.x * v.x + v.y * v.y));
x = p.x + v.x * t - x;
y = p.y + v.y * t - y;
return x * x + y * y;
}
Вариант, который обрабатывает сегмент линии, за исключением того, что он также фиксирует коэффициенты до 1,0 в верхней части. Это не самое оптимальное решение, но оно работает. Это довольно дорого, хотя, поэтому в зависимости от вашего приложения вы можете просто использовать простой raycast. Я пробовал несколько разных подходов, но все они не работают в крайних случаях.
Два года выглядит довольно поздно, но если кто-то собирается искать в Интернете эту проблему, они найдут это решение.