Unity中的四元数

一.简介:

  在游戏中常常需要对物体进行旋转操作,或者了解物体的旋转朝向,所以需要对物体的旋转进行描述.对物体的旋转的描述有以下4种常用方式:

  1.欧拉角:将物体的旋转拆分为绕x轴旋转\绕y轴旋转和绕z轴旋转三个操作.Unity的Inspector窗口中可以查看到Transform组件中的旋转参数,这个参数就是欧拉角

  Unity中的四元数

  使用欧拉角的方式描述旋转优点在于非常直观,易于理解,但是缺点在于同样的旋转结果可能会有不同的旋转描述,同时可能导致万向节死锁的问题.

  2.轴-角对:三维空间中的物体旋转一定能描述为绕着某条轴线旋转一定的度数.我们使用一个向量描述轴线,使用一个数字描述角度,这样的描述方式称为轴角对.轴角对的方式不会产生万向节死锁的问题.但是在描述旋转时,我们会发现旋转α度和α+n*360度(n∈Z)的结果是一样的,所以采用这种方式描述旋转角度仍然需要转化.同时如果将一个轴-角对的旋转描述中轴和角都取为原来的相反数,描述的结果仍然是相同的.因此同样的旋转,使用轴角对仍然有无数种描述方式,但是我们可以发现虽然描述的角度不同,但是这些角度的三角函数值相同,所以引入三角函数来描述旋转就可以有效减少同一种旋转结果的可用描述方式.

  3.四元数:对于给定的旋转,可以使用轴-角对描述为绕着n=(x,y,z)轴旋转β度得到,那么这个旋转使用四元数可以描述为Q=[cos(β/2),sin(β/2)*n]或者Q=[cos(β/2),sin(β/2)*x,sin(β/2)*y,sin(β/2)*z].显然四元数使用了三角函数对角度进行描述,至于四元数为什么是这个公式,读者可以自行查阅学习四元数公式的数学推导和意义,这里更多地介绍Unity中和四元数有关的内容.四元数可以看做是轴角对描述方式的一种变形.注意:轴角对转化为四元数时,轴必须单位化(也就是说n必须是单位向量).

  4.旋转矩阵.

二.四元数有关的常用API

  1.创建四元数

        //四元数Q = [cos(β/2), sin(β/2)*x, sin(β/2)*y, sin(β/2)*z]
        float angle = 60f;
        float halfAngle = angle / 2 * Mathf.Deg2Rad;
        //轴角对中的轴必须是单位长度轴
        Vector3 axis = new Vector3(1, 0, 0);
        //直接指定四元数的四个参数,繁琐且复杂,一般不会使用这种方式
        Quaternion q = new Quaternion(Mathf.Sin(halfAngle) * axis.x, Mathf.Sin(halfAngle) * axis.y, Mathf.Sin(halfAngle) * axis.z, Mathf.Cos(halfAngle));
        //使用AngleAxis静态方法指定旋转角和旋转轴
        Quaternion q2 = Quaternion.AngleAxis(angle,axis);

  2.四元数和欧拉角转换

        //欧拉角转化为四元数
        Quaternion q = Quaternion.Euler(60, 60, 0);//使用Quaternion结构体的静态方法
        var e = q.eulerAngles;//四元数中属性eulerAngles是四元数对应的欧拉角

  3.四元数的乘法表示旋转

transform.localRotation *= Quaternion.AngleAxis(60 * Time.deltaTime, (new Vector3(10, 5, 4)).normalized);

  4.单位四元数和四元数插值运算

        //单位四元数对应欧拉角(0,0,0)
        transform.localRotation = Quaternion.identity;
        //插值运算(四元数中线性插值和球形插值差别不大,线性插值相对运算速度较快但是旋转范围较大时效果较差,推荐球形插值)
        Quaternion.Lerp(transform.rotation, Quaternion.AngleAxis(60, Vector3.right), .5f);
        Quaternion.Slerp(transform.rotation, Quaternion.AngleAxis(60, Vector3.right), .5f);

  5.计算旋转朝向LookRotation

        //直接设置物体朝向向量(1,1,1)方向
        transform.localRotation = Quaternion.LookRotation(new Vector3(1, 1, 1));
        //设置物体A朝向物体B方向
        Transform A;
        Transform B;
        A.localRotation = Quaternion.LookRotation(B.localPosition - A.localPosition);

三.四元数运算的意义

  1.四元数相乘:代表旋转量的叠加.如四元数q1和四元数q2的乘法结果代表旋转四元数是q1的基础上旋转q2得到的旋转四元数结果.

  2.四元数和向量相乘:代表将向量按照四元数对应的轴和角度进行旋转.

 

Unity中的四元数

上一篇:Java学习知识点-学弟学妹必备Java学习路线


下一篇:js基础---数组去重