我有一台相机需要围绕一个物体进行局部旋转。该对象具有任意旋转,由法线向量描述。想象一个球形行星,用照相机俯视该行星上的某个三角形。
我目前的实现是使用经典的向量交叉方法从三角形的法线生成一个旋转矩阵,然后使用该矩阵作为标准轨道相机的基础。这在地球赤道附近工作得很好,但是一旦它靠近两极,它就会开始爆炸,随着相机越接近极点的中心,它的行为就会越来越不规律。
我已经确定这是由于第一个矢量交叉,因为在这种情况下两个矢量彼此接近 - 我不确定这种现象的技术名称是什么。如果第一个向量是 0,1,0,当法线接近 0,1,0 或 0,-1,0 时会发生疯狂。
我发现了很多关于这个问题的描述,但没有有效的解决方案。我最接近的是这里:http: //xboxforums.create.msdn.com/forums/p/13278/13278.aspx它提到要处理“奇点”,在检测到它时使用不同的向量。我可以很容易地确定相机何时在行星面上会导致这种情况发生(因为我的行星球体是从投影到球坐标的 6 个四叉树生成的),但是当我切换到新矢量时会出现非常明显的快照。
这是当前代码:
Vector3 triNormal; //the current normal of the target vertex
Vector3 origin = Vector3.Forward;
Matrix orientation.Forward = origin;
orientation.Up = triNormal;
orientation.Right = Vector3.Cross(orientation.Up, orientation.Forward);
orientation.Right.Normalize();
orientation.Forward = Vector3.Cross(orientation.Right, orientation.Up);
orientation.Forward.Normalize();
我已经尝试检测 triNormal 何时位于其中一个极面上,并将“原点”设置为其他值,例如 Right。相机一旦在脸上就会正常运行,但会在它越过时立即捕捉到新的旋转。这是有道理的,因为它的参考向量刚刚改变,但需要消除以获得流畅的用户体验。我试图弄清楚如何抵消轨道相机的相机偏航以抵消新的坐标系,但它似乎不是一个恒定值,具体取决于相机当前瞄准的球体上的位置。我不确定如何计算差异。
另请注意,由于它在 XNA 和 C# 中,我使用的是右手坐标系。