CSharpGL(32)矩阵与四元数与角度旋转轴的相互转换

三维世界里的旋转(rotate),可以用一个3x3的矩阵描述;可以用(旋转角度float+旋转轴vec3)描述。数学家欧拉证明了这两种形式可以相互转化,且多次地旋转可以归结为一次旋转。这实际上就是著名的轨迹球(arcball)方式操纵模型的理论基础。

本文中都设定float angleDegree为旋转角度,vec3 axis为旋转轴。

+BIT祝威+悄悄在此留下版了个权的信息说:

四元数

+BIT祝威+悄悄在此留下版了个权的信息说:

定义(angleDegree+axis到四元数)

四元数就是一个四维向量(w, x, y, z),其中w描述旋转的角度(但不是直接的angleDegree值),(x, y, z)描述旋转轴。从angleDegree和axis得到一个四元数的方式比较简单。

  1. public struct Quaternion
  2. {
  3. private float w;
  4. private float x;
  5. private float y;
  6. private float z;
  7.  
  8. /// <summary>
  9. /// Quaternion from a rotation angle and axis.
  10. /// </summary>
  11. /// <param name="angleDegree">angle in degree.</param>
  12. /// <param name="axis">rotation axis.</param>
  13. public Quaternion(float angleDegree, vec3 axis)
  14. {
  15. vec3 normalized = axis.normalize();
  16. double radian = angleDegree * Math.PI / 180.0;
  17. double halfRadian = radian / 2.0;
  18. this.w = (float)Math.Cos(halfRadian);
  19. float sin = (float)Math.Sin(halfRadian);
  20. this.x = sin * normalized.x;
  21. this.y = sin * normalized.y;
  22. this.z = sin * normalized.z;
  23. }
  24. }

先别管为什么四元数是这么定义的,只要知道这个定义就好。这里引入四元数只是为了方便提取出矩阵中蕴含的angleDegree和aixs。四元数的其他用途本文不涉及。

+BIT祝威+悄悄在此留下版了个权的信息说:

四元数到angleDegree+axis

从上面的定义可以很容易推算出四元数里蕴含的angleDegree和axis。显然得到的axis已经失去了原有的长度,但是axis的长度并不重要,保持在单位长度才是最方便的。

  1. public void Parse(out float angleDegree, out vec3 axis)
  2. {
  3. angleDegree = (float)(Math.Acos(w) * * 180.0 / Math.PI);
  4. axis = (new vec3(x, y, z)).normalize();
  5. }
+BIT祝威+悄悄在此留下版了个权的信息说:

四元数到矩阵

从四元数到矩阵的推导有点复杂,有很多相关文章,本文就只贴代码了。代码还是很简练的。

  1. /// <summary>
  2. /// Transform this quaternion to equivalent matrix.
  3. /// </summary>
  4. /// <returns></returns>
  5. public mat3 ToRotationMatrix()
  6. {
  7. vec3 col0 = new vec3(
  8. * (x * x + w * w) - ,
  9. * x * y + * w * z,
  10. * x * z - * w * y);
  11. vec3 col1 = new vec3(
  12. * x * y - * w * z,
  13. * (y * y + w * w) - ,
  14. * y * z + * w * x);
  15. vec3 col2 = new vec3(
  16. * x * z + * w * y,
  17. * y * z - * w * x,
  18. * (z * z + w * w) - );
  19.  
  20. return new mat3(col0, col1, col2);
  21. }
实际上得到的矩阵就是这样的:
+BIT祝威+悄悄在此留下版了个权的信息说:

矩阵到四元数

