孔雀开发小屋

专注并致力于手机客户端开发
<2011年1月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
303112345

统计

  • 随笔 - 103
  • 文章 - 0
  • 评论 - 251
  • 引用 - 0

常用链接

留言簿(38)

随笔分类

随笔档案

关注的博客

朋友的博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜

四元数概念及其应用
学习3D编程,四元数是不得不学的。其概念的引入和定义都比较抽象,今学了,总结归纳如下:

介绍四元数之前,先做如下约定:

1.采用右手坐标系(OpenGL)

2.旋转次序:x->y->z

3.  矩阵是列优先存储


1.
什么是四元数?

直接用数学上的定义来解释,因为我很难在现实生活中找到可以描述明白的例子。

 

i, j, k 为虚数

Q = w + xi + yj + zk

其中w是实数,而x,y,z为复数。

另外一种常见的表达方式是:

Q = [w, v]

其中v=(x,y,z)称为矢量部(虽然称为矢量,但是这个不是三维空间中的矢量,而是四维空间的,想象吧L),w称为标量部。


2.
四元数可以做什么?

有了四元数的概念还不行,四元数可以干什么?四元数可以用来描述方向。

先来看下如何求取四元数的长度:

||q|| = Norm(q) = sqrt(w2 + x2 + y2 + z2)

单位长度的四元数有以下属性:

w2 + x2 + y2 + z2 = 1

所以我们使用如下方法来标准化(Normalize)一个四元数:

q = q / ||q|| = q / sqrt(w2 + x2 + y2 + z2)

 

使用一个单位四元数来描述方向,请记住必须是单位四元数才可以描述方向。


3.
四元数的乘法

因为一个单位四元数可以代表一个三维空间中的方向,那么两个四元数相乘得到的结果仍然是一个四元数,这个四元素依旧可以标识一个方向。

 

给定两个四元数:

Q1 = (w1, x1, y1, z1)

Q2 = (w2, x2, y2, z2)

 

Q1 * Q2 = (w1.w2 – v1.v2, w1.v2 + w2.v1 + v1 x v2)

注意:.代表向量间的点积,x代表叉积。v1=(x1, y1, z1)  v2=(x2, y2, z2)

 

优化一下:

w=w1w2 - x1x2 - y1y2 - z1z2
x = w1x2 + x1w2 + y1z2 - z1y2
y = w1y2 + y1w2 + z1x2 - x1z2
z = w1z2 + z1w2 + x1y2 - y1x2

 

4.四元数的转换

       为什么要转换,因为我们还不能直接使用四元数来进行3D物体的旋转。在OpenGL中和Direct3D中都是通过矩阵来描述3D旋转的。


4.1 四元数到矩阵的转换

 

使用单位四元数转换到矩阵:

Matrix = [ 1 - 2y2 - 2z2   2xy - 2wz      2xz + 2wy
             2xy + 2wz      1 - 2x2 - 2z2   2yz - 2wx
             2xz - 2wy      2yz + 2wx      1 - 2x2 - 2y2 ]

 

4.2 四元数到轴角的转换

轴角也是一种表达空间旋转的方式。

如果旋转轴是:(ax, ay, az)

旋转角度是:angle (单位:弧度)

那么四元数与轴角之间的转换关系如下:

 

angle = 2 * acos(w)

ax = x / scale

ay = y / scale

az = y / scale

其中scale = sqrt(x2 + y2 + z2)


  4.3
轴角到四元数的转换

假设旋转轴是(ax, ay, az),记得必须是一个单位向量。

旋转角度是theta. (单位:弧度)

那么转换如下:

w = cos(theta / 2 )

x = ax * sin(theta / 2)

y = ay * sin(theta / 2)

z = az * sin(theta / 2 )


  4.4
欧拉角到四元数的转换

如果你的欧拉角为(a, b, c)那么就可以形成三个独立的四元数,如下:

 

Qx = [ cos(a/2), (sin(a/2), 0, 0)]
Qy = [ cos(b/2), (0, sin(b/2), 0)]
Qz = [ cos(c/2), (0, 0, sin(c/2))]


最终的四元数是Qx * Qy * Qz的乘积的结果。

 

 
5.
使用四元数来避免Gimbal Lock

 

基本思路如下:

1)  使用一个四元数来标识一个方向

2)  创建一个临时的四元数来标识当前方向到新方向的变化

3)  右乘临时的四元数和初始四元数,结果是一个合并了两个四元数的新的四元数

4)  将四元数转换成矩阵


6.
更深入的学习四元数

SLERP:球状线性插值对于三位模型进行动画处理非常有用,因为这种方式在模型的各种方向之间提供了平滑的转换。



posted on 2010-08-18 14:01 孔雀 阅读(5740) 评论(1)  编辑 收藏 引用 所属分类: Graphics

评论

# re: 四元数概念及其应用 2010-08-19 22:08 普派

球状线性插值对于三位模型进行动画处理非常有用,因为这种方式在模型的各种方向之间提供了平滑的转换。
  回复  更多评论    

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理