四元数(复数的二维扩展)可用于表示3D向量的旋转和缩放,并且将四元数应用于3D向量涉及两个四元数乘法,因此与通过相应变换矩阵进行乘法运算相比,所需操作更少。但是,通常会改用线性和仿射变换矩阵,尤其是在着色器代码中。

何时使用四元数表示缩放和旋转是合适的并且是优选的(由于速度,稳定性等)在三个维度上,而不是相应的变换矩阵上?

评论

另请参阅GameDev SE上的相关问题。

#1 楼

我想从一个误解入手:

现代GPU(相当一段时间以来,NVIDIA以及从Southern Islands开始的AMD)并没有真正地支持硬件中的矢量/矩阵运算。它们是沿不同方向的向量体系结构:向量的每个分量(x,y,z)通常具有32或64值,其中包含泳道中每个元素的值。因此3D点乘积通常不是指令,它是一个乘法和两个乘法加法。

另外,对诸如乘法加法之类的原始运算进行计数,通过四元数转换向量比转换更昂贵一个矩阵向量用3x3矩阵变换向量是3个乘法和6个乘法加法,用四元数变换向量是两个四元数乘法,每个四元数乘法包括4个乘法和12个乘法加法。 (您可能会比这更幼稚-这是一种更快的方法-但它仍然不如将向量乘以矩阵便宜。)

但是,性能并非总是通过计数来确定它执行的ALU操作数。四元数比等效矩阵需要更少的空间(假设您仅在进行纯旋转/缩放),这意味着更少的存储空间和更少的内存流量。这在动画中通常很重要(四元数的漂亮插值属性通常也很方便出现)。

除此之外:


矩阵使用更多空间,因为它们支持更多操作。 3x3矩阵可以包含不均匀的比例尺,偏斜,反射和正交投影。
自然可以将矩阵视为基本矢量,并可以轻松地从这些矢量中构建。
一个四元数与另一个四元数相乘(组成两个旋转)。 )比将一个矩阵乘以另一个要少。


评论


$ \ begingroup $
有趣的是,在Intel Haswell GPU上,ARBfp的DP3指令实现为3乘2加,请参阅Intel Linux驱动程序的INTEL_DEBUG = fs输出:paste.ubuntu.com/23150494。不确定是驱动不良还是硬件确实没有特殊的矢量mul指令。
$ \ endgroup $
–俄罗斯
16 Sep 8'在15:14



$ \ begingroup $
@Ruslan很可能该硬件没有特殊的矢量mul指令。尽管它们确实更准确,但它们是在体系结构的SIMD宽度(通道)上向量化的,而不是在vec3 / vec4维度上向量化的。
$ \ endgroup $
– John Calsbeek
16年8月8日在18:17

#2 楼

(在这里,我无情地从joojaa和棘轮怪胎的答案中借来了很多信息,并附带了一些自己的注释。)

矩阵优势



非均匀缩放和旋转,偏斜,投影
平移(除非使用双四元数)
本机硬件支持
四元数通常需要先验函数来构造
更容易理解

四元数优点


变换向量需要较少的操作(或者不是-参见John的答案)
用另一个quat进行变换所需的操作更少
四元数占据4个浮点,(8 (如果是对偶),但矩阵占据9-16个浮点数

如果您只打算进行统一的刚体变换,则矢量/四对通常在3x4矩阵上是一个坚实的胜利在存储空间(向量/ quat:7或8个浮点数与mat3x4:12个浮点数)和处理速度方面。如果四元数仍然对您来说是神秘的伏都教,请尝试在其上使用此网络系列。

#3 楼

与四元数相比,矩阵提供了更多可能的变换,它可以倾斜,镜像和非均匀缩放矩阵。没有任何内容表明,如果不需要其他转换功能,就无法使引擎仅执行基于四元数的转换。

当您需要在需要知道的位置构建空间时,矩阵非常方便基本向量。例如在对正交进行投影时。在矩阵空间中进行透视变换也很容易。

以某种方式通常使用矩阵,因为它们代表最常见的面额,并且不太容易掌握和理解。标准化的好处远远超过了从自定义工作流程中获得的好处。它众所周知的如何做矩阵运算。 qua并不是uni中最容易立即介绍的东西。只是问周围有多少人知道如何反转四元数,而没有找到很多不知道如何反转矩阵的学生。

请注意,图形卡还具有用于矩阵操作的专用管道。

评论


$ \ begingroup $
我实际上一直在考虑这个。 Ive还开玩笑地问,除了可以使用矩阵和quat层次结构之外,还可以使用什么其他方法对管道进行建模。
$ \ endgroup $
– joojaa
2015年8月9日下午13:17

#4 楼

四元数只能表示均匀的缩放和旋转,因此如果需要其他任何内容,则需要添加一些内容来表示。

可以使用单个附加vec3(或使用双四元数)进行翻译。但是,用mat4可以更好地表示不均匀的缩放和收缩。投影变换(本质上是不均匀的缩放以及交换z和w)不能用四元数表示。

四元数在插值时具有很大的优势。使用四元数最容易计算出slerp。

GPU中未内置应用四元数(或双四元数)的功能,因此您需要使用矢量运算来实现。大多数四元数库都假定您不会使用四元数来表示比例,因此需要注意。