After some research, I've decided to use the Liang-Barsky line clipping algorithm in my 2D game. Google did not deliver on any VB.NET implementations of this algorithm but plenty C/++ ones. Therefore, as I have knowledge in C++, decided to port one found on Skytopia over to VB.Net. Unfortunately, it does not work with:
Public Class PhysicsObject
Public Function CollideRay(ByVal p0 As Point, ByVal p1 As Point, ByRef clip0 As Point, ByRef clip1 As Point) As Boolean
Dim t0 As Double = 0.0
Dim t1 As Double = 1.0
Dim xdelta As Double = p1.X - p0.X
Dim ydelta As Double = p1.Y - p0.Y
Dim p, q, r As Double
For edge = 0 To 3
' Traverse through left, right, bottom, top edges
If (edge = 0) Then
p = -xdelta
q = -(AABB.Left - p0.X)
ElseIf (edge = 1) Then
p = xdelta
q = (AABB.Right - p0.X)
ElseIf (edge = 2) Then
p = -ydelta
q = -(AABB.Bottom - p0.Y)
ElseIf (edge = 3) Then
p = ydelta
q = (AABB.Top - p0.Y)
End If
r = q / p
If p = 0 And q < 0 Then Return False ' Don't draw line at all. (parallel line outside)
If p < 0 Then
If r > t1 Then
Return False ' Don't draw line at all.
ElseIf r > t0 Then
t0 = r ' Line is clipped!
End If
ElseIf p > 0 Then
If r < t0 Then
Return False ' Don't draw line at all.
ElseIf r < t1 Then
t1 = r ' Line is clipped!
End If
End If
Next
clip0.X = p0.X + t0 * xdelta
clip0.Y = p0.Y + t0 * ydelta
clip1.X = p0.X + t1 * xdelta
clip1.Y = p0.Y + t1 * ydelta
Return True ' (clipped) line is drawn
End Function
Public AABB As Rectangle
End Class
I'm using the class/method like:
Dim testPhysics As PhysicsObject = New PhysicsObject
testPhysics.AABB = New Rectangle(30, 30, 20, 20)
Dim p0, p1 As Point
p0 = New Point(0, 0)
p1 = New Point(120, 120)
Dim clip0, clip1 As Point
clip0 = New Point(-1, -1)
clip1 = New Point(-1, -1)
GlobalRenderer.Graphics.DrawLine(Pens.LimeGreen, p0, p1)
If testPhysics.CollideRay(p0, p1, clip0, clip1) Then
GlobalRenderer.Graphics.DrawLine(Pens.Magenta, clip0, clip1)
End If
However, the CollideRay method fails on its 3rd edge iteration (edge = 3), r < t0, therefore the function returns false.
I'm wondering if anyone can spot some issue with my CollideRay function which would result in this behaviour, because I'm well and truly stumped.
Thanks in advance.
The code assumes a different coordinate system, note that topEdge is larger than bottomEdge in the linked web page. Your test works with normal graphics coordinates where Bottom is larger than Top. You have to swap the bottom and top arguments.