3D Math Keynote 2

1、方向(diretion),指的是前方朝向。方位(orientation),指的是head、pitch、roll。

    

2、欧拉角的缺点:

  1)给定方位的表达式不惟一。

    例如,pitch 135 = heading180 + pitch 45 + bank 180。

    通过将 heading、bank 限制在 +180~-180度,pitch限制在+90~-90度即可解决不惟一的问题。

  2)两个角度间插值非常困难。

3、复数的共轭

  

  复数的模。

    

4、复数集存在于一个2D平面上,可以认为这个平面有2个轴:实轴、虚轴。

    

  四元数有3个虚部,i、j、k。

    

  绕向量 n 旋转 0 度的四元数:

    

  q与-q代表的实际角位移是相同的,将0 加上360度,不会改变q的角位移,但q的四个分量都变负了。所以任意角位移有2种四元数的表示法。

  四元数也有模。

    

5、四元数的共轭:

    

  四元数的逆:

    

  当 |q| 为1时,四元数的共轭,就是四元数的逆。

  单位四元数:[1, 0]

  四元数逆意味着向相反的方向旋转相同的角度。

6、四元数乘法。

  

  四元数乘法满足结合律,不满足交换律。

  四元数叉乘的模等于模的积:

  

  

  四元数逆的性质:

  

7、四元数旋转公式:

  

  下例,先执行a旋转,再执行b旋转:

    

8、四元数点乘。结果是一个标量。

  

9、四元数的对数。引入变量 alpha = 0/2

  

  指数公式为:

    

9.1、四元数求幂。我们看看它的数学定义。
  

  结合9中的公式,上式可以推导为 exp(t[0 alpha*n]),也就是 q^t次方,其实是 alpha 乘以了t。所以q^t实际上是 [cos(t*alpha) n.sin(t*alpha)]。

  下述代码使用上述原理,计算四元数 q 的 t 次方的值。原理是让角度 alpha * t。

  

  上面的 if 是用于避免单位四元数[1 0]的情况,单位四元数放大 t 倍,还是单位四元数。

10、slerp 避免了欧拉角插值的所有问题。四元数插值的理论:

  

  

  旋转插值图解:

    

  

  由相似三角形原理,可以求出 k0、k1。

  

    

  所以 V(t) 可以表示为:

    

  扩展到四元数即为:

    

  slerp 的完整代码如下:

    

    

  上述实现用了一个书上未证明的公式,四元数的点乘等于夹角的 cos。

    

11、squard 是四元数的样条插值。需要引入控制点:

  

  可以看到,Si的计算需要引用 qi-1、qi、qi+1。所以在计算转变时,实际需要四个 q点。

  

  样条插值轨迹为:

  

12、从欧拉角到矩阵。

  从惯性坐标系到物体坐标系非常容易,将3个轴轴的旋转矩阵相乘即可。
  

  而从物体坐标系到惯性坐标系,取上面矩阵的转置矩阵即可。

  

  

13、从矩阵到欧拉角

  

  

  上面求解出了 pitch,也就推出了 cosp 的值。从而根据 m13、m33 可以推出 sinh、cosh 的的值,然后使用 atan2 即可计算出 h。

    

  用同样的方式,可以用m21、m22解得 bank。

    

  若 cosp 为0,则可推出 p 是+/- 90,b 为0。从而可以使用下面的值化简公式:

      

  通过 m11、m31 可计算出h。

14、实现从矩阵解出欧拉角的算法。

// 设矩阵保存在下面这些变量中
float m11, m12, m13;
float m21,m22,m23;
float m31,m32,m33; // 以弧度形式计算欧拉角并存在以下变量中
float h,p,b; // 从m23计算pitch, 小心 asin() 的域错误,因浮点计算我们允许一定的误差
float sp = -m23;
if (sp <= -1.0f){
p = -1.570796f; // -pi/2
}else if (sp >= 1.0){
p = 1.570796; // pi/2
} else {
p = asign(sp);
} // 检查万象锁的情况,允许一些误差
if (sp > 0.9999f){
// 向正上或正下看
// 将 bank 置零,赋值给 heading
b = 0.0f;
h = atan2(-m32, m11);
} else {
// 通过 m12 和 m33 计算heading
h = atan2(m12, m33);
b = atan2(m21, m22);
}

