说实话关于四元数这一节真的是不好懂,因为里面涉及到好多数学知识,单说推出来的公式就有很多。不怕大家笑话,对于四元数的学习我足足花了两天的时间,包括整理出这篇文章。在前面一章我写到了“变换”,这也是总结的学习笔记。我发现,写博客真是的是一个好多学习方法,加上之前一个博士师兄告诉我,要想好好的学习一本书或者一门技术,那么以此将学习笔记或者经验写成博客专栏是一种有效的方法。现在我要坚持这种方式,给自己留下学习过程中的足迹,也给大家分享一下。欢迎大家指出其中的不足,谢谢!

四元数是表示旋转的另一种数学形式,使用四元数可以节省存储空间,其之间的连接运算需要的算术运算更少,在产生平滑的三维动画时,用四元数更容易进行修改。

四元数集合,在数学上被称为哈密顿四元数环(ring of Hamiltonian quaternions),用H表示,可以理解为四维空间向量,空间中的元素q可以表示为:

q = (x,y,z,w) = w + xi +yj + zk;

也可以用实数和向量的形式进行表示,即:

q = w + v;其中w是实数部分,v是v(x,y,z)。

四元数集合是复数集合的自然扩展。四元数的乘法服从分配率,并且虚部i,j,k之间满足一下关系:

四元数式的乘法不满足交换律,因此在进行乘法运算时要注意顺序。两个四元数q1 = w1 + x1i + y1j + z1k和q2 = w2 + x2i + y2j+z2k的乘积q1q2为:

用数量-向量的形式,则q1=s1+v1和q2=s2+v2的乘积表达式为:

四元数也有共轭,比如一个四元数为 q = s+v,那么它的共轭为q’ = s-v。而qq’=||q||2 = q2.

非零的四元数的逆,记作q-1,所以。

重点来了,下面;来说一下四元数的旋转

三维空间的旋转可以理解为R3到自身的映射函数φ。由于φ代表旋转,所以它必须包含长度,角度,旋转方向等信息。

如果有则长度保持不变。

如果对任意两个点p1和p2

则从原点到两个点p1和p2的连线所形成 夹角保持不变。

如果  

则手向性也保持不变。

如果满足条件φ(s+v) = s+φ(v),则函数φ可以扩展为H到自身的映射,这样就将(4)式改写为

如果将p1和p2看做是数量部分为零的四元数,根据,就可以将(5),(6)式合并成一个等式,在该等式中可以保持角度和手向性不变,等式如下:

满足(7)是的函数φ称为是同态的。

该类函数φ可以用公式(8)表示:

其中q为一个非零的四元数,且满足,因此可以表示旋转的集合。证明过程如下:

首先证明φq的长度保持不变,因为

其次,φq是同态的,因为

四元数与旋转的关系

假设向量P绕一任意旋转轴的单位向量A(xa,ya,za)旋转θ角,如下图所示:

我们可以将P看作为没有实数部分的四元数xi+yj+zk,设q = s+v,则q-1 = s-v。

那么φq(P) = qPq-1就等于(s+v)P(s-v)。即计算过程如下所示:

由于则(11)等于:

设v = tA,则上式可以改写为:

将(13)与绕任意轴旋转的公式P’ = PcosΘ + (A x P)sinΘ + A(A.P)(1-cosΘ),可以推出

则可以得到:

带入q = s+v得到:

推广一下来讲:

对于四元数q的任意数量乘积表示的都是相同的旋转,因为:

两个四元数q1和q2的乘积也可以表示一个旋转。乘积q1q2表示现已q2,后以q1进行旋转。因为:

可以将多个四元数结合起来,形成一系列旋转的一个四元数。将两个四元数相乘需要做16次乘法和加法运算,而两个3×3矩阵相乘就需要做27次类似的操作。因此对物体进行多次旋转时,应用四元数可以获得较高的计算效率。

如何将一个四元数变换成等价的3×3旋转矩阵的形式呢?

首先将改写成矩阵的形式

将四元数q改写成四维向量q = (w,x,y,z),那么w = s,x = tAx,y = tAy,z = tAz。因为A是单位向量,所以x2+y2+z2 = t2A2 = t2

则上式等价于:

因为q是单位四元数,满足w2+ x2+y2+z2 =1,所以可以得到:

则四元数的旋转矩阵Rq的公式如下:

球型线性插值

因为四元数是用向量表示的,所以很适合做插值运算。在产生一个物体动画过程中,在产生位于两个预先计算的关键帧之间的中间过渡定位时,插值非常有用。

最简单的差值类型是线性插值。对于两个四元数q1和q2,线性插值后得到的四元数q(t)为:

当t在[0,1]范围内取值时,函数q(t)在连接q1和q2的线段上平滑变化。如下图所示:

q(t)并不保持q1和q2的单位长度,但可以使用下面的函数在任意点位置对q(t)进行重新规格化:

这样就可以用该函数描绘位于q1和q2间的过渡弧线。在上图中,它将弧描绘成四维单位超球面的二维截面。

尽管线性插值很有效,但是q(t)并没有以恒定的速率描绘q1和q2间的过渡弧线,这就是线性插值的弊端。下图关于cos-1(q(t).q1)的图形表明,q1和q2之间的角度变化速率在端点t = 0 和 t = 1时相对较慢,而在t = 1/2时最快。

我们希望找到一个函数q(t),用它对四元数q1和q2进行插值时,会保持其单位长度不变并且以恒定的速率扫过位于q1和q2之间的夹角。如果q1和q2的夹角为θ,那么这个函数将会产生一个四元数,该四元数在q(t)和q1的形成一个夹角θt,这里t在0到1之间取值。

