Real-Time Rendering-第四章 Transforms(3)

来源:互联网 发布:网络监控系统设计说明 编辑:程序博客网 时间:2024/06/09 17:04

4.3 Quaternions

虽然四元数早在1843年就由William Rowan Hamilton先生发明出来用于表示复数的扩展,但是直到1985年才由Shoemake[1176]把四元数引入到了计算机图形学领域。四元数是构建具有强大功能的变换操作的一个有力工具,而且在某些方面,四元数是比欧拉角度和矩阵更好的计算方式,特别是在旋转操作和方位计算方面。给定一个 轴&角度 的表示形式,转变成一个四元数或从四元数转变成原来的形式是直截了当的,而使用欧拉角度则无法在任何方向进行转换。四元数可以用于稳定并不断的确定方位的插值运算,而这是使用欧拉角度无法完成的。

复数包含一个实部和一个虚部。每一个部分由两个实数表示,其中第二个实数通过与1相乘。类似的,四元数具有四个部分。前三个部分的值与旋转轴密切相关,因为旋转的角度会影响所有部分的值(4.3.2节有更多相关的内容)。每一个四元数由4个实数表示,每个实数对应于一个不同的部分。由于四元数具有四个分量,我们选择使用向量的形式表示它们,但是与向量不同的是,在记号上加一个帽子:q^。首先我们会讨论一些关于四元数的数学背景知识,然后用于构建一些有趣的,实用的变换运算。

4.3.1 Mathematical Background

我们从描述一个四元数的定义开始。
Definition. 可以使用下面的方法定义四元数 q^,所有的定义都同等的。

q^ qv i2 =(qv,qw)=iqx+jqy+kqz+qw=qv+qw,=iqx+jqy+kqz=(qx,qy,qz),=j2=k2=1,jk=kj=i,ki=ik=j,ij=ji=k.(4.28)

其中变量 qw 称为四元数 q^ 的实部,虚部为 qv,并且 ijk 称为虚部的基本单位。

对于四元数的虚部 qv,我们可以使用向量的所有基本运算,比如向量加法,向量-标量乘法,点乘,叉乘等等。使用四元数的定义,我们推导出两个四元数 q^r^ 的乘法运算,如下所示。需要注意的是虚部的乘法不满足交换律。

Multiplicationq^r^ =(iqx+jqy+kqz+qw)(irx+jry+krz+rw)==i(qyrzqzry+rwqx+qwrx)  +j(qzrxqxrz+rwqy+qwry)  +k(qxryqyrx+rwqz+qwrz)  +qwrwqxrxqyryqzrz==(qv×rv+rwqv+qwrv,qwrwqvrv).(4.29)

从该公式中可以看出,我们同时使用了叉积和点积计算两个四元数的乘积。有了四元数的定义之后,我们就可以定义四元数的加法,共轭,范数,以及单位化运算:

Addition:Conjugate:Norm:Identity:q^+r^=(qv,qw)+(rv,rw)=(qv+rv,qw+rw).q^=(qv,qw)=(qv,qw).n(q^)=q^q^=q^q^=qvqv+q2w=q2x+q2y+q2z+q2w.i^=(0,1).(4.30)

在对n(\hat{\mathbf{q}}) = \sqrt{\hat{\mathbf{q}}\hat{\mathbf{q}}^*}进行简化(结果如上)之后,虚部都抵消了且只剩下一个实部。四元数的规范化有时也可以表示为|\hat{\mathbf{q}}| = n(\hat{\mathbf{q}})[808]。由以前运算的结果可以推导出四元数的乘法倒数,表示为 q^1。倒数必须满足公式q^1q^=q^q^1=1(这正是乘法倒数的通用性质)。由四元数规范化运算的定义可以推出以下公式:

n(q^)2=q^q^q^q^n(q^)2=1,(4.31)

由此可以得到如下的乘法倒数公式:

Inverse:q^1=1n(q^)2q^.(4.32)

四元数的求导公式使用了标量乘法,这是由公式4.29中的乘法运算推导出来的:sq^=(0,s)(qv,qw)=(sqv,sqw),并且q^s=(qv,qw)(0,s)=(sqv,sqw),也就是说标量乘法满足交换律。

由四元数的定义可以推导出以下的运算法则:

Conjugate rules(q^)(q^+r^)(q^r^)=q^,=q^+r^,=r^q^.(4.33)

Norm rulesn(q^)(q^+r^)=n(q^),=q^+r^.(4.34)

Laws of MultiplicationLinearity线Associativityp^(sq^+tr^)(sp^+tq^)r^p^(q^r^)=sp^q^+tp^r^,=sp^r^+tq^r^.=(p^q^)r^.(4.35)