15、从四元数转换到矩阵。

  绕任意轴的旋转矩阵:

    

  绕任意轴旋转的四元数:

  

  我们需要把每一个m推导成为 w,x,y,z 的形式,以m11为例。

  

  使用 cos 倍角公式:

    

  最后展开化简可得:

    

  其他m求法的就不举例了,是类似的方法。下面是最终答案,从四元数构造出的完整旋转矩阵:

    

  

16、从矩阵转换到四元数。

  从直接利用公式 10.23,首先检查对角线元素。

    

  可以用有类似的方法求得其他三个元素:

    

  因为平方根的结果总是正。另一个技术是检查对称位置上的元素和。

    

  首先用第一种方法计算出 w,x,y,z 其中一个的值,然后再用第二种方法,得出另外三个数值的值,即可避免所有元素均为正的问题。
    

  下面是算法实现:

// 输入矩阵
float m11, m12, m13;
float m21, m22, m23;
float m31, m32, m33; // 输出四元数
float w, x, y, z; // 探测 w, x, y, z 中的最大绝对值
float fourWSquaredMinus1 = m11 + m22 +m33;
float fourXSquaredMinus1 = m11 - m22 - m33;
float fourYSquaredMinus1 = m22-m11-m33;
float fourZSquaredMinus1 = m33 - m11 -m33; int biggestIndex = ;
float fourBiggestSquaredMinus1 = fourWSquaredMinus1; if (fourXSquaredMinus1 > fourBiggestSquaredMinus1){
fourBiggestSquaredMinus1 = fourXSquaredMinus1;
biggestIndex = ;
} if (fourYSquaredMinus1 > fourBiggestSquaredMinus1){
fourBiggestSquaredMinus1 = fourYSquaredMinus1;
biggestIndex = ;
} if (fourZSquaredMinus1 > fourBiggestSquaredMinus1){
fourBiggestSquaredMinus1 = fourZSquaredMinus1;
biggestIndex = ;
} // 计算平方根和除法
float biggestVal = sqrt(fourBiggestSquaredMinus1 + 1.0f) * 0.5f;
float mult = 0.25f / biggestVal; // 计算四元数的值
switch(biggestIndex){
case :
w = biggestVal;
x = (m23-m32)*mult;
y = (m31-m13)*mult;
z = (m12 - m21) * mult;
break;
case :
x = biggestVal;
w = (m23-m32)*mult;
y = (m12+m21)*mult;
z = (m31+m12)*mult;
break;
case :
y = biggestVal;
w = (m31 - m13) * mult;
x = (m12 + m21) * mult;
z = (m23 + m32) * mult;
break;
case :
z = biggestVal;
w = (m12 - m21) * mult;
x = (m31 + m13) * mult;
y = (m23 + m32) * mult;
break;
}

17、从欧拉角转换到四元数。

  先将三个轴的旋转分别转换为四元数,再将这三个四元数连接成一个四元数。下面是分别旋转的四元数:

    

  将其连接起来即可得到结果。

    

18、从四元转换到欧拉角

  我们已经知道从四元数到矩阵,也知道从矩阵到欧拉角。下面是从矩阵求欧拉角:

  

  再下面是四元数求矩阵:

  

  将图一中的 m 全部替换为 wxyz,即可得四元数到欧拉角的推导公式。

  

// 使用全局变量保存输入输出
float w,x,y,z;
float h,p,b; // 计算 si(pitch)
float sp = -2.0f * (y*z + w*x); // 检查万向锁,允许有一定误差
if (fabs(sp)>0.9999f){
// 向正上或正下看
p = 1.570796f * sp;
// 计算 heading, bank 置零
h = atan2(-x*z - w*y, 0.5f - y*y - z*z);
b = 0.0f;
}else{
// 计算角度
p = asin(sp);
h = atan2(x*z - w*y, 0.5f - x*x - y*y);
b = atan2(x*y - w*z, 0.5f - x*x, -z*z);
}

19、

20、