矩阵到四元数的推导也有点复杂,借助了一些数学技巧,本文不详述,直接贴代码。

  1. /// <summary>
  2. /// Transform this matrix to a <see cref="Quaternion"/>.
  3. /// </summary>
  4. /// <returns></returns>
  5. struct mat3
  6. {
  7. public Quaternion ToQuaternion()
  8. {
  9. // input matrix.
  10. float m11 = this.col0.x, m12 = this.col1.x, m13 = this.col2.x;
  11. float m21 = this.col0.y, m22 = this.col1.y, m23 = this.col2.y;
  12. float m31 = this.col0.z, m32 = this.col1.z, m33 = this.col2.z;
  13. // output quaternion
  14. float x = , y = , z = , w = ;
  15. // detect biggest in w, x, y, z.
  16. float fourWSquaredMinus1 = +m11 + m22 + m33;
  17. float fourXSquaredMinus1 = +m11 - m22 - m33;
  18. float fourYSquaredMinus1 = -m11 + m22 - m33;
  19. float fourZSquaredMinus1 = -m11 - m22 + m33;
  20. int biggestIndex = ;
  21. float biggest = fourWSquaredMinus1;
  22. if (fourXSquaredMinus1 > biggest)
  23. {
  24. biggest = fourXSquaredMinus1;
  25. biggestIndex = ;
  26. }
  27. if (fourYSquaredMinus1 > biggest)
  28. {
  29. biggest = fourYSquaredMinus1;
  30. biggestIndex = ;
  31. }
  32. if (fourZSquaredMinus1 > biggest)
  33. {
  34. biggest = fourZSquaredMinus1;
  35. biggestIndex = ;
  36. }
  37. // sqrt and division
  38. float biggestVal = (float)(Math.Sqrt(biggest + ) * 0.5);
  39. float mult = 0.25f / biggestVal;
  40. // get output
  41. switch (biggestIndex)
  42. {
  43. case :
  44. w = biggestVal;
  45. x = (m23 - m32) * mult;
  46. y = (m31 - m13) * mult;
  47. z = (m12 - m21) * mult;
  48. break;
  49.  
  50. case :
  51. x = biggestVal;
  52. w = (m23 - m32) * mult;
  53. y = (m12 + m21) * mult;
  54. z = (m31 + m13) * mult;
  55. break;
  56.  
  57. case :
  58. y = biggestVal;
  59. w = (m31 - m13) * mult;
  60. x = (m12 + m21) * mult;
  61. z = (m23 + m32) * mult;
  62. break;
  63.  
  64. case :
  65. z = biggestVal;
  66. w = (m12 - m21) * mult;
  67. x = (m31 + m13) * mult;
  68. y = (m23 + m32) * mult;
  69. break;
  70.  
  71. default:
  72. break;
  73. }
  74.  
  75. return new Quaternion(w, -x, -y, -z);
  76. }
  77. }

matrix to quaternion

好了,现在矩阵 ⇋ 四元数 ⇋ (angleDegree+axis)之间的转换就全有了。

BTW,OpenGL里的glRotate{fd}(angle, axis)里的angle是以角度为单位的。为了统一,我将CSharpGL里的所有angle都设定为以角度为单位了。

+BIT祝威+悄悄在此留下版了个权的信息说:

下载

CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入(https://github.com/bitzhuwei/CSharpGL

+BIT祝威+悄悄在此留下版了个权的信息说:

总结

现在解决了矩阵与(angleDegree+axis)之间的转换问题,就可以从容地解析轨迹球算出的旋转矩阵,抽取出里面蕴含的(angleDegree+axis)了。这就可以单独更新模型的旋转角度和旋转轴,避免了对整个模型矩阵的破坏。

CSharpGL(32)矩阵与四元数与角度旋转轴的相互转换的更多相关文章

  1. 从矩阵(matrix)角度讨论PCA(Principal Component Analysis 主成分分析)、SVD(Singular Value Decomposition 奇异值分解)相关原理

    0. 引言 本文主要的目的在于讨论PAC降维和SVD特征提取原理,围绕这一主题,在文章的开头从涉及的相关矩阵原理切入,逐步深入讨论,希望能够学习这一领域问题的读者朋友有帮助. 这里推荐Mit的Gilb ...

  2. Matrix4x4矩阵变换、欧拉角转四元数、角度转弧度

    Matrix4x4 // 重置矩阵 ][]) { m[][] = ; m[][] = ; m[][] = ; m[][] = ; m[][] = ; m[][] = ; m[][] = ; m[][] ...

  3. BIT祝威博客汇总(Blog Index)

    +BIT祝威+悄悄在此留下版了个权的信息说: 关于硬件(Hardware) <穿越计算机的迷雾>笔记 继电器是如何成为CPU的(1) 继电器是如何成为CPU的(2) 关于操作系统(Oper ...

  4. Unity手游之路<四>3d旋转-四元数,欧拉角和变幻矩阵

    http://blog.csdn.net/janeky/article/details/17272625 今天我们来谈谈关于Unity中的旋转.主要有三种方式.变换矩阵,四元数和欧拉角. 定义 变换矩 ...

  5. opengl矩阵向量

    如何创建一个物体.着色.加入纹理,给它们一些细节的表现,但因为它们都还是静态的物体,仍是不够有趣.我们可以尝试着在每一帧改变物体的顶点并且重配置缓冲区从而使它们移动,但这太繁琐了,而且会消耗很多的处理 ...

  6. 四元数(Quaternions)简介

    经常在代码中看到Quaternions,也知道它是用来表达三维空间的旋转的,但一直没有更深的理解.这两天终于花点时间看了看维基百科的介绍,算是多了解了点.做个记录吧! 本质上而言,四元数是一个数学概念 ...

  7. 四元数与欧拉角(RPY角)的相互转换

    RPY角与Z-Y-X欧拉角 描述坐标系{B}相对于参考坐标系{A}的姿态有两种方式.第一种是绕固定(参考)坐标轴旋转:假设开始两个坐标系重合,先将{B}绕{A}的X轴旋转$\gamma$,然后绕{A} ...

  8. 【转载】Unity中矩阵的平移、旋转、缩放

    By:克森 简介 在这篇文章中,我们将会学到几个概念:平移矩阵.旋转矩阵.缩放矩阵.在学这几个基本概念的同时,我们会用到 Mesh(网格).数学运算.4x4矩阵的一些简单的操作.但由于克森也是新手,文 ...

  9. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十二章:四元数(QUATERNIONS)

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十二章:四元数(QUATERNIONS) 学习目标 回顾复数,以及 ...

随机推荐

  1. 纯CSS3实现的一些酷炫效果

    之前在网上看到一些用纯CSS3实现的酷炫效果,以为实现起来比较困难,于是想看看具体是怎么实现的. 一.笑脸猫动画 实现效果如下: 这个实现起来确实比较麻烦,很多地方需要花时间,有耐心地调整. 1.先看 ...

  2. 【疯狂造轮子-iOS】JSON转Model系列之一

    [疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ...

  3. Linux虚拟机的安装(使用Centos6.3)

    1.什么是虚拟机? 虚拟机指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统 2.安装Linux虚拟机前要做的准备 2.1:一台windows环境的pc 2.2:下载VM ...

  4. Python标准模块--ContextManager

    1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就是允许你可以自动地开始和结束一些事情. ...

  5. EntityFramework之DetectChanges's Secrets(三)(我为EF正名)

    前言 对于应用程序开发者来说,通常不需要考虑太多对于Entity Framework中的变更追踪(change tracking),但是变更追踪和DetectChanges方法是栈的一部分,在这其中, ...

  6. Hawk 4.4 执行器

    执行器是负责将Hawk的结果传送到外部环境的工具.你可以写入数据表,数据库,甚至执行某个特定的动作,或是生成文件等等. 在调试模式下,执行器都是不工作的.这是为了避免产生副作用.否则,每刷新一遍数据, ...

  7. [.NET] C# 知识回顾 - 委托 delegate (续)

    C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...

  8. Xamarin与Visual stuido2015离线安装包分享

    最近看见大伙留言才知道国内安装Xamarin开发原来这么艰辛啊! 第一:网速不快 第二:Android SDK下载受限 等等... 鉴于这些原因,特写下这篇文章以及分享打包好的离线包以帮助大家尽快体验 ...

  9. 在开启DRS的集群中修复VMware虚拟主机启动问题

    通过iSCSI方式连接到ESXi主机上的外挂存储意外失联了一段时间,导致部分虚拟主机在集群中呈现出孤立的状态,单独登陆到每台ESXi上可以看到这些虚拟主机都变成了unknow状态.因为有过上一次(VM ...

  10. 【HanLP】HanLP中文自然语言处理工具实例演练

    HanLP中文自然语言处理工具实例演练 作者:白宁超 2016年11月25日13:45:13 摘要:HanLP是hankcs个人完成一系列模型与算法组成的Java工具包,目标是普及自然语言处理在生产环 ...