四元数(Quaternion)和旋转 & Unity中的旋转

四元数本质上是一种高阶复数,是一个四维空间,相对于复数的二维空间。我们高中的时候应该都学过复数,一个复数由实部和虚部组成,即x = a + bi,i是虚数单位,如果你还记得的话应该知道i^2 = -1。而四元数其实和我们学到的这种是类似的,不同的是,它的虚部包含了三个虚数单位,i、j、k,即一个四元数可以表示为x = a + bi + cj + dk。

 

Unity里,tranform组件里面的rotation,它的类型就是四元数。

 

使用矩阵哪儿不好:

旋转其实只需要知道一个向量+一个角度,一共4个值的信息,但矩阵法却使用了16个元素;

而且在做乘法操作时也会增加计算量,造成了空间和时间上的一些浪费;

 

欧拉旋转哪儿不好:

万向节锁问题https://v.youku.com/v_show/id_XNzkyOTIyMTI=.html?debug=flv

 

一个四元数可以表示为q = w + xi + yj + zk,使用q = ((x, y, z),w) = (v, w),其中v是向量,w是实数,这样的式子来表示一个四元数。

 

我们先来看问题的答案。我们可以使用一个四元数q=((x,y,z)sinθ2, cosθ2) 来执行一个旋转。

 

Quaternion.Euler和Quaternion.eulerAngles。它们基本可以满足绝大多数的四元数旋转变换。

 

 

和其他类型的转换

 

轴角到四元数:

 

给定一个单位长度的旋转轴(x, y, z)和一个角度θ。对应的四元数为:

q=((x,y,z)sinθ2, cosθ2) 
 

 

 

欧拉角到四元数:

 

给定一个欧拉旋转(X, Y, Z)(即分别绕x轴、y轴和z轴旋转X、Y、Z度),则对应的四元数为:

 

x = sin(Y/2)sin(Z/2)cos(X/2)+cos(Y/2)cos(Z/2)sin(X/2)
y = sin(Y/2)cos(Z/2)cos(X/2)+cos(Y/2)sin(Z/2)sin(X/2)
z = cos(Y/2)sin(Z/2)cos(X/2)-sin(Y/2)cos(Z/2)sin(X/2)
w = cos(Y/2)cos(Z/2)cos(X/2)-sin(Y/2)sin(Z/2)sin(X/2)
q = ((x, y, z), w)

 

 

四元数的插值

 

这里的插值指的是球面线性插值。

 

设t是一个在0到1之间的变量。我们想要基于t求Q1到Q2之间插值后四元数Q。它的公式是:

Q3  = (sin((1-t)A)/sin(A))*Q1 + (sin((tA)/sin(A))*Q2)

Q = Q3/|Q3|,即单位化

 

 

 

四元数的创建

 

在Unity里如何利用四元数进行旋转呢?Unity里提供了非常多的方式来创建一个四元数。例如

 

static Quaternion AngleAxis(float angle,Vector3 axis)

 

它可以返回一个绕轴线axis旋转angle角度的四元数变换。我们可以一个Vector3和它进行左乘,就将得到旋转后的Vector3。在Unity里只需要用一个“ * ”操作符就可以进行四元数对向量的变换操作,

 Vector3 newVector = Quaternion.AngleAxis(90, Vector3.up) * Quaternion.LookRotation(someDirection) * someVector;  

其中:

static Quaternion LookRotation(Vector3 forward);
static Quaternion LookRotation(Vector3 forward,Vector3 upwards);
使用指定的向前方向和向上方向来创建四元数,跟SetLootRotation差不多,区别是可以返回一个Quaternion。 

 

 

尽管欧拉角更容易我们理解,但四元数比欧拉角要强大很多。Unity提供了这两种方式供我们选择,我们可以选择最合适的变换。

例如,如果我们需要对旋转进行插值,我们可以首先使用Quaternion.eulerAngles来得到欧拉角度,然后使用Mathf.Clamp对其进行插值运算。

最后更新Quaternion.eulerAngles或者使用Quaternion.Euler(yourAngles)来创建一个新的四元数。

 

又例如,如果你想要组合旋转,比如让人物的脑袋向下看或者旋转身体,两种方法其实都可以,但一旦这些旋转不是以世界坐标轴为旋转轴,比如人物扭动脖子向下看等,那么四元数是一个更合适的选择。Unity还提供了transform.forward, transform.right and transform.up 这些非常有用的轴,这些轴可以和Quaternion.AngleAxis组合起来,来创建非常有用的旋转组合。例如,下面的代码让物体执行低头的动作:

transform.rotation = Quaternion.AngleAxis(degrees, transform.right) * transform.rotation;  

 

 

