3D游戏与计算机图形学中的数学方法-四元数
说实话关于四元数这一节真的是不好懂,因为里面涉及到好多数学知识,单说推出来的公式就有很多。不怕大家笑话,对于四元数的学习我足足花了两天的时间,包括整理出这篇文章。在前面一章我写到了“变换”,这也是总结的学习笔记。我发现,写博客真是的是一个好多学习方法,加上之前一个博士师兄告诉我,要想好好的学习一本书或者一门技术,那么以此将学习笔记或者经验写成博客专栏是一种有效的方法。现在我要坚持这种方式,给自己留下学习过程中的足迹,也给大家分享一下。欢迎大家指出其中的不足,谢谢!
四元数是表示旋转的另一种数学形式,使用四元数可以节省存储空间,其之间的连接运算需要的算术运算更少,在产生平滑的三维动画时,用四元数更容易进行修改。
四元数集合,在数学上被称为哈密顿四元数环(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游戏与计算机图形学中的数学方法-四元数的更多相关文章
- 3D游戏与计算机图形学中的数学方法-变换
1变换 在3D游戏的整个开发过程中,通常需要以某种方式对一系列的向量进行变换.通常用到的变换包括平移,缩放和旋转. 1.1通用变换 通常可将n x n可逆矩阵M看成是一个从坐标系到另一个坐标系的变换矩 ...
- 3D游戏与计算机图形学中的数学方法-点线面
<易传·系辞上传>:”易有太极,是生两仪,两仪生四象,四象生八卦.” 借用一下古代先人们的智慧引一下本文的主题-三维图形中的点线面,在三维几何中也有一句话可以和上面的话相对应:由点成线,由 ...
- 3D游戏与计算机图形学中的数学方法-视截体
视截体用来表示一个空间的范围,位于这个空间范围内的三维场景的任何物体都可以被看到. 视截体由六个平面围成,其中的四个平面与场景的边界相对应,分别被称为左,右,底,顶视截面.另外两个平面称为近视截面和远 ...
- Mathematics for Computer Graphics数学在计算机图形学中的应用 [转]
最近严重感觉到数学知识的不足! http://bbs.gameres.com/showthread.asp?threadid=10509 [译]Mathematics for Computer Gra ...
- 3D游戏开发之UE4中的集合:TSet容器
好久没有更新了,最近一直在老家过年,网络不通的,今天才有时间更新一集. 一.TSet<T>是什么 UE4中,除了TArray动态数组外,还提供了各种各样的模板容器.这一节,我们就介绍集合容 ...
- 计算机图形学中使用Turbo C++画图步骤
一.下载安装Turbo C++ 我安装的是Turbo C++ 3.2.2.0下载链接 二.画图 1.打开Turbo C++,点击右下角start turbo C++ 2.点击file ->new ...
- JS中的数学方法
1 . Math.ceil() 向上取整 2. Math.floor() 向下取整 3. Math.round() 四舍五入取整 4. Math.random() 生成 ...
- Java中的数学方法
直接用代码 public class TestNumber { public static void main(String[] args) { float f1 = 5.4f; float f2 = ...
- 计算机图形学学习方法和相关书籍,做游戏,GIS,虚拟现实,三维引擎的都能够看看.
本书參照<<图形学扫盲>> 整理的,原文内容引子: http://www.cppblog.com/lai3d/archive/2008/12/30/70796.html 前言: ...
随机推荐
- Android利用Fiddler进行网络数据抓包【怎么跟踪微信请求】
主要介绍Android及IPhone手机上如何利用Fiddler进行网络数据抓包,比如我们想抓某个应用(微博.微信.墨迹天气)的网络通信请求就可以利用这个方法. Mac 下请使用 Charles 代替 ...
- Oracle学习笔记之一,重温范式
第一范式(1NF) 第一范式是第二和第三范式的基础,是最基本的范式.第一范式包括下列的指导原则: 数据组的每个属性只可以包含一个值. 关系中的每个数组必须只包含相同数量的值. 关系中的每个数组一定不能 ...
- perl的匿名引用
perl中列表不能嵌套,只能通过引用的方式构建复杂的结构.引用其实就是c中的指针,只不过perl中对指针,也就是一个地址的声明和取值有自己的一套方法. 1.先复习普通标量的引用方法: [vagrant ...
- [na][tools]快速ping网段工具-QuickPing
一款神器 quickping 能够很快的探测出该网断分出去哪些地址. 在线的会显示绿色 在线的+有主机名的显示为亮绿色
- Fragment里面的ListView的item点击没反应
近期做一个消息列表,发现fragment的listview载入消息出来后,每条消息都点击不了.经过询问和查下已解决 开发中非经常见的一个问题,项目中的listview不不过简单的文字,经常须要自定义l ...
- VS2012 WIN7下使用DotNetBar 使用Office2007Form皮肤 窗体运行不显示问题解决方法
在窗体属性中有个EnableGlass属性,设置为False即可.
- 在Ubuntu环境中qemu-kvm网桥的配置
在文件/etc/network/interfaces中添加以下内容 auto lo iface lo inet loopback #auto eth0 #iface eth0 inet manual ...
- 四、用“”或构造函数创建Java的String区别
在Java中,一个字符串可以通过下面两种方法创建. String x = "abc"; String y = new String("abc"); 用双引号创建 ...
- SpringKafka消费端配置类ConsumerConfig.java源码
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. ...
- LINQ架构简单描述
写在前面的话:课堂上老师只是简单提了一下LINQ,当时听着老师对它的描述,感觉非常神奇,不用去操作繁琐的SQL语句了,读取数据库的操作居然能向写C#代码一样方便,但是一直没有机会去学习使用它. LIN ...