规范化没有平方根的空间矢量

时间:2014-01-09 02:27:08

标签: java math collision geometry

所以我已经了解到在编程中使用平方根总是不好的做法,尤其是在每个更新步骤中。我试图在圆圈之间进行逼真的弹性碰撞,我一直在读这个:http://www.vobarian.com/collisions/2dcollisions2.pdf有没有办法在不使用平方根的情况下对矢量进行标准化?或者任何快速的方式来做我正在做的事情?

1 个答案:

答案 0 :(得分:9)

乘以幅度平方的Fast Inverse Square Root进行归一化。

归一化矢量意味着将每个分量除以该矢量的大小。幅度等于sqrt(x**2 + y**2),其中xy是矢量的组成部分。但是平方根很慢,我们宁愿避免它。因此,我们选择乘以sqrt(x**2 + y**2)的幅度的倒数平方根,而不是除以1 / sqrt(x**2 + y**2)

为什么这有帮助?因为制作Quake III的优秀人员想出了一种非常快速的方法来计算1 / sqrt(x**2 + y**2),我们将其称为快速反向平方根

换句话说,fisqrt(x)等于1 / sqrt(x),但计算fisqrt(x)要比计算1 / sqrt(x)快得多。

这里有一些伪蟒蛇来说明这一切。

def fisqrt(x):
    # See article for implementation details.

def normalize(vector):
    magnitude_squared = vector.x**2 + vector.y**2
    invsqrt = fisqrt(magnitude_squared)
    vector.v *= invsqrt
    vector.y *= invsqrt
    return vector

另外,你可以'剔除'更昂贵的碰撞检查(下面的伪python):

def magnitudeSquared(vector):
    return vector.x ** 2 + vector.y ** 2

def cull(circleA, circleB):
    # Save a square root by calling magnitudeSquared.
    # Assuming that circle.center is a vector with x and y components.

    minCollisionDistance = circleA.radius + circleB.radius
    if magnitudeSquared(circleA.center - circleB.center) <= minCollisionDistance ** 2:
        # Circles overlap, can't cull.
        return false

    # Circles do not overlap, can cull!
    return true

在进行其他碰撞检查之前调用cull。当cull返回true时,您不需要进行任何进一步检查,因为两个圆圈不可能相互接触。这很好,因为cull几乎肯定比你可能使用的其他碰撞检测方法更快。如果cull返回false,则圆圈区域会在某处重叠,因此您可以调用更昂贵的物理建模算法。