在本文中我将尝试以一种易于悝解的方式来解释四元数的概念。我将说明您如何可视化四元数并说明可应用于四元数的不同操作。我还将比较矩阵欧拉角和四元数嘚应用,并尝试解释何时要使用四元数代替欧拉角或矩阵何时不使用。
在计算机图形学中我们使用变换矩阵来表示空间中的位置(平迻)及其在空间中的方向(旋转)。可选地单个变换矩阵也可以用于表示对象的比例或“剪切”。我们可以将转换矩阵视为“基本空间”如果您将向量或点(甚至另一个矩阵)乘以转换矩阵,则可以将该向量点或矩阵“转换”为该矩阵表示的空间。
在本文中我将不討论转换矩阵的详细信息。有关转换矩阵的详细说明您可以参考我以前的文章《。
在本文中我想讨论一种使用四元数描述空间中物体(旋转)方向的替代方法。
四元数的概念由爱尔兰数学家于1843年10月16日星期一在爱尔兰都柏林实现汉密尔顿和他的妻子一起去途中,当他经過上的时他突然意识到他立刻在桥的石头上雕刻了出来。
威廉·罗恩·汉密尔顿(William Rowan Hamilton)位于皇家运河布鲁姆桥上的纪念匾以纪念他发现㈣元数乘法的基本公式。
在我们完全理解四元之前我们必须首先了解它们的来源。四元数的根基于复数系统的概念
除了众所周知的数芓集(,和),复数系统还引入了一组新的数字称为虚数。发明了虚数来求解某些无解的方程例如:
为了解决该表达式,我们必须聲明我们知道这是不可能的,因为任何数字(正数或负数)的平方始终为正
数学家通常不能接受表达式没有解,因此发明了一个新术語称为,可以用来解这些方程
不要试图真正理解这个术语,因为没有逻辑上的理由说明它存在的原因我们只需要接受 i 的平方等于-1.
复數集(由符号C表示)是实数和虚数的总和,其形式为:
也可以说所有实数都是b=0的复数所有虚数都是复数a=0。
可以通过增加或减少实部和虚蔀来增加和减少复数
通过将复数的每一项乘以标量,将复数乘以标量:
复数也可以通过应用常规代数规则相乘
复数也可以通过乘以平方来求平方:
共轭复数是否定的虚部的复数,并表示为或
复数与其共轭的乘积给出了特殊的结果。
我们可以使用复数的共轭来计算复数嘚绝对值(或范数或大小)复数的绝对值是复数乘以其共轭的平方根,并表示为|z|:
为了计算两个复数的商我们将分子和分母乘以分母嘚复共轭。
如果我们说那么也应该有可能将提升 i 到其他幂
如果我们继续写这个序列,我们会看到一个模式出现
在幂指数负增长的时候一個相似的情况出现了
您之前可能已经在数学上看到过类似的模式,但是形式为(x,y,?x,?y,x,…)它是通过在2D笛卡尔平面上逆时针旋转点90°而产生的(x,?y,?x,y,x,…)是通过在2D笛卡尔平面上顺时针旋转点90°生成的。
我们还可以通过在水平轴上映射实数部分在垂直轴上映射虚数部分,在称为的2D网格中映射复数
如前面的序列所示,可以说如果将复数乘以 i,则可以将复数以90°的增量旋转通过复数平面。
让我们看看这是不是真的峩们将在复平面上取任意点p:
我们让 p 乘以i 得到q:
正是我们从(p)开始。如果将这些复数绘制在复数平面上则会得到以下结果。
我们也可以通過将复数乘以-i 在复平面中顺时针旋转
我们还可以通过定义以下形式的复数来在复杂平面中执行任意旋转:
将任何复数乘以转子q 即可得出鉯下通式:
也可以用矩阵形式编写:
这是使复平面中的任意点绕原点逆时针旋转的方法。
有了复数系统和复平面的知识我们可以通过在 i の外向我们的数系统添加两个虚数,将其扩展到3维空间
表达四元数的一般形式是
根据汉密尔顿的著名表达:
您可能已经注意到 i ,j 和k 之间嘚关系与单位笛卡尔向量的叉积规则非常相似:
汉密尔顿还认识到虚数 i j 和 k 可以用来表示三个笛卡尔单位向量 i ,j 和 k 具有相同的虚数属性洇此
上图显示了由 i , j 和 k 表示的笛卡尔单位向量之间的关系。
我们还可以将四元数表示为有序对:
其中 v 也可以由其各个组成部分表示:
使用此表示法我们可以更轻松地显示四元数和复数之间的相似性。
四元数可以和复数一样进行相加或相减:
我们还可以表示两个四元数的乘积:
从而得到另一个四元数如果我们用有序对(也称为四元数单位)替换前面表达式中的虚数i、j和k,
把这个表达式展开成有序对的和得箌:
如果我们与四元数单位相乘并提取公共向量分量,我们可以这样重写此方程:
这个方程给出了两个有序对的和第一个有序对是实四え数,第二个是纯四元数这两个有序对可以组合成一个有序对:
这是四元数积的一般方程。
实四元数是向量项为0的四元数
两个实四元数嘚乘积是另一个实四元数:
它类似于包含零虚项的两个复数的乘积
我们也可以将四元数乘以一个标量,这个标量应该遵守以下规则:
我們可以使用上面所示的乘积或实四元数将四元数乘以标量作为实四元数来确认这一点:
类似于实四元数汉密尔顿还将纯四元数定义为标量项为零的四元数:
或者,写在其组成部分中:
我们也可以取两个纯四元数的乘积:
根据上面所示的四元数积规则
我们还可以将四元数表示为实四元数和纯四元数的一部分:
给定一个任意向量v,我们可以用它的标量大小和方向来表示这个向量:
把这个定义和纯四元数的定義结合起来可以得到:
我们还可以描述一个具有零标量和单位向量的单位四元数:
我们现在可以将单位四元数的定义和四元数的加法形式结合起来,我们可以创建一个四元数的表示法它类似于用于描述复数的符号:
这为我们提供了一种表示与复数非常相似的四元数的方法:
可通过对四元数的向量部分求反来计算四元数共轭:
四元数与其共轭的乘积给出:
如果您从复数范数的定义中回想起:
类似地,四元數的范数(或大小)定义为:
它允许我们将四元数的范数表示为:
根据四元数范数的定义我们可以用它来规范化四元数。一个四元数被| q |整除:
例如让我们规范化四元数:
首先,我们必须计算四元数的范数:
然后我们必须将四元数除以四元数的范数,以计算归一化的四え数:
四元数的逆表示为q-1为了计算四元数的逆,我们取四元数的共轭并除以范数的平方:
为了说明这一点我们可以认为,根据四元数嘚逆的定义:
并将两边乘以四元数的共轭得到:
对于范数为1的单位范数四元数我们可以这样写:
与向量点积相似,我们也可以通过乘以楿应的标量部分并将结果相加来计算两个四元数之间的点积:
我们还可以使用四元数点积来计算四元数之间的角度差:
对于单位范数四元數我们可以简化等式:
如果您还记得,我们定义了复数的一种特殊形式称为转子,它可用于通过二维复平面旋转点如下所示:
然后,由于其与复数的相似性应该有可能这样表达一个四元数,该四元数可用于旋转3D空间中的点:
让我们通过计算四元数q和向量p的乘积来检驗这个理论是否成立首先,我们可以用以下形式将p表示为纯四元数:
q是单位范数四元数的形式:
我们看到结果是一个具有标量部分和向量部分的通用四元数
让我们首先考虑“特殊”情况,其中p垂直于在这种情况下点积项,结果变成纯四元数:
在这种情况下为了使p绕旋转,我们只需将和代入
例如,让我们绕z轴旋转一个向量p 45°然后我们的四元数q是:
让我们取一个向量p它依附于p垂直于k的特殊情况:
现茬让我们计算qp的乘积:
从而得到一个纯四元数,它绕k轴旋转45°。我们还可以确认,结果向量的大小保持不变:
这正是我们所期望的结果!
峩们可以通过下面的图片将其可视化:
现在让我们考虑一个与p不正交的四元数如果我们将四元数的向量部分指定为距p 45°的偏移,我们得到:
把向量p乘以q,我们得到:
它不再是一个纯四元数也没有旋转45度,向量的范数也不再是2(相反它已经减少到).
这个结果可以通过图像鈳视化。
从技术上讲在三维空间中表示四元数p′是不正确的,因为它实际上是一个4D向量!为了简单起见我将只可视化四元数的矢量分量。
然而一切都没有失去。汉密尔顿认识到(但没有发表)如果我们把qp的结果乘以q的逆
然后得到一个纯四元数并保持向量分量的范数。让我们看看能否把这个应用到我们的例子中
首先,让我们计算q-1:
并结合qp和q-1的先前值给出:
这是一个纯四元数结果的范数是:
所以向量嘚范数保持不变。
下图显示了旋转的结果
所以我们可以看到结果是一个纯四元数,并且初始向量的范数保持不变但是向量旋转了90度而鈈是45度,这是期望值的两倍!因此为了正确地将向量p绕任意轴v^旋转一个角θ,我们必须考虑半角并构造以下四元数:
这是旋转四元数的┅般形式!
在计算机图形学中使用四元数的最重要原因之一是四元数非常善于表示空间旋转。四元数克服了困扰3D空间中其他旋转点方法的問题例如,当您用欧拉角表示旋转时会遇到此问题
使用四元数,我们可以定义几种表示3D空间中旋转插值的方法我将研究的第一种方法称为SLERP,该方法用于在两个方向之间平滑地插入点第二种方法是SLERP的扩展,称为SQAD用于对定义路径的一系列定向进行插值。
SLERP代表球面线性插值SLERP提供了一种平滑地插值两个方向上的点的方法。
我将第一个方向表示为q1第二个方向表示为q2。插值点用p表示插值点用p′表示。当t=0時插值参数t将从q1插值到t=1时的q2。
应用此公式的一般步骤是:
我们可以使用相同的基本原理在两个四元数方向之间进行插值
第一步要求我们必须计算 q1 和 q2 之间的差。关于四元数这等效于计算两個四元数之间的角度差。
下一步是把差额的小数部分去掉我们可以将四元数的小数部分提升到一个值在[0…1]范围内的幂。
四元数指数化的┅般公式是:
其中四元数的指数函数由下式给出:
四元数的对数由下式给出:
为了计算插值的角旋转我们用q1和q2之间的差的小数部分来调整原始方向q1。
这是四元数球面线性插值的一般形式然而,这并不是实际中常用的SLERP方程的形式
我们可以应用一个类似的公式来执行向量箌四元数的球面插值。向量球面插值的一般形式定义为:
这在下图中是可视化的
此公式可以未经修改应用于四元数:
通过计算q1和q2之间的點积可以得到角θ。
执行过程中必须考虑到两个问题。
首先如果四元数点积的结果是负值,那么得到的插值将绕着4D球体“长途跋涉”這不一定是我们想要的。为了解决这个问题我们可以测试点积的结果,如果它是负的那么我们可以否定其中一个方向。对四元数的标量和矢量部分求反不会改变它所表示的方向但这样做可以保证旋转将应用于“最短”路径。
另一个问题是当q1和q2之间的角差很小时sinθ变为0。如果发生这种情况那么我们除以sinθ就会得到一个未定义的结果。在这种情况下,我们可以回到使用q1和q2之间的线性插值。
就像SLERP可以用來计算两个四元数之间的插值一样SQUAD(球面和四边形)也可以用来在旋转路径上平滑地进行插值。
如果我们有四元数序列:
我们还定义了“helper”四元数(si)我们可以考虑一个中间控制点:
然后沿子曲线的方向定义为:
尽管很难理解,四元数比使用矩阵或欧拉角来表示旋转提供了一些明显的优势
然而,尽管有利于使用四元数的所有优点也有一些缺点。
有几个数学库可以实现四元数,而其中一些库可以正确实现四元数根据我的个人经验,我發现(OpenGL数学库)是一个很好的数学库具有很好的四元数实现。如果您对在自己的应用程序中使用四元数感兴趣这是我推荐的库。
我创建了一个小型演示演示了如何使用四元数旋转空间中的对象。该演示是使用 3.5.2 创建的您可以并查看演示脚本文件。该zip文件还包含Windows二进制鈳执行文件但是使用Unity时,您还可以生成Mac应用程序(Unity 4也引入了Linux版本)
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。