【问题标题】:Monogame / Xna basic 3D Vector rotation mathMonogame / Xna 基本 3D 矢量旋转数学
【发布时间】:2022-08-21 12:45:58
【问题描述】:

我正在为 Monogame 中的一些基本矢量旋转而苦苦挣扎。

我有一个 3D 前向单位向量(0, 0, -1)只是想旋转它们180度周围Y轴(上).这是代码:

[Fact]
public void Vector_Rotation()
{
    Vector3 forward = Vector3.Forward;

    float angle = (float)Math.PI;

    Vector3 dirQuat = Vector3.Transform(forward, Quaternion.CreateFromAxisAngle(Vector3.Up, angle));
    Vector3 dirMatrix = Vector3.Transform(forward, Matrix.CreateRotationY(angle));
}

预期结果

dirQuat = (0, 0, 1);
dirMatrix = (0, 0, 1);

实际结果

dirQuat = (8.742278E-08, 0, 1)
dirMatrix = (8.742278E-08, 0, 1)

我希望有一个与正向相反的单位向量 (0, 0, 1)。我是 Monogame 框架的新手,我在这里错过了一些基本的东西吗? 提前感谢您的任何建议

  • 8.742278E-08 是 0.000000087,基本上是 0。我认为这只是浮点数学,导致它几乎是 0,但不完全是。

标签: vector rotation xna game-development monogame


【解决方案1】:

正如 britter 正确指出的那样,差异是由浮点运算的误差累积引起的。这在本网站的其他地方有很好的描述,但我会在这里给出简短的回答。

主要外卖点:

  1. 计算机以有限的位数工作。在以 10 为底的情况下,1/3 (.33333333333333333...) 不能用有限的位数精确表示。

  2. 将两个 32 位 Int 数字相乘会产生 64 位结果。然后在存储时将其切碎以仅包括 32 个最高有效位。当应用于Floats 时,这个整数示例总是更糟(因为并非 FP32 中的每个位都是数据)并且随着值的指数差异而变化(即,当两个数字都在 0 和 1 之间时,错误被最小化)。

  3. 两个Floats 之间的最小绝对可识别差异由Float.Epsilon 给出。换句话说,减去任何两个不相同的Float 值,可以得到一个高达Float.Epsilon=1.401298E-45 的值


    那么为什么你的预期结果是0返回8.742278E-08错误来自中间矩阵乘法和累加步骤中的错误求和,首先是截断PI:float angle = (float)Math.PI;#2的影响渗透到了每个方面最终设计。

    关于你的结果唯一有点令人惊讶的是Quaternion 变换不会由于额外的矩阵维度而在最终产品中引入更多的错误,直到我意识到这两个函数调用产生相同的精确变换矩阵(额外的维度矩阵都是零),大部分差异来自这两个调用。

    其余的错误体现在最后一个矩阵乘法Vector3.Transform(forward,

    考虑到每一步发生的乘法次数,结果并不令人惊讶。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    相关资源
    最近更新 更多