一个四元数 q^=(qv,qw)为单位四元数,也就是说 n(q^)=1。由此可以把 q^ 写成如下形式:

q^=(sinϕuq, cosϕ)=sinϕuq+cosϕ,(4.36)

对于某些三维向量 uq,有uq=1,因为

n(q^)=n(sinϕuq, cosϕ)=sin2ϕ(uquq)+cos2ϕ=sin2ϕ+cos2ϕ=1(4.37)

有且仅有uquq=1=uq2。在下一节我们将会看到,单位四元数非常适合用于高效的创建旋转和定向运算。但在些之前,将会介绍关于四元数的一些额外操作。

对于复数,一个二维的单位向量可以写成cosϕ+isinϕ=eiϕ。而对于复数,使用同样的方法表示为

q^=sinϕuq+cosϕ=eϕuq.(4.38)

由公式4.38可以得到单位四元数的对数和指数运算公式:

LogarithmPowerlog(q^)=log(eϕuq)=ϕuq,q^t=(sinϕuq+cosϕ)t=eϕuq=sin(ϕt)uq+cos(ϕt).(4.39)

4.3.2 Quaternion Transforms

我们现在开始研究四元数集的一个子类,单位四元数,即那些具有单位长度的四元数。有关单位四元数的最重要的性质是它们可以表示任意的三维旋转,并且这种表示方式极其紧凑简单。

现在我们描述四元数对于旋转和定向操作如此实用的原因。首先把一个点或向量p=(px  py  pz  pw)T 4个坐标值存储到一个四元数 p^ 的四个分量中,并假设有一个单位四元数 q^=(sinϕuq,cosϕ)。则有

q^p^q^1(4.40)

把四元数 p^(也就是点 p)围绕轴 uq 旋转 2ϕ 度。需要注意的是,由于 q^ 是一个单位四元数,有q^1=q^。图4.8中演示了该旋转操作,显示这种方法可以用于围绕任意轴旋转。

这里写图片描述
图4.8 使用单位四元数q^=(sinϕuq,cosϕ)表示旋转变换的示例。该变换表示围绕轴 uq旋转 2ϕ 弧度。

四元数 q^ 任何非0的多个实部也可以表示同样的变换,这意味着 q^q^ 表示相同的旋转操作。也就是说对轴 uq 及实部 qw 取反,会创建一个与原始四元数旋转结果完全一样的四元数。同样还意味着从一个矩阵中提取出四元数可以是 q^ 或者 q^

给定两个单位四元数 q^r^,对四元数 p^(可以用于表示点 p) 首先使用 q^ 再使用 r^ 的串联运算,如果公式4.41所示:

r^(q^p^q^)r^=(r^q^)p^(r^q^)=c^p^c^.(4.41)

其中 c^=r^q^ 是一个单位四元数,表示单位四元数 q^r^的串联。

Matrix Conversion

由于一些系统使用硬件的方式实现矩阵乘法,并且这种矩阵乘法比公式4.40更加高效,因此我们需要一种方法用于把一个四元数变换成一个矩阵,反之亦然。把四元数 q^ 转换成矩阵 Mq,可以使用公式4.42表示

Mq=1s(q2y+q2z)s(qxqy+qwqz)s(qxqzqwqy)0s(qxqyqwqz)1s(q2x+q2z)s(qyqz+qwqx)0s(qxqz+qwqys(qyqzqwqx1s(q2x+q2y00)0)0)1.(4.42)

其中标量为 s=2/n(q^)。对于单位四元数,公式4.42可以简化为
Mq=12(q2y+q2z)2(qxqy+qwqz)2(qxqzqwqy)02(qxqyqwqz)12(q2x+q2z)2(qyqz+qwqx)02(qxqz+qwqy2(qyqzqwqx12(q2x+q2y00)0)0)1.(4.43)

使用四元数构建了矩阵之后,没有任何三角函数需要计算了,因此在实际运算过程中这种变换过程是非常高效的。

反过来,从一个正交矩阵 Mq 变换为单位四元数 q^ 则需要更多运算。该运算过程的关键是由公式4.43中的矩阵得到的不同点:

mq21mq12mq02mq20mq10mq01=4qwqx,=4qwqy,=4qwqz.(4.44)

这些公式所表示的含义是,如果 qw 是已知的,就可以计算向量 vq的值,因此可以推导出 q^。使用如下公式可以计算矩阵 Mq 的迹
tr(Mq)=42s(q2x+q2y+q2z)=4(1q2x+q2y+q2zq2x+q2y+q2z+q2w)=4q2wq2x+q2y+q2z+q2w=4q2wn(q^).(4.45)

由此可以得到如下单位四元数的转换公式:
qw=12tr(Mq),qy=mq02mq204qw,qx=mq21mq124qw,qz=mq10mq014qw.(4.46)

