c++ - 从四元数查看矩阵

标签 c++ math camera directx quaternions

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

任何帮助,将不胜感激。

最佳答案

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

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

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

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

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

左变换四元数到行 vector 变换矩阵
我使用左变换四元数和变换矩阵,并将 vector 表示为行 vector 。我还将四元数 q 表示为包括实标量部分 qs 和 vector 虚部 qv。鉴于这些表示,从四元数生成矩阵的计算是(伪代码):

// 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]);
}

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

替代表示
上面的警告并不像看起来那么糟糕。你需要确保我的陈述与你的一致。不是这样的几率是 50-50。如果不是,只需将分配交换到非对角线元素。使用 T[i][j] 的计算为 T[j][i] ,反之亦然。如何告诉:
  • 从 s=1 开始。
  • 如果使用旋转四元数而不是变换四元数,则将 s 乘以 -1。
  • 如果使用右四元数而不是左四元数,则将 s 乘以 -1。
  • 如果使用旋转矩阵而不是变换矩阵,则将 s 乘以 -1。
  • 如果您使用行 vector 而不是列 vector ,则将 s 乘以 -1。

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

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

    关于c++ - 从四元数查看矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12777675/

    相关文章:

    c++ - Eigen::MatrixXd 类型定义的替换

    c++ - MFC中的窗口消息管理:是否必须添加基类调用?

    预算内最高值(value)的算法

    iOS10,相机权限 - 黑屏 "camera app"

    cordova - 使用Cordova访问托管的PWA Web应用程序的 native 摄像头,音频和文件

    c++ - CMake的package_find冲突如何解决?

    c++ - 这是什么 C++ C11 语法 : "= {}"?

    java - Android - 调整可缩放 ImageView 顶部的 ImageView 位置

    algorithm - 实现互联网的希尔伯特图

    c++ - 由 View 相机 vector 指向的世界位置