[百度空间] [转] 四元数(Quaternions)

转:四元数(Quaternions)

好吧,我必须承认到目前为止我还没有完全理解四元数,我一度把四元数理解为轴、角表示的4维向量,也就在下午我才从和同事的争辩中理解了四元数不完全是角、轴这么简单,为此写点心得给那些同我一样搞了2年3D游戏的还不清楚四元数的朋友。

为什么使用四元数

为了回答这个问题,先来看看一般关于旋转(面向)的描述方法-欧拉描述法。它使用最简单的x,y,z值来分别表示在x,y,z轴上的旋转角度,其取值为0-360(或者0-2pi),一般使用roll,pitch,yaw来表示这些分量的旋转值。需要注意的是,这里的旋转是针对世界坐标系说的,这意味着第一次的旋转不会影响第二、三次的转轴,简单的说,三角度系统无法表现任意轴的旋转,只要一开始旋转,物体本身就失去了任意轴的自主性,这也就导致了万向轴锁(Gimbal Lock)的问题。

还有一种是轴角的描述方法(即我一直以为的四元数的表示法),这种方法比欧拉描述要好,它避免了Gimbal Lock,它使用一个3维向量表示转轴和一个角度分量表示绕此转轴的旋转角度,即(x,y,z,angle),一般表示为(x,y,z,w)或者(v,w)。但这种描述法却不适合插值。

那到底什么是Gimbal Lock呢?正如前面所说,因为欧拉描述中针对x,y,z的旋转描述是世界坐标系下的值,所以当任意一轴旋转90°的时候会导致该轴同其他轴重合,此时旋转被重合的轴可能没有任何效果,这就是Gimbal Lock,这里有个例子演示了Gimbal Lock,点击这里下载。运行这个例子,使用左右箭头改变yaw为90°,此时不管是使用上下箭头还是Insert、Page Up键都无法改变Pitch,而都是改变了模型的roll。

那么轴、角的描述方法又有什么问题呢?虽然轴、角的描述解决了Gimbal Lock,但这样的描述方法会导致差值不平滑,差值结果可能跳跃,欧拉描述同样有这样的问题。

什么是四元数

四元数一般定义如下:

q=w+xi+yj+zk

其中w是实数,x,y,z是虚数,其中:

i*i=-1

j*j=-1

k*k=-1

也可以表示为:

q=[w,v]

其中v=(x,y,z)是矢量,w是标量,虽然v是矢量,但不能简单的理解为3D空间的矢量,它是4维空间中的的矢量,也是非常不容易想像的。

四元数也是可以归一化的,并且只有单位化的四元数才用来描述旋转(面向),四元数的单位化与Vector类似,

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

因为w2 + x2 + y2 + z2=1

所以Normlize(q)=q/Norm(q)=q / sqrt(w2 + x2 + y2 + z2)

说了这么多,那么四元数与旋转到底有什么关系?我以前一直认为轴、角的描述就是四元数,如果是那样其与旋转的关系也不言而喻,但并不是这么简单,轴、角描述到四元数的转化:

w    =    cos(theta/2)

x    =    ax * sin(theta/2)

y    =    ay * sin(theta/2)

z    =    az * sin(theta/2)

其中(ax,ay,az)表示轴的矢量,theta表示绕此轴的旋转角度,为什么是这样?和轴、角描述到底有什么不同?这是因为轴角描述的“四元组”并不是一个空间下的东西,首先(ax,ay,az)是一个3维坐标下的矢量,而theta则是级坐标下的角度,简单的将他们组合到一起并不能保证他们插值结果的稳定性,因为他们无法归一化,所以不能保证最终插值后得到的矢量长度(经过旋转变换后两点之间的距离)相等,而四元数在是在一个统一的4维空间中,方便归一化来插值,又能方便的得到轴、角这样用于3D图像的信息数据,所以用四元数再合适不过了。

关于四元数的运算法则和推导这里有篇详细的文章介绍,重要的是一点,类似与Matrix的四元数的乘法是不可交换的,四元数的乘法的意义也类似于Matrix的乘法-可以将两个旋转合并,例如:

