如何防止相机向量中的浮点错误

Ric*_*ral 2 c++ opengl floating-point vector

在一个不同的问题上,回答(Ricky)我的用户也说了以下(我仍然觉得有点混乱):

当我说它们必须保持垂直时,我只是意味着如果你一遍又一遍地通过相同的变换独立地旋转矢量,浮点误差可能会进入并且它们可能偏离垂直.点(x,y),点(y,z)和点(x,z)应非常接近零.如果没有,你需要做一些交叉产品并重新连接它们.它就像重写z = cross(x,y),然后y = cross(z,x)一样简单.

在我的相机系统上有3个相关矢量,这些矢量是浮点数并且总是标准化.参考矢量指向相机正在观察的方向,UpVector和RightVector是不言自明的.

任何人都知道如何回答,当然应该回答,但瑞奇,如果你在那里,请帮帮我...

1)究竟是什么意思是点(x,y),点(y,z)和点(x,z)?这是这些载体之间的点积吗?我想......但是哪些(x,y,z)对应我的Reference,UpVector和RightVector?我有点困惑......

2)那么,这些点积应该非常接近于零,我究竟该如何检查?我已经看到这样的代码在类似的上下文中实现了同样的东西:

const float Math::EPSILON = 1e-6f;

Math::closeEnough(<floating_point_variable_to_check>, 0.0f);

static bool closeEnough(float f1, float f2) {
    // Determines whether the two floating-point values f1 and f2 are
    // close enough together that they can be considered equal.

    return fabsf((f1 - f2) / ((f2 == 0.0f) ? 1.0f : f2)) < EPSILON;
}
Run Code Online (Sandbox Code Playgroud)

我想这很好吗?

3)我应该在哪里执行所有这些检查并重新连接向量?我有3个旋转相机的功能,Pitch,Yaw和Roll(最后一个我没有那么多使用它),只有这些功能改变了那些单位矢量.每当我调用其中一个旋转功能时,我应该执行检查和修复吗?还是会过多?那时何时何地?

4)最后但并非最不重要的是,为了修复它们,我需要用十字产品覆盖矢量,这是有意义的,因为我希望它们彼此垂直.但上面的引用是不是缺少一个交叉产品?我执行这些修复的顺序是否重要?

小智 5

希望目前的两个答案是充分的,所以我只是在理论上加上一个理由,说明它产生的原因以及你处理它的原因并不重要的原因是形成3x3旋转矩阵的9个数字并描述你的相机如何面向不仅是必要的.

旋转矩阵只是具有三个向量(例如,向上,向右,向前)作为三列的矩阵.考虑具有三个向量的矩阵e1 =右,e2 =向上,e3 =向后.然后,将一个点转换为与矩阵相同的参考帧,将列向量预乘

[ e1_x  e2_x  e3_x ]
[ e1_y  e2_y  e3_y ]
[ e1_z  e2_z  e3_z ]
Run Code Online (Sandbox Code Playgroud)

(或者反过来...我总是把语言混淆,这取决于你如何看待它.另外,OpenGL使用4x4矩阵作为一个技巧来应用翻译甚至透视只有一个矩阵.)无论如何,你可以得到任何一个通过交叉两个其他三个向量.即e1 = e2 x e3,e2 = e3 x e1e3 = e1 x e2 那意味着一个向量是不必要的.少一个向量留下六个数字.剩下的两个向量的长度是无关紧要的 - 只有方向很重要 - 这留下了描述变换所需的四个数字.输入四元数.它们是一种数学工具,恰好以稳定,稳健的方式处理其余四个数字.如果你使用全部九个数字,你只需要确保向量总是长度为1,任何一个都垂直于另外两个.否则它不是一个真正的旋转矩阵.向上可能不是90度.这就是我建议的原因:

e1 = Normalize(e1);
e3 = Normalize(Cross(e1,e2));  // e3 is now perpendicular to e1 and e2, and
                               // probably hasn't changed much.  It will also 
                               // have length 1.
e2 = Normalize(Cross(e3,e1));  // e2 was perpendicular to e3 from the previous
                               // step, but now it's also perpendicular to e1.
Run Code Online (Sandbox Code Playgroud)

您可以按任何顺序或组合执行此操作,只要它完成相同的效果即可.每次迭代或每千次.如果完全忽略它,相机很可能会开始扭曲图像.经过几次相机旋转后,只会修改最后几个数字,因此将其视为一个软件因素,以防止事物长时间漂移.