[WebGL入门]三十一,Quaternions(四元数)

注:文章译自http://wgld.org/,原作者杉本雅広(doxas)

3D编程和数学

3D编程的世界中,数学的知识是非常重要的。最具代表的就是矩阵了,不知道矩阵的话,就没办法进行坐标变换了。而其他的,向量的知识,内积・外积这些也都是不可缺少的。的确是非常烦人。
那么,这次的标题是四元数。不光是WebGL,在DirectX中也同样存在着四元数。它到底是个什么东西,使用它之后又有那些方便之处,我想很多人恐怕也没有明确的概念。这次就来说说四元数的定义以及它的简单的使用方法。这次真的是纯粹的数学话题,估计读起来会很枯燥,首先理解这篇文章的最大目的,然后慢慢往下看吧。

它到底是什么

四元数是数学中的一个概念。3D编程中和旋转相关的处理会经常使用到四元数。
四元数到底是什么,大家自己在网上搜一下,估计会出现很多很难理解的说明。比如在wikipedia中四元数的解释如下。

拥有三个虚数的超复数之一

这对大多数人来说,跟没说一样。至少我个人读了这个之后,完全不明白它的意思。
刚才也说了,四元数的定义和原理并不是本篇文章的目的。咱们只在一定程度上说一下四元数是什么,怎么用,这才是本次的重点。请在这个大前提下,继续读下去。
首先,来考虑一下。三维空间上,讲一个什么模型放进去的时候,这个模型的姿势要如何来表示呢。注意不是模型的坐标位置,是[姿势]。这里所说的姿势,是模型如何倾斜啦,模型面向什么方向啦,等等,主要是模型的各种旋转的属性。
旋转的话,使用矩阵不是也已经可以表现出来了吗!确实,矩阵是可以处理矩阵的旋转的,移动和缩放也是可以同时处理的,只是单纯的表达[姿势]的话,已经包含在里面了。
而且,使用矩阵进行旋转,可以知道X ・ Y ・ Z的各轴分别旋转了多少度,三个轴的旋转组合在一起,确实差不多已经可以表达[姿势]了。但是会稍微有些复杂,比如说面向局部坐标(0.0, 1.0, 0.0)方向的模型,将它变为面向(0.42, 0.59, 0.68)方向,那么XYZ的各轴要分别旋转多少度才合适呢。这就不是一般人的思考能力可以想象的了。
从这个观点来看[姿势],用矩阵就有些难理解了。为了表示[姿势],至少需要[旋转了多少度]和[向哪个方向旋转]这些信息。也就是说,有了这两个信息,就可以表示出旋转了。可能也不是很好理解,所有的姿势都可以通过这两个要素来表示出来。
那么,要把这两个要素很好的表示出来,就是四元数了。使用四元数,就可以表示以任意方向为轴,做任意角度的旋转。也就是说,只需要一个四元数,就可以将所有的姿势表示出来了。
估计读到这里,还是有很多人对四元数依然不是很理解。那就在接下来实际运用过程中,进一步理解吧。

四元数的表示

四元数可以表示出以[ 任意方向的轴 ]进行[ 任意角度的旋转 ]。

首先,想一下任意方向的轴。比如说在做灯光的处理的时候,为了表示光的方向,我们定义了光向量。从这一点来看,表示方向的话,用一个向量就足够了。三维空间中的向量,就可以通过X ・ Y ・ Z三个元素来表示。
接着,想一下任意的旋转角度,因为是纯粹的角度,角的度量可以用角度或者弧度来表示。
这些综合起来,构成四元数的元素,就是一个拥有三个元素的向量和一个角度。这就是四元数了。
四元数一般来说,像下面这样表示。

Q = (t; x, y, z)
只有一个元素和一个向量而已吧。就是刚才说的那样,四元数就是由向量和角度构成的。从上面的式子来看,也很容易理解吧。用难一点的语言来描述的话,上面的t叫做实数部分,向量部分的三个元素叫做虚数部分。但是,也不用太在意这些叫法。重要的是,理解了四元数可以用来表示四个元素就行了。

在实际的编程当中,如果要使用四元数,最低限度也得知道上面说的这些。而实数,虚数这些内容,想知道的话,可以自己查一下。

使用四元数的计算

接着看一下四元数的计算方法。
首先应该知道,四元数之间的乘法和矩阵一样,相乘的顺序改变的话,结果也会改变,这个一定要记住。
四元数的相乘,像下面这样进行。

>クォータニオン同士の掛け算

Q = (q; V)

R = (r; W)

QR = (qr - V ・ W; qW + rV + V × W)
上面的式子就是第一个四元数 Q 和第二个四元数 R 相乘的计算。这里出现的[ ・ ]是点积,也就是内积。[ × ]是差积,也就是外积。
这里的四元数之间的相乘处理,最终就是加算,减算,以及内积和外积的计算,计算的负荷也不大,可以进行比较告诉的处理。
理解了四元数之间的相乘,下面来看使用四元数来表示旋转。这个也一样,记住规则的话,也就没那么难了。用四元数做旋转像下面这样。
>用四元数来旋转

以原点为中心的轴向量 = (x, y, z)

旋转角度 = th

Q = (cos(th / 2); x * sin(th / 2), y * sin(th / 2), z * sin(th / 2))

乍一看,一定会想这是什么玩意儿?仔细看一下,其实很简单。就是X ・ Y ・ Z 的每一项,分别乘以角度的一半的正弦值。就这样,就可以表示旋转了,是不是很简单。
这里需要注意的是,向量需要正规化,千万不要使用未正规化的向量。(把一个非零向量化成与它同方向的单位向量,称为向量的正规化或单位化。)
用上面表示四元数的同样的方法,接下来来表示一个叫做共轭四元数的四元数。名字有点儿吓人,但是也不需要害怕,共轭四元数只是将四元数的X ・ Y ・ Z 的值取反。
>共轭四元数

以原点为中心的轴向量 = (x, y, z)

旋转角度 = th

Q = (cos(th / 2); x * sin(th / 2), y * sin(th / 2), z * sin(th / 2))

Q 的共轭四元数 R

R = (cos(th / 2); -x * sin(th / 2), -y * sin(th / 2), -z * sin(th / 2))
这样,表示旋转的四元数Q,和它的共轭四元数R就表示出来了。使用这两个四元数,在三维空间上的一点,沿着任意轴,任意角度进行旋转,就都可以表示出来了。计算方法如下。
>任意轴・任意角上的旋转计算

三维空间上的坐标: P = (0; x, y, z)

将P 做旋转的计算……

R * P * Q = (0; X, Y, Z)
刚才也说了,四元数之间的乘法是跟顺序有关的,要十分注意。上面的式子,大写字母的XYZ,就是沿任意轴,任意角度旋转后得到的坐标。
仔细想一下的话,只需要简单的计算,就能用四元数做一些处理了吧。

总结

好了,四元数已经了解了吧,使用四元数的方便之处还远不止这些,这次的文章,也只是让大家知道四元数是个什么东西,以及用四元数来做一些基本的计算,知道这些就足够了。
任意轴和任意角的旋转的计算方法也接触到了,像旋转那样冗长的坐标计算,也用四元数很简洁的进行了。虽然在实际程序中,如何灵活的运用是个问题,但无疑四元数是个很强大的工具。
下一次,使用四元数来写一个demo。为了方便四元数的处理,自己的库也会稍微解说一下。通过demo来接触下四元数的话,就能更加了解四元数的使用方法了。


欢迎继续关注我的博客

转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页