Q=Q1*Q2

表示Q的是先做Q2的旋转,再做Q1的旋转的结果,而多个四元数的旋转也是可以合并的,根据四元数乘法的定义,可以算出两个四元数做一次乘法需要16次乘法和加法,而3x3的矩阵则需要27运算,所以当有多次旋转操作时,使用四元数可以获得更高的计算效率。

为什么四元数可以避免Gimbal Lock

在欧拉描述中,之所以会产生Gimbal Lock是因为使用的三角度系统是依次、顺序变换的,如果在OGL中,代码可能这样:

glRotatef( angleX, 1, 0, 0)

glRotatef( angleY, 0, 1, 0)

glRotatef( angleZ, 0, 0, 1)

注意:以上代码是顺序执行,而使用的又是统一的世界坐标,这样当首先旋转了Y轴后,Z轴将不再是原来的Z轴,而可能变成X轴,这样针对Z的变化可能失效。

而四元数描述的旋转代码可能是这样:

TempQ = From Eula(x,y,z)

FinalQ =CameraQ * NewQ

theta, ax, ay, az = From (FinalQ)

glRotatef(theta, ax, ay, az);

其中(ax,ay,az)描述一条任意轴,theta描述了绕此任意轴旋转的角度,而所有的参数都来自于所有描述旋转的四元数做乘法之后得到的值,可以看出这样一次性的旋转不会带来问题。这里有个例子演示了使用四元数不会产生Gimbal Lock的问题。

关于插值

使用四元数的原因就是在于它非常适合插值,这是因为他是一个可以规格化的4维向量,最简单的插值算法就是线性插值,公式如:

q(t)=(1-t)q1+t q2

但这个结果是需要规格化的,否则q(t)的单位长度会发生变化,所以

q(t)=(1-t)q1+t q2 / || (1-t)q1+t q2 ||

如图:

尽管线性插值很有效,但不能以恒定的速率描述q1到q2之间的曲线,这也是其弊端,我们需要找到一种插值方法使得q1->q(t)之间的夹角θ是线性的,即θ(t)=(1-t)θ1+t*θ2,这样我们得到了球形线性插值函数q(t),如下:

q(t)=q1 * sinθ(1-t)/sinθ + q2 * sinθt/sineθ

如果使用D3D,可以直接使用D3DXQuaternionSlerp函数就可以完成这个插值过程。

时间: 2024-10-24 17:18:34

[百度空间] [转] 四元数(Quaternions)的相关文章

百度空间代码大全

display:nonecss全能隐藏代码 背景{}中添加background: url(图片地址)repeat注:repeat 背景图像在纵向和横向上平铺no-repeat 背景图像不平铺repeat-x 背景图像在横向上平铺repeat-y 背景图像在纵向平铺 line-height: 25.2px;">超链接自定义设置超链接的属性就是在相关栏目名称后面+上a{}的属性 color:#颜色代码或颜色英文名称 定义超链接字体的颜色font-family:字体名称 定义超链接字体font-

Eclipse启动之四 : Eclipse核心框架启动(百度空间迁移)

框架启动位于org.eclipse.osgi_<version>插件中,入口为org.eclipse.core.runtime.adaptor.EclipseStarter.run(String[] args, Runnable endSplashHandler) 其中最主要的方法是Startup方法,其主要功能: 1.初始化框架属性信息     FrameworkProperties 2.处理命令行参数 3.初始化LocationManager 4.加载config.ini中配置信息 5.创

Eclipse启动之二:Eclipse动态库(百度空间迁移)

动态库中的主要实现文件是:eclipse.c 其主要功能定位启动Java虚拟机和显示Splash窗口(暂未用,通过在org.eclipse.equinox.launcher.Main中调用来显示) java虚拟机定位算法: 1.从-vm参数所指定的文件或目录中查找 2.如果没有指定-vm参数,程序会寻找Eclipse自带的JRE,它会在当前目录中查找jre\bin\javaw.exe 3.按照系统的环境变量指定的路径去查找javaw.exe 其中,通过-vm参数指定虚拟机位置可以有多种选择: 1

