目录
欧拉角
欧拉角由三个角度(x,y,z)构成,在特定坐标系下用于描述物体的旋转量。Inspector窗口中的调节的角度(Rotation)就是欧拉角,this.transform.eulerAngles得到的就是欧拉角角度。欧拉角直观,易于理解,但是却存在同一旋转表示不唯一,万向节死锁等缺点。
万向节死锁
当某个特定轴达到某个特殊值时,绕一个轴旋转可能会覆盖住另外一个轴旋转,从而失去一维自由度,在Unity中,X轴达到90度时会产生万向节死锁。
四元数公式
由于四元数旋转不存在万向节死锁问题,因此我们常常使用四元数表示三维空间中的旋转消息。
Q=[cos(β/2),sin(β/2)x,sin(β/2)y,sin(β/2)z](四元数是简单的超复数,主要在三维空间中表示旋转,四元数Q则表示绕着轴n旋转β度的旋转量)
四元数计算原理:
Quaternion q=new Quaternion(Mathf.Sin(30*Mathf.Deg2Rad),0,0,Mathf.Cos(30*Mathf.Deg2Rad));
提供的轴角对初始化四元数的方法
(轴-角对:在3D空间中,任意旋转都可以表示绕着某一个轴旋转一个旋转角得到,该轴不是空间中的x,z,y轴,而是任意一个轴)
Quaternion q=Quaternion.AngleAxis(60,Vector3.right);
四元数和欧拉角转换
欧拉角转四元数
Quaternion.Euler(x,y,z)
Quaternion q2=Quaternion.Euler(60,0,0);
GameObject obj2=GameObject.CreatePrimitive(PrimitiveType.Cube);
obj2.transform.rotation=q2;
四元数转欧拉角
Quaternion q;
q.eulerAngles
print(q2.eulerAngles);
四元数弥补欧拉角的缺点
1.同一旋转的表示不唯一
四元数旋转后,转换后的欧拉角始终是-180~180度
2.万向节死锁
通过四元数旋转对象可以避免万向节死锁。
必备:四元数相乘代表旋转四元数
//以下代码写在Update语句块中
this.transform.rotation*=Quaternion,AngleAxis(1,Vector3.forward);
//这里虽然是Vector3但是代表的是相对于自身坐标系的变化
单位四元数
用于对象角度初始化。
表示没有旋转量(角位移),当角度为0或者360度时对于给定轴就会得到单位四元数。
代码得到单位四元数的方法:
print(Quaternion.identity);
四元数中的插值运算
用于平滑旋转。
四元数中也存在Lerp和Slerp的运算,但是使用效果上看,推荐Slerp运算。
//以下为简略写法
//首先存储start
start=B.transform.rotation;
//以下代码写在Update语句块中
//无限接近,先快后慢
A.transform.rotation=Quaternion.Slerp(A.transform.rotation,target.rotation,Time.deltaTime);
//匀速变化time>=1到达目标
time+=Time.deltaTime;
B.transform.rotation=Quaternion.Slerp(start,target.rotation,time);
向量指向四元数
向量指向四元数,类似于LookAt的效果。(用于让对象朝向某个方向)
//如果以下代码写在Update语句块中就会实现不断看向
//首先得到AB向量
Quaternion q=Quaternion.LookRotation(lookB.position-lookA.position);
//将向量的值赋值给A的四元数
lookA.rotation=q;
四元数相乘(角度叠加)
两个四元数相乘得到一个新的四元数。代表两个旋转量的叠加,例如:
//直接用轴角对
Quaternion q=Quaternion.AngleAxis(20,Vector3.up);
//旋转20度
this.transform.rotation*=q;
//再旋转20度
this.transform.rotation*=q;
四元数乘向量(旋转向量)
四元数乘向量返回一个新的向量。相当于旋转向量。
Vector3 v=Vector3.forward;
//先旋转45度
v=Quaternion.AngleAxis(45,Vector3.up)*v;
//再旋转45度
v=Quaternion.AngleAxis(45,Vector3.up)*v;