分离轴定理在遇到锐角时失败

这是我在Lua语言中为LOVE2D引擎制作的一个小型库,它使用分离轴定理来解决碰撞问题。

当我让我的分离轴定理程序能够正常工作时,我感到非常高兴,开始用各种多边形进行测试。它在大多数情况下都能够正常工作,并为它们提供正确的最小平移向量。令人奇怪的是,如果两个形状都有锐角,那么这些锐角会导致程序失败,即使形状没有接触,甚至更不寻常的是,它会给出一个奇怪的最小平移向量。我已经检查了返回法向量的函数,因为我觉得这可能是第一个可能失败的地方,但它似乎工作正常。

这是处理我的碰撞的主要函数。

function findIntersection(shape1, shape2)
--获取要测试的轴。
--MTV意味着“最小平移向量”,即交集的最短向量
local axes1 = {}
local axes2 = {}
local overlap = false
local MTV = {direction = 0, magnitude = 99999}

for i, vert in pairs(shape1.hitbox) do
    nrm = getNormal(shape1.hitbox, i)
    table.insert(axes1, nrm)
end
for i, vert in pairs(shape2.hitbox)do
    nrm = getNormal(shape2.hitbox, i)
    table.insert(axes2, nrm)
end

--print(#axes1 .. '    ' .. #axes2)

--现在我们有了轴,必须沿着每个轴进行投影
for i, axis in pairs(axes1) do
    test1 = hitboxProj(shape1, vectorToCoord(axis.direction, axis.magnitude))
    test2 = hitboxProj(shape2, vectorToCoord(axis.direction, axis.magnitude))
    if test2.max > test1.min or test1.max > test2.min then
        if test2.max - test1.min < MTV.magnitude then
            MTV.direction = axes1[i].direction
            MTV.magnitude = test2.max - test1.min
        end
    else
        return false
    end
end

--现在我们有了轴,必须沿着每个轴进行投影
for i, axis in pairs(axes2) do
    test1 = hitboxProj(shape1, vectorToCoord(axis.direction, axis.magnitude))
    test2 = hitboxProj(shape2, vectorToCoord(axis.direction, axis.magnitude))
    if test2.max > test1.min or test1.max > test2.min then
        if test2.max - test1.min < MTV.magnitude then
            MTV.direction = axes2[i].direction
            MTV.magnitude = test2.max - test1.min
        end
    else
        return false
    end
end

return {MTV}
end

我的项目文件在这里https://github.com/ToffeeGoat/ToffeeCollision

点赞
用户13619683
用户13619683

这是一个很好的开始,你的代码相当清晰。有一些可以改进的地方,特别是我发现你所有的函数都是全局的。首先你应该将所有函数存储在一个“模块”中,以避免污染 _G 空间。你可以为其他所有东西使用局部变量。

注意,编写类似 x == 0 的内容是不健壮的,这种检查只适用于整数,当涉及到浮点数时可能会失败。我建议为库中每个函数编写一个简单的测试脚本。

此外,不高效的写法是 return {x = xCoord, y = yCoord},当你可以使用 Lua 的多个返回值 return xCoord, yCoord 时。创建大量中间表会给垃圾回收器带来压力。

有些代码需要重新修改,比如“getDirection”函数。我的意思是,这种事情已经有人发明了一些已知的技术。请查看我的教程以获得示例:https://2dengine.com/?p=vectors#Angle_between_two_vectors

其中有一些愚蠢的操作,比如 function sq(x) return x*x end。你知道在 Lua 中可以写成 x^2 吗?

addDeg 可以使用取模运算符替换:newAng = (angle + addition)%360。还要注意的是,使用度数没有任何好处-建议仅使用弧度。你已经使用了以弧度为单位的 math.pi。无论如何,你必须选择弧度或度数,并坚持使用其中一个。不要在代码中同时使用两个单位。

我不想挑剔得太多,因为你的代码并不差,只是需要适应一些最佳实践。下面是我另一个教程:

https://2dengine.com/?p=intersections

2020-09-01 07:22:08