【问题标题】:What's wrong with this XNA RotateVector2 function?这个 XNA RotateVector2 函数有什么问题?
【发布时间】:2010-09-21 02:34:06
【问题描述】:

我知道这可能是一个非常简单的问题,但我似乎无法弄清楚。首先,我想说明我确实浏览了 Google 和 SO 半小时左右,但没有找到问题的答案(是的,我是认真的)。

基本上,我想围绕一个点旋转 Vector2(在我的情况下,它始终是 (0, 0) 向量)。因此,我尝试创建一个函数来执行此操作,参数为要旋转的点和要旋转的角度(以度为单位)。

这是一个快速绘图,显示了我想要实现的目标:

我想取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.371139E-08) ...

另外,如果我也想接受一个旋转点作为参数怎么办?这样旋转并不总是发生在 (0, 0) 附近...

【问题讨论】:

    标签: c# vector xna rotation


    【解决方案1】:

    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;
        }
    

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

    【讨论】:

    • 非常感谢您发布该功能!
    • 这似乎是逆时针旋转,这绝对不是标准的。 RotateVector(new Vector2(0,1), Pi/2) 应该返回 (1,0)。
    【解决方案2】:

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

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

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

    【讨论】:

    • 感谢您的回答!但是我应该怎么做呢,因为 Matrix.CreateRotationZ 函数需要一个浮点数?
    • 浮点数仍然是必需的,并且会出现错误(您只需要忍受),但不要在整个代码中使用度数,而是使用弧度。
    猜你喜欢
    • 1970-01-01
    • 2017-03-26
    • 2014-06-29
    • 2011-02-13
    • 2011-04-24
    • 2011-08-26
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    相关资源
    最近更新 更多