VB.NET 梁-巴尔斯基实现的问题

发布于 2024-10-01 02:54:33 字数 2699 浏览 1 评论 0原文

经过一番研究,我决定在我的 2D 游戏中使用Liang-Barsky线裁剪算法。 Google 没有提供该算法的任何 VB.NET 实现,但提供了大量 C/++ 实现。因此,由于我有 C++ 知识,决定移植在 Skytopia 上找到的一个 转到 VB.Net。不幸的是,它不适用于:

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

我正在使用如下类/方法:

    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

但是,CollideRay方法在其第三次边缘迭代(边缘= 3)上失败,r t0,因此该函数返回 false。

我想知道是否有人能发现我的 CollideRay 函数的一些问题,这会导致这种行为,因为我真的很难过。

提前致谢。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雪化雨蝶 2024-10-08 02:54:33

该代码假定不同的坐标系,请注意,链接网页中的 topEdge大于。您的测试适用于正常图形坐标,其中底部大于顶部。您必须交换底部和顶部参数。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文