Eclipse启动之三 : 启动器插件(百度空间迁移)

Eclipse启动之三启动器插件 空间 启动插件名为org.eclipse.equinox.launcher.<version>,入口类org.eclipse.core.launcher.main.它是Eclipse虚拟机启动的最早的插件 main整体流程: 1.处理命令行参数 2.设置虚拟机属性 3.处理配置 4.获取安装路径 5.获取启动路径 6.加载JNI动态库 7.设置安全属性 8.处理闪屏 9.启动Eclipse核心框架 1.处理命令行参数           解析命令行参数 -sh

“百度空间关闭”后的问题解决攻略

4月7日消息,运营八年的百度空间今日宣布关闭,百度空间的内容将于5月7日正式迁移到百度云. 公告显示,从今年4月21日起,百度空间停止编撰更新博文,博文内容迁移后只对自己可见. 针对百度空间关闭的问题,多备份为您提供完整的解决攻略. 第一步:根据自身情况寻找一个主机商,购买虚拟主机; 第二步:进入多备份,联系客服索取博客快速建站脚本; 第三步:将快速建站脚本上传到虚拟主机的FTP中,然后用域名访问该文件,选择个人喜欢的博客程序,下载解压,然后访问域名安装.安装完成即可实现自建博客; 第四步:自建

转自 x_x的百度空间

空华人生         by 淡漠的心情 昨天,又昨天. 今天,又今天. 明天,又明天. 日历渐渐稀薄,忽然发现,那是时间的痕迹. 似乎,总是在麻木的等待. 何时,才能历尽. 再算算,我又还有多少天能够挥霍. 上天,又还会给我多少天. 人生短暂. 日子,总有过完的一天. 而我,又能做些什么. 发呆?叹气?还是努力?深思着...... 或许,这些事.不该我烦吧.若烦,是自寻烦丝. 记得有句话说:要顺其自然,开心点. 呵,是这样吗? 仔细想想,又不对. 有些人,庸碌一生.满头白发后,再唏嘘的向后人

写给急功过利的百度:从此放弃百度空间

从n年前,以为百度是咱们民族互联网行业的象征之一,赚了很多钱,但不以赚钱为目的,在赚到钱的同时,会向中国广大的IT提供一些免费而稳定的辅助服务. 后来,百度推出的每项公众服务我都有关注到,如:百度空间,百度问答,百度贴吧,百度影音,电子商务站,云盘等等.有多少次都是风声大,雨点小,最后在自己小小的生态圈里折腾来折腾去.只要不赚钱就会很快萎缩或关闭,要不就是安全不顾忌用户体验,强行作大改,改到一半不了了之. 我从2008年初把自己的一些文字写到了当时新开不久的百度空间里,当时觉得:第一,她是免费的

再见-百度空间

头一段时间就知道百度空间要关闭了,但是还能打开,现在已经真的不能用了!陪伴了我四年的百度空间也总算是走到了尽头,有伤感,有惆怅,有不舍,更有无奈! 还记得当时在上面更新ACM时的激情和疯狂,青春的脚印和奋斗气息在上面展现的淋漓尽致.还记得当时以题会友,结交了好多ACM爱好者,时光荏苒,现在的自己早已被岁月磨平了棱角,一些年少轻狂的豪情壮志只能随着百度空间一样深深的埋在心里了! 再见,百度空间! 再见,年少轻狂的自己! 再见,青春!

Android手机无法访问百度空间的解决办法

本文网址:http://www.cnblogs.com/tunnel213/p/4301165.html 现象: 百度“JavaScript函数高级”后找到一篇文章,百度空间的,无法查看: 配置: 三星I929, Android 4.0, UC浏览器 诊断过程: 1.使用UC浏览其他网页正常,说明网络.手机.浏览器均正常: 2.使用UC的“网络诊断”功能,显示访问网站失败!然而使用其它手机可查看该网页,说明不是网站的原因! 3.百度后,初步认猜测可能是hosts文件的导致的! 解决: 1.已经r