3D Math Keynote 2的更多相关文章

  1. 3D Math Keynote 4

    [3D Math Keynote 4] 1.三角带. 合并三角带能够提升渲染效率. 三角扇. 2.边缩坍,将边缩减为顶点 . 网格消减,使用边缩坍,可以实现渐进式网络. 3.下图左边是面拆分.右边是焊 ...

  2. 3D Math Keynote 3

    [3D Math Keynote 3] 1.球的表面积 Surface.球的体积 Volumn: 2.当物体旋转后,如果通过变换后的旧AABB来顶点来计算新的AABB顶点,则生成的新AABB可能比实际 ...

  3. 3D Math Keynote

    [3DMathKeynote] 1.常用公式. 1)(A*B)^T = B^T*A^T.   2)(A*B)^-1 = B^-1*A^-1. 3)|A*B| = |A|*|B|. 4)|M^T|=|M ...

  4. 《3D Math Primer for Graphics and Game Development》读书笔记2

    <3D Math Primer for Graphics and Game Development>读书笔记2 上一篇得到了"矩阵等价于变换后的基向量"这一结论. 本篇 ...

  5. 《3D Math Primer for Graphics and Game Development》读书笔记1

    <3D Math Primer for Graphics and Game Development>读书笔记1 本文是<3D Math Primer for Graphics and ...

  6. 3D Math Library的姿势

    http://www.opentk.com/doc/math http://www.gamedev.net/topic/484756-fast-vector-math-library-for-net/ ...

  7. 3D math primer for graphics and game development

    三角网格(Triangle Mesh) 最简单的情形,多边形网格不过是一个多边形列表:三角网格就是全部由三角形组成的多边形网格.多边形和三角网格在图形学和建模中广泛使用,用来模拟复杂物体的表面,如建筑 ...

  8. 3D数学基础 KeyNote 1

    [计算几何复习要点] 1.向量加法的几何含意: a+b的释意为:a的尾连上b的头,新建一条从a的尾指向b的头的向量. 2.向量减法的几何含意: a-b的释意为:尾部相连,新建一个从b的头指向a的头的向 ...

  9. 3D数学学习笔记——笛卡尔坐标系

    本系列文章由birdlove1987编写.转载请注明出处. 文章链接: http://blog.csdn.net/zhurui_idea/article/details/24601215 1.3D数学 ...

随机推荐

  1. 第二节 Python基础之变量,运算符,if语句,while和for循环语句

    我们在上一节中,我们发现当我们用字符串进行一些功能处理的时候,我们都是把整个字符串写下来的,比如"jasonhy".startwith("j"),如果我们在程序 ...

  2. 嵌入式V3s交叉编译 tslib和QT4.8.7,并使用Qt Creator编译项目

    本文主参考:http://zero.lichee.pro/%E5%BA%94%E7%94%A8/QT_index.html 环境 Ubuntu16 64位 arm-linux-gnueabihf ve ...

  3. cplusplus标准库

    http://www.cplusplus.com/reference/   Standard C++ Library reference C Library The elements of the C ...

  4. MySql 的SQL执行计划查看,判断是否走索引

    在select窗口中,执行以下语句: set profiling =1; -- 打开profile分析工具show variables like '%profil%'; -- 查看是否生效show p ...

  5. qcom,msm8996-pinctrl.txt

    Qualcomm Technologies, Inc. MSM8996 TLMM block This binding describes the Top Level Mode Multiplexer ...

  6. 前端反爬虫策略--font-face 猫眼数据爬取

      1 .font-face定义了字符集,通过unicode去印射展示. 2 .font-face加载网络字体,我么可以自己创建一套字体,然后自定义一套字符映射关系表例如设置0xefab是映射字符1, ...

  7. 傻瓜学编程之block_2

    block的实质 以一个简单的实现为列子: - (void)myBlcokTest{ void (^blk)()=^{ printf(@“beijinghuanyingni”); }; blk(); ...

  8. 著名java博客

    http://blog.csdn.net/net19880504/article/details/20807403

  9. 使用shell进行etl数据验证

    方法如下: 整理校验的类型,不同的类型配置文件不一样. 1:校验数据增量:需要设置表名,增量字段. 2:非法值校验:设置表名,条件,校验字段,合法值/非法值范围. 3:自定义校验:设置表名,校验名称, ...

  10. Nginx 负载配置

    简版的,详细参数需要自己微调. nginx.conf http{ upstream name { server 127.0.0.1:8777; server 127.0.0.1:8778; serve ...