文档库 最新最全的文档下载
当前位置:文档库 › Unity旋转(四元数)

Unity旋转(四元数)

Unity旋转(四元数)
Unity旋转(四元数)

在Unity 3D中,实现物体旋转有多种方式,如旋转矩阵、欧拉角和四元数等[1]。旋转需要两个基本参量轴和角,物体从一个方位旋转到另一个方位可以采用多次改变轴和角的方式,依次旋转。其中,有一种旋转方式是只绕一个轴旋转一次就能达到指定方位,且旋转角度在﹣180°~180°之间,称

这样的旋转方式为最短旋转。

任意指定两个方位,要找出其中的最短旋转并不是一件容易的事。本文将给出最短旋转的数学描述以及在Unity 3D中实现最短旋转的方法。

最短旋转的数学描述

刚体的运动包括平动和转动。描述刚体的空间位置,用三维空间坐标点(x,y,z)表示,在Unity 3D中有3个基本坐标系,分别是世界坐标系、惯性坐标系与本地坐标系。相应的,描述刚体的旋转状态,即方位,是本地坐标系与惯性坐标系所形成的角度变化,采用欧拉角来描述。由于本文不涉及平移,因此为方便讨论,将惯性坐标系和世界坐标系重合。

众所周知,“两点之间线段最短”,同样两个方位之间也存在类似的关系,即最短旋转,两点之间的距离用两点位置之差来描述。相应的,两个方位之间的最短旋转用两个方位的四元数之比来描述。

如果方位a的四元数为q1,方位b的四元数为q2,刚体从方位a旋转到方位b的最短旋转的四元数为q,则q = q2÷q1。

设四元数q的4个分量分别是(x,y,z,w),该四元数隐含了旋转轴向量n和旋转角d,设轴向量n 的3个分量为(nx,ny,nz)。一般将轴n和角d写成“轴角对”的形式,即(n,d)=(nx,ny,nz,d )。四元数q=(x,y,z,w)与轴角对(n,d)=(nx,ny,nz,d )之间的关系为:

q = (x,y,z,w) = (nx*sin(d/2),ny*sin(d/2),nz*sin(d/2),cos(d/2))

在Unity 3D中,改变欧拉角和改变四元数是两种基本的旋转方式,Unity 3D提供了Lerp和Slerp 两种插值函数,在两个方位之间进行采样插值。对欧拉角的Lerp插值,很难实现最短旋转,而四元数Slerp函数插值则非常容易实现最短旋转,下面通过例子来进行验证。

在Unity3D中改变欧拉角实现旋转

在Unity 3D中,制作一个空物体,命名为a,该物体位于世界坐标系的原点位置,在其下面放置一个立方体Cube和一个小球Sphere,调整立方体和小球的大小和位置,如下图所示,让小球位于立方体的一个角点。

选中物体a,在Inspector面板上修改参数rotation为(-20,-30,9),这是物体a的欧拉角,结果如下图所示。

复制物体a,重新命名为b。再次复制物体a,并命名为c,修改b欧拉角为(15, 80, 60),结果如下图所示,要实现的操作是物体c开始与a重合,然后旋转到物体b的位置。

为了能够跟踪物体x的旋转,对x上的小球Sphere,添加代码如下:public class MyDrawPointsPath : MonoBehaviour

{

List points = new List();

void Update()

{

points.Add(transform.position);

for (int i = 0; i < points.Count - 1; i++)

{

Debug.DrawLine(points[i], points[i + 1]);

}

}

}

为实现物体x的旋转,创建代码如下:

public class MyRotation : MonoBehaviour

{

public Transform a, b;

float t;

void Update()

{

Vector3 v = Vector3.Lerp(a.eulerAngles,b.eulerAngles, t);

transform.eulerAngles = v;

t += 0.1f * Time.deltaTime; //每秒变化0.1°

}

}

将该段代码拖拽到物体x上,将场景中的物体a和b拖放到代码的公共变量卡槽a和b上,代码中的Vector3.Lerp是系统提供的插值函数,包括3个参数:起始向量a的欧拉角、结束向量b 的欧拉角、插值t在0~1的取值,运行结果如下图所示。

从图中可以看到,物体x上的小球画出了一条奇怪的轨迹,说明用欧拉角插值不能实现最短旋转。

在Unity3D中改变四元数实现最短旋转

将上面代码中的Update()函数进行修改如下:

void Update()

{

Quaternion q1= a.rotation;

Quaternion q2= b.rotation;

Quaternion q= Quaternion.Slerp(q1, q2, t);

transform.rotation = q;

t += 0.1f * Time.deltaTime;

}

代码中q1和q2分别是a,b的四元数,Slerp是在两个四元数之间进行插值,再次运行,结果如下图所示。通过观察可以看出,物体c绕某一固定轴一次旋转到了指定位置,实现了最短旋转。

这个旋转过程用语言可以描述为:一个刚体从初始方位为a,其欧拉角为(-20,-30,9),旋转到末方位b,欧拉角为(15,80,60),找到轴角对实现最短旋转。

仿照最短距离,本文给出了最短旋转的概念并给出了最短旋转的数学描述,即两个方位的四元数的比值。在Unity3D中,通过修改四元数很容易实现最短旋转,并能够直观地给出旋转轴和角,对理解四元数在Unity 3D中的应用具有重要作用。

相关文档