Unity3D与旋转相关的函数(C#)

 

1)void Rotate(Vector3 eulerAngles, float relativeTo)
应用一个欧拉角的旋转角度,eulerAngles.z度围绕z轴,eulerAngles.x度围绕x轴,eulerAngles.y度围绕y轴(这样的顺序)。
如果relativeTo留空或者设置为Space.Self 旋转角度被应用围绕变换的自身轴。(当在场景视图选择物体时,x、y和z轴显示)如果是Space.World 旋转角度被应用围绕世界的x、y、z轴。

 

2)void SetFromToRotation (Vector3 fromDirection, Vector3 toDirection)
把物体的fromDirection旋转到toDirection

3)void SetLookRotation(Vector3 view);
void SetLookRotation(Vector3 view,Vector3 up);
这个函数根据指定的向前和向上向量创建四元数,建立一个旋转使z轴朝向view, y轴朝向up。

4)static Quaternion AngleAxis(float angle,Vector3 axis)
物体沿指定轴向axis旋转角度angle。

5)Quaternion.eulerAngles
存放四元数对应的三个轴向的欧拉角,分别是绕x轴、y轴、z轴旋转的角度

6)static Quaternion FromToRotation(Vector3 fromDirection,Vector3 toDirection);
根据两个向量计算出旋转量,计算出来的旋转量为从fromDirection旋转到toDirection的旋转量,跟SetFromToRotation差不多,区别是可以返回一个Quaternion。通常用来让transform的一个轴向(例如 y轴)与toDirection在世界坐标中同步。 

7)static Quaternion LookRotation(Vector3 forward);
static Quaternion LookRotation(Vector3 forward,Vector3 upwards);
使用指定的向前方向和向上方向来创建四元数,跟SetLootRotation差不多,区别是可以返回一个Quaternion。 

8)static Quaternion RotateTowards(Quaternion from,Quaternion to, float maxDegreesDelta);
以maxDegreesDelta作为角度步长计算从from到to之间的旋转量

9)static Quaternion Slerp (Quaternion from : Quaternion to, float t)
球形插值, 从from转换到to,移动距离为t。当两个quaternion接近时,转换的速度会比较慢。

10)static Quaternion Lerp (Quaternion a, Quaternion b, float t)
跟Slerp相似,且比Slerp快,.但是如果旋转角度相距很远则会看起来很差

11)static Quaternion Inverse (Quaternion rotation) : 
返回与rotation相反的方向 

12)static float Angle (Quaternion a, Quaternion b)
计算两个旋转之间的夹角。跟Vector3.Angle() 作用一样。 

13)static Quaternion Euler (float x, float y, float z)
把旋转角度变成对应的Quaternion

 

14)void ToAngleAxis (out float angle, out Vector3 axis)
返回物体的旋转角度(物体的z轴和世界坐标z轴的夹角)和三维旋转轴的向量到变量out angle 和out axis
--------------------- 
作者:只要你在 
来源:CSDN 
原文:https://blog.csdn.net/icebergliu1234/article/details/81154128 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity四元数Quaternion)是一种用于表示旋转的数据类型。它由四个实数构成,即(x, y, z, w),其前三个分量表示旋转轴的向量部分,而第四个分量表示旋转角度的标量部分。 Unity使用四元数来表示物体的旋转是因为它具有很多优点,例如避免万向节锁(Gimbal Lock)问题以及提供更高效的旋转计算。使用四元数可以执行平滑的插值和旋转操作,并且在进行多个旋转操作时不会出现旋转误差的累积问题。 在Unity,可以通过Quaternion类来创建和操作四元数。你可以使用Quaternion.Euler函数通过欧拉角(Euler angles)来创建一个四元数,也可以使用Quaternion.LookRotation函数通过指定的方向向量来创建一个四元数。此外,你还可以使用四元数的乘法运算来执行旋转的组合操作。 例如,要将一个物体绕着Y轴旋转90度,可以使用以下代码: ```csharp Quaternion rotation = Quaternion.Euler(0f, 90f, 0f); transform.rotation = rotation; ``` 这将把物体的旋转设置为绕着世界坐标系的Y轴旋转90度。 需要注意的是,Unity四元数是归一化的,即它们的长度(模)始终为1。因此,如果你直接修改四元数的值,可能会导致旋转失效或产生意想不到的结果。通常情况下,建议使用旋转操作函数(如Rotate、RotateAround等)来进行旋转操作,而不是直接修改四元数的值。 总而言之,四元数Unity一种用于表示旋转的强大数据类型,它提供了灵活而高效的旋转操作,使你可以在游戏开发实现各种复杂的旋转效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值