如下图(a),(b):四元数q(t)位于连接q1和q2的弧上,与q1的形成一个夹角θt,与q2构成夹角θ(1-t)。可以将q(t)写成:

其中a(t)和b(t)分别表示q(t)在q1和q2方向上的分量的长度。

我们可以构造相似三角形来确定长度a(t),q1到以原点和q2为端点的线段的垂直距离为||q1||sinθ,而q(t)到该线段的垂直距离为||q1||sinθ(1-t)。根据相似三角形,可以得到以下关系式:

由于||q1|| = 1,||q(t)|| = 1,可以将上式化简为:

同理可以得到:

这时可以将球型线性插值函数q(t)定义为:

θ角为

因为四元数q和-q表示相同的旋转,所以在旋转四元数q1和q2的正负号时一般要满足q1.q2>=0,这样也可以保证以最短路径的方式进行插值。

3D游戏与计算机图形学中的数学方法-四元数的更多相关文章

  1. 3D游戏与计算机图形学中的数学方法-变换

    1变换 在3D游戏的整个开发过程中,通常需要以某种方式对一系列的向量进行变换.通常用到的变换包括平移,缩放和旋转. 1.1通用变换 通常可将n x n可逆矩阵M看成是一个从坐标系到另一个坐标系的变换矩 ...

  2. 3D游戏与计算机图形学中的数学方法-点线面

    <易传·系辞上传>:”易有太极,是生两仪,两仪生四象,四象生八卦.” 借用一下古代先人们的智慧引一下本文的主题-三维图形中的点线面,在三维几何中也有一句话可以和上面的话相对应:由点成线,由 ...

  3. 3D游戏与计算机图形学中的数学方法-视截体

    视截体用来表示一个空间的范围,位于这个空间范围内的三维场景的任何物体都可以被看到. 视截体由六个平面围成,其中的四个平面与场景的边界相对应,分别被称为左,右,底,顶视截面.另外两个平面称为近视截面和远 ...

  4. Mathematics for Computer Graphics数学在计算机图形学中的应用 [转]

    最近严重感觉到数学知识的不足! http://bbs.gameres.com/showthread.asp?threadid=10509 [译]Mathematics for Computer Gra ...

  5. 3D游戏开发之UE4中的集合:TSet容器

    好久没有更新了,最近一直在老家过年,网络不通的,今天才有时间更新一集. 一.TSet<T>是什么 UE4中,除了TArray动态数组外,还提供了各种各样的模板容器.这一节,我们就介绍集合容 ...

  6. 计算机图形学中使用Turbo C++画图步骤

    一.下载安装Turbo C++ 我安装的是Turbo C++ 3.2.2.0下载链接 二.画图 1.打开Turbo C++,点击右下角start turbo C++ 2.点击file ->new ...

  7. JS中的数学方法

    1 . Math.ceil()      向上取整 2.  Math.floor()     向下取整 3. Math.round()    四舍五入取整 4.  Math.random()   生成 ...

  8. Java中的数学方法

    直接用代码 public class TestNumber { public static void main(String[] args) { float f1 = 5.4f; float f2 = ...

  9. 计算机图形学学习方法和相关书籍,做游戏,GIS,虚拟现实,三维引擎的都能够看看.

    本书參照<<图形学扫盲>> 整理的,原文内容引子: http://www.cppblog.com/lai3d/archive/2008/12/30/70796.html 前言: ...

随机推荐

  1. spring中action和url的对应关系

    spring 中, action和url的对应关系             在web.xml中,这样配置:           <servlet-mapping >             ...

  2. [svc]磁盘接口与RAID

    一 磁盘接口 IDE 传统家用: /dev/hda1 SISC 传统服务器: /dev/sdb1 SATA 现在家用 SAS 现在服务器用 FC(光纤通道) 高级服务器 注意: 分区编号,1-4只能给 ...

  3. Serviceability

    http://hg.openjdk.java.net/jdk7u/jdk7u2/hotspot/file/6259c6d3bbb7/agent/doc/clhsdb.html http://blog. ...

  4. CentOS 7 开放防火墙端口 命令

    iptables防火墙 1.基本操作 # 查看防火墙状态 service iptables status   # 停止防火墙 service iptables stop   # 启动防火墙 servi ...

  5. LeetCode: Binary Tree Preorder Traversal 解题报告

    Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes' valu ...

  6. Pro mvvm读书笔记mvvm中的VM

    一.构建ViewModels 设计模式的其中一个目标就是抽象构造一个给出指定类型的对象或者实现指定类型的接口的过程.需要把类给客户端,让客户端去使用,但是要隐藏类是具体的实现细节. 1.1The Ap ...

  7. 三级级联查询省份名称和编码(保证名称不反复)的SQL语句

    三级级联查询省份名称和编码(保证名称不反复)的SQL语句 1.省份.地市和县级数据库表 2.SQL语句 SELECT DISTINCT t.`province_name`,t.`province_co ...

  8. C语言 · 明明的随机数

    算法训练 明明的随机数   时间限制:1.0s   内存限制:256.0MB      问题描述 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的 ...

  9. pthread_cond_wait()函数的详解

    http://hi.baidu.com/tjuer/item/253cc6d66b921317d90e4483 了解 pthread_cond_wait() 的作用非常重要 -- 它是 POSIX 线 ...

  10. JavaScrip——简单练习(抓错误信息,for循环,日期)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...