2

我在几年前使用 OpenTK 和 C# 编写的现有项目中实现了 Arcball 旋转,并陷入了最后的障碍。

这是“旧式”非着色器 OpenGL。我确信 Arcball 旋转工作正常,问题只是应用生成的矩阵。它应该是相当简单的,但它不是那样工作的。

我将 Arcball 旋转作为四元数(qCurrent),然后将其转换为矩阵。然后我尝试了几种方法:

  1. 只需将其作为附加旋转应用于现有场景:

    GL.PushMatrix();
    Matrix4 arcball_rot = Matrix4.CreateFromQuaternion(qCurrent);
    GL.MultMatrix(ref arcball_rot);
    ... render objects in scene
    GL.PopMatrix();
    

这将围绕正确的原点(相机目标)应用正确的旋转,但相对于世界坐标系,而不是观察者。这是有道理的,因为我有效地以错误的顺序应用了旋转。

  1. 依次应用旋转,轨迹球首先旋转,这意味着从头开始。这里, rtn_complete 是一个矩阵,在 Arcball 旋转之前存储了初始化的模型视图矩阵:

    Matrix4 modelview = Matrix4.LookAt(camera.camerapos, camera.cameratarget, camera.cameraup);
    rtn_complete = modelview;
    

然后...

Matrix4 mm = Matrix4.CreateFromQuaternion(qCurrent) * rtn_complete;
GL.LoadIdentity();
GL.MultMatrix(ref mm);

这适用于观看者的正确旋转,但围绕错误的旋转中心。这是一个距离相机目标很远的点。

显然,这种方法需要在旋转的任一侧进行向前/向后平移,但我已经尝试了几乎所有可能的组合,但它们都不起作用。

相机和目标位置如下:-

camera.camer’ = (-51.3, -67.9, 37.7),和

camera.cameratarget = (0.0, 0.6, 7.3)

当我添加如下翻译(以及无数其他排列)时,我仍然让场景围绕错误的原点旋转。

GL.LoadIdentity();
GL.Translate(camera.cameratarget);
GL.MultMatrix(ref arcball_rot);
GL.Translate(-camera.cameratarget);
GL.MultMatrix(ref rtn_complete);

我的感觉是问题的根源很可能是使用 LookAt 应用的翻译,我在进行上述转换时没有考虑到这一点。

但是,当我检查 rtn_complete 矩阵(它是 LookAt 之后的模型视图矩阵)时,第四列不包含翻译。矩阵如下所示:

0.80, 0.20, -0.56, 0.00
-0.60, 0.27, -0.75, 0.00
0.00, 0.94, 0.34, 0.00
0.38, -7.02, -92.8, 1.00

我本来希望在这里看到翻译。

编辑1:

终于找到了。我对使用 Matrix4.LookAt() 产生的翻译的怀疑是正确的。

我列出用于调试的矩阵的方式导致了转置,所以我可以看到翻译,但我错过了它,但它在第四行而不是第四列。平移为 (0.38, -0.72, -92.8) 在 Arcball 旋转的任一侧应用此平移会导致最初的预期旋转行为。

GL.LoadIdentity();
GL.Translate(0.38, -7.02, -92.8);
GL.MultMatrix(ref mm);
GL.Translate(-0.38, 7.02, 92.8);
GL.MultMatrix(ref rtn_complete);

编辑2:

解决了上述问题后,我已经非常接近了,但是当我在场景中的其他地方移动时仍然不太正确。我再次遇到了几个问题,可以同时解决一个或另一个,但不能同时解决。

由于 Matrix4.LookAt,我分离出了​​ rtn_complete 矩阵的平移和旋转分量(分别为 'rtn_complete_trans' 和 'rtn_complete_rot')。

如果我这样做,旋转就在:

GL.LoadIdentity();
GL.Translate(rtn_complete_trans); // modelview translation component
GL.Translate(camera.cameratarget); // translate to rotation centre
GL.MultMatrix(ref arcball_rot); // ongoing Arcball rotation
GL.MultMatrix(ref rtn_complete_rot); // modelview rotation component
GL.Translate(-camera.cameratarget); // translate back from rotation centre

但是每次初始化视图时都会出现不需要的翻译。如果我旋转、释放并重复几次,对象会逐渐移出屏幕。

如果我更改第二个摄像机平移的位置,则不再发生这种不需要的移位,但旋转中心关闭:

GL.LoadIdentity();
GL.Translate(rtn_complete_trans); // modelview translation component
GL.Translate(camera.cameratarget); // translate to rotation centre
GL.MultMatrix(ref arcball_rot); // ongoing Arcball rotation
GL.Translate(-camera.cameratarget); // translate back from rotation centre
GL.MultMatrix(ref rtn_complete_rot); // modelview rotation component

谁能解释一下?

4

0 回答 0