这个XNA RotateVector2功能出了什么问题?

时间:2010-09-21 02:34:06

标签: c# vector xna rotation

我知道这可能是一个非常简单的问题,但我似乎无法弄明白。首先,我想指出我确实在半小时左右的时间内查看Google和SO,但没有找到我的问题的答案(是的,我很认真)。

基本上,我想围绕一个点旋转一个Vector2(在我的例子中,它总是(0,0)向量)。因此,我尝试使用参数作为旋转点和旋转角度(以度为单位)来创建函数。

这是一张快速绘图,展示了我正在努力实现的目标:

alt text

我想取V1(红色矢量),将其旋转角度A(蓝色),以获得新的矢量(V2,绿色)。在这个例子中,我使用了一个最简单的情况:轴上的V1和90度角,但我希望该函数能够处理更多的“复杂的”情况。

所以这是我的功能:

public static Vector2 RotateVector2(Vector2 point, float degrees)
{
    return Vector2.Transform(point, 
    Matrix.CreateRotationZ(MathHelper.ToRadians(degrees)));
}

那么,我做错了什么?当我运行代码并使用(0,-1)向量和90度角调用此函数时,我得到向量(1,4.3111139E-08)......

另外,如果我想接受一个点作为参数旋转呢?因此旋转并不总是发生在(0,0)...

周围

2 个答案:

答案 0 :(得分:6)

Chris Schmich关于浮点精度和使用弧度的答案是正确的。我建议使用RotateVector2的替代实现,并回答问题的第二部分。

构建4x4旋转矩阵以旋转矢量将导致大量不必要的操作。矩阵变换实际上是在执行以下操作,但使用了大量冗余数学:

    public static Vector2 RotateVector2(Vector2 point, float radians)
    {
        float cosRadians = (float)Math.Cos(radians);
        float sinRadians = (float)Math.Sin(radians);

        return new Vector2(
            point.X * cosRadians - point.Y * sinRadians,
            point.X * sinRadians + point.Y * cosRadians);
    }

如果要围绕任意点旋转,首先需要平移空间,以便旋转的点是原点,旋转然后反转平移。

    public static Vector2 RotateVector2(Vector2 point, float radians, Vector2 pivot)
    {
        float cosRadians = (float)Math.Cos(radians);
        float sinRadians = (float)Math.Sin(radians);

        Vector2 translatedPoint = new Vector2();
        translatedPoint.X = point.X - pivot.X;
        translatedPoint.Y = point.Y - pivot.Y;

        Vector2 rotatedPoint = new Vector2();
        rotatedPoint.X = translatedPoint.X * cosRadians - translatedPoint.Y * sinRadians + pivot.X;
        rotatedPoint.Y = translatedPoint.X * sinRadians + translatedPoint.Y * cosRadians + pivot.Y;

        return rotatedPoint;
    }

请注意,向量运算已内联以获得最大速度。

答案 1 :(得分:3)

  

那么,我做错了什么?当我运行代码并使用(0,-1)向量和90度角调用此函数时,我得到向量(1,4.3111139E-08)......

您的代码是正确的,这只是一个浮点表示问题。 4.371139E-08基本上为零(它是0.0000000431139),但转换没有产生恰好为零的值。这是您应该注意的浮点的常见问题。 This SO answer对浮点有一些额外的好处。

另外,如果可能的话,你应该坚持使用弧度而不是使用度数。这可能会在计算中引入更多错误。