I'm writing some code to check intersection between all of a rectangles segments and a ray. It will sometimes use the Left and Right side of the rectangle as the closest face hit (face DA & BC) even when it is clearly on the top of the rectangle (face AB).
This is what the Rectangle v Ray collision looks like.
// Ray intersections
static public IntersectData IntersectRectRay(Rectanglef rect, Vector2 origin, float dir)
{
IntersectData data = new IntersectData();
// Create segments for all the sides of a rectangle
Segment topLeftRight = new Segment(rect.TopLeft, rect.TopRight);
Segment leftTopBottom = new Segment(rect.TopLeft, rect.BottomLeft);
Segment bottomLeftRight = new Segment(rect.BottomLeft, rect.BottomRight);
Segment rightTopBottom = new Segment(rect.TopRight, rect.BottomRight);
// Check collision with all the faces and use the closet one
float smallestDepth = float.PositiveInfinity;
IntersectData topLeftRightData = IntersectSegmentRay(topLeftRight, origin, dir);
if (topLeftRightData.intersecting && topLeftRightData.depth.Length() < smallestDepth)
{
smallestDepth = topLeftRightData.depth.Length();
data = topLeftRightData;
data.face = "AB";
data.dir = MathHelper.PI / 2f;
}
IntersectData leftTopBottomData = IntersectSegmentRay(leftTopBottom, origin, dir);
if (leftTopBottomData.intersecting && leftTopBottomData.depth.Length() < smallestDepth)
{
smallestDepth = leftTopBottomData.depth.Length();
data = leftTopBottomData;
data.face = "DA";
data.dir = 0f;
}
IntersectData bottomLeftRightData = IntersectSegmentRay(bottomLeftRight, origin, dir);
if (bottomLeftRightData.intersecting && bottomLeftRightData.depth.Length() < smallestDepth)
{
smallestDepth = bottomLeftRightData.depth.Length();
data = bottomLeftRightData;
data.face = "CD";
data.dir = MathHelper.PI / 2f;
}
IntersectData rightTopBottomData = IntersectSegmentRay(rightTopBottom, origin, dir);
if (rightTopBottomData.intersecting && rightTopBottomData.depth.Length() < smallestDepth)
{
data = rightTopBottomData;
data.face = "BC";
data.dir = 0f;
}
return data;
}
and this is the ray v Segment intersection
static public IntersectData IntersectSegmentRay(Segment seg, Vector2 origin, float dir)
{
IntersectData data = new IntersectData();
// Get vector between p1 and p2
Vector2 q = seg.p1;
Vector2 s = seg.p2 - seg.p1;
Vector2 p = origin;
Vector2 r = new Vector2((float)Math.Cos(dir), (float)Math.Sin(dir)) * 100000f;
float t = MathHelper.Vec2CrossProduct(q - p, s) / MathHelper.Vec2CrossProduct(r, s);
float u = MathHelper.Vec2CrossProduct(q - p, r) / MathHelper.Vec2CrossProduct(r, s);
if (MathHelper.Vec2CrossProduct(r, s) != 0 && t <= 1 && t >= 0 && u <= 1 && u >= 0)
{
data.intersecting = true;
data.depth = p + t * r;//q + u * s;
data.dir = dir;
}
return data;
}
Extra Info: My Vec2CrossProduct is V × W to be Vx Wy − Vy Wx
I imagine there is something wrong with the ray segment intersection because if I tried to replace that 100000f with float.PositiveInfinity() it won't work.