7

我目前正在构建自己的四元数相机。据我所知,您只需要一个四元数即可完全指定相机的方向(如果我错了,请纠正我)。那么,我将如何创建视图矩阵?顺便说一句,我使用 C++ 作为编程语言。

任何帮助,将不胜感激。

4

4 回答 4

14

首先是一些警告。你会在网上和关于这个主题的文献中看到很多明显相互矛盾的公式。大多数冲突只是显而易见的。有一些是真正的冲突,但那是因为有人弄错了数学。问题是没有单一的正确方法可以做到这一点。您需要知道如何使用四元数和矩阵,源如何使用它们,以及如何纠正这些明显的差异。

旋转与变换
你的相机有一个与之关联的参考框架,底层空间也是如此。您的矩阵是表示相机从基础空间到相机方向的物理旋转,还是表示将基础空间中表示的向量转换为相机框架的矩阵?(或者别的什么;这里有四个选择。)这些选择是相关的;变换矩阵是旋转矩阵的转置。变换和旋转是共轭运算。同样的概念也适用于四元数。您使用的是转换四元数还是旋转四元数?这些又是相关的概念;一个是另一个的共轭。

左右四元数
给定一个单位四元数q来变换或旋转向量v,一些使用qvq *来变换/旋转向量,其他使用q * vq。哪种形式是正确的?两者都是。这两种形式的区别仅在于非共轭四元数是在要转换/旋转的向量的左侧(qvq *)还是右侧(q * vq)。

列向量与行向量
大多数人使用列向量,但有些人使用行向量。在这里,您遇到了矩阵的左右问题。列向量通过Mv变换/旋转,矩阵位于向量的左侧;通过vM的行向量,右侧的矩阵。

影响
你必须小心阅读文献。关于从四元数形成矩阵,您需要注意构造矩阵的非对角元素时的符号变化。一种配方的加法/减法可能会变成另一种配方的减法/加法。

左变换四元数到行向量变换矩阵
我使用左变换四元数和变换矩阵,并将向量表示为行向量。我还将四元数q表示为包含实数标量部分q s和向量虚数部分q v。给定这些表示,从四元数生成矩阵的计算是(伪代码):

// Compute the cosine of the rotation angle.
cost = 2.0*qs*qs - 1.0;

// Construct the diagonal of the matrix:
// T_ii = cost + 2qv_i^2
for (i = 0; i < 3; ++i) {
   T[i][i] = cost + 2.0*qv[i]*qv[i];
}

// Construct off-diagonal transformation matrix elements:
//   T_ij = 2 (qv_i qv_j - eps_ijk qs qv_k), where eps is the Levi-Civita symbol
for (k = 0; k < 3; ++k) {
   i = (k+1)%3;
   j = (i+1)%3;
   T[i][j] = 2.0*(qv[i]*qv[j] - qs*qv[k]);
   T[j][i] = 2.0*(qv[i]*qv[j] + qs*qv[k]);
}

您可能想要扩展这些循环。第一个循环扩展为三个语句,后者为六个。您不需要在后一个循环的扩展中计算ij;循环的扩展使它们成为固定数量。

替代表示
上面的这些警告并不像看起来那么糟糕。你需要确保我的陈述与你的一致。赔率是 50-50,它不是。如果不是,只需将分配交换到非对角线元素。T[i][j]使用for的计算,T[j][i]反之亦然。如何判断:

  • 从s =1开始。
  • 如果使用旋转四元数而不是变换四元数,则将s乘以-1。
  • 如果使用右四元数而不是左四元数,则将s乘以-1。
  • 如果使用旋转矩阵而不是变换矩阵,则将s乘以-1。
  • 如果使用行向量而不是列向量,则将s乘以-1。

如果s的最终值为1,请使用我的公式。如果为 -1,只需将分配交换为T[i][j]T[j][i]。或者您可以将加法改为减法,将减法改为加法。

最后一个问题
上述计算适用于标量部分不接近于零的情况。如果我们有无限精度的算术,它将在任何地方都有效。您可能希望对非常接近零或 180 度的旋转使用单独的计算。

于 2012-10-08T13:19:34.980 回答
3

维基百科知道:四元数和空间旋转

于 2012-10-08T08:47:05.963 回答
2

我建议使用Eigen C++ 库来表示您的四元数和矩阵。当你有一个四元数对象时,你可以简单地调用.toRotationMatrix()它来获得一个 3x3 矩阵。

另一个可能有用的库是glm

于 2012-10-08T16:13:33.673 回答
1

可配置数学库 ( http://cmldev.net/ ) 是一个非常轻量级的库,可以为您进行计算。它是一个头文件库,因此集成到您的代码中应该不成问题。此功能 ( http://cmldev.net/?p=196 ) 也可能对您有所帮助。

于 2012-10-08T16:02:57.657 回答