为了得到一个数值稳定的例程,需要避免除以较小的数。因此,首先设置t=q2wq2xq2yq2z,由此可以得到如下公式

m00m11m22u=t+2q2x,=t+2q2y,=t+2q2z,=m00+m11+m22=t+2q2w.(4.47)

也就是说最大的 m00,m11,m22u 值反过来可以确定 qx,qy,qzqw 也是最大的。如果 qw 为最大值,则可以使用公式4.46除四元数。否则,我们需要注意以下公式:
4q2x4q2y4q2z4q2w=+m00m11m22+m33,=m00+m11m22+m33,=m00m11+m22+m33,=tr(Mq).(4.48)

然后使用上面适用的公式计算 qx,qyqz 的最大值,之后再使用公式4.44计算四元数 q^ 的其余分量值。幸运是已经有相关的代码用于转换的计算,见本章末尾的Further Reading and Resources。

Spherical Linear Interpolation

Spherical Linear Interpolation(球面线性插值)是指,给定两个单位四元数 q^r^,以及一个参数 t[0,1],计算一个插值四元数的操作。比如在处理动画物体时这种操作非常实用。但是对于相机朝向的插值运算该操作并不实用,因为相机的“向上方向”的向量在插值过程中会发生倾斜,通常产生一种令人不快的效果。

这种插值操作的代数形式可以使用如下的组合四元数 s^ 表示:

s^(q^,r^,t)=(r^q^1)tq^.(4.49)

但是对于使用软件实现来说,使用以下的形式更合适,其中 slerp 表示球面线性插值:
s^(q^,r^,t)=slerp(q^,r^,t)=sin(ϕ(1t))sinϕq^=sin(ϕt)sinϕr^.(4.50)

要计算该公式中所需要的 ϕ 值,可以使用如下论据:cosϕ=qxrx+qyry+qzrz+qwrw[224]。对于任意的 t[0,1],slerp函数用于计算插值的两个四元数从 q^(t=0)r^(t=1) 一起构成了四维单位球面上的最短圆弧。该弧线位于由 q^r^及球心所有的平面,与四维单位球的相交形成的圆圈上。如图4.9所示。由些计算得到的旋转四元数以恒定的速度围绕一个固定轴旋转。这种具有恒定速度的旋转曲线, 加速度为0,称为 geodesic 曲线[263]。

slerp函数非常适用于在两个朝向向量之间进行插值,并且计算结果非常稳定(保持固定轴,恒定速度)。在使用多个欧拉角度进行插值时无法达到这种运算效果。在实际运算过程中,直接执行slerp运算需要调用大量的三角函数,是一种高计算成本的操作。为此,Li[771,772]提出改进的方法,在不牺牲任何精度的情况下可以更快速的计算slerps值。

当有多个表示朝向的四元数可以用时,比如q^0q^1q^n1,并且我们要从 q^0q^1 再到 q^2 进行插值,依此类推,直接到 q^n1,可以使用一连串的slerp运算。假设现在要计算 q^i,我们将会使用 q^i1q^i 作为slerp的参数。计算完 q^i 之后,就使用 q^iq^i+1 作为下一个slerp运算的参数。这会导致在对朝向向量进行插值过程中出现急剧的变动,如图4.9所示。这种方法类似于对多个点进行线性插值;详见原书578页图13.2的右上图。一些读者在阅读第13章有关样条曲线的描述之后可能会回过头来学习以下段落。

一种更好的插值计算方法是使用某种样式的样条曲线。首先我们引入介于 q^iq^i+1 之间的四元数 a^ia^i+1。然后使用 q^ia^ia^i+1q^i+1 组成的四元数集定义三次球面插值运算。令人惊奇的是,使用如下的公式可以计算这些额外的四元数[294]:

a^i=q^iexp[log(q^1iq^i1)+log(q^1iq^i+1)4].(4.51)

其中 q^ia^i 用于对四元数进行球面插值,使用公式4.52所示的光滑的三次样条曲线:
saurd(q^i,q^i+1,a^i,a^i+1,t)=slerp(slerp(q^i,q^i+1,t),slerp(a^i,a^i+1,t),2t(1t)).(4.52)

如上公式所示,slerp 函数由多次重复使用slerp进行球面插值运算构成(详见第13章13.1.1节有关对多个点进行重复线性插值的讲解)。插值将会在初始的朝向四元数 q^i,i[0,,n1]之间进行传递,但是不会在 a^i 中传递,这些新引入的四元数用于表示初始四元数的切线方向。

插值将通过传递
初始方向 ˆqi,我 ∈ [0,…,n−1],但不是通过 ˆai — — 这些都是
用于指示在初始取向的切线方向

1 0
原创粉丝点击