【Unity API】四元数Quaternion的乘法规则详解,含代码案例演示

四元数相乘有两种方式,一种是四元数之间相乘,另一种是四元数与向量相乘。

1.四元数之间相乘

public static Quaternion operator * (Quaternion lhs, Quaternion rhs);

官方文档上:旋转 lhs * rhs 的乘积与按以下顺序应用两个旋转的效果相同:先应用 lhs,然后相对于 lhs 旋转生成的参考帧应用
/rhs/。注意,这意味着旋转不满足交换律,因此 lhs * rhs 产生的旋转效果不同于 rhs * lhs 的旋转效果。

可以知道rhs是在lhs旋转后,以其自身坐标系为参照坐标轴,再进行rhs旋转,并得到最终结果。所以四元数乘法不满足交换律,乘号两边互换,得到的结果是完全不同的。

请看下面代码:

例1:

Quaternion q1 = Quaternion.AngleAxis(-90, Vector3.forward); //得到以的前方向旋转为轴,-90°的旋转

物体以自身坐标系为参照,绕Vector3.forward轴,旋转-90度。
【Unity API】四元数Quaternion的乘法规则详解,含代码案例演示_第1张图片

例2:

Quaternion q2 = Quaternion.AngleAxis(170, Cube2.forward);//得到以Cube2的前方向为轴,旋转170°的旋转

物体以自身坐标系为参照,绕Cube2.forward轴,旋转170度。
【Unity API】四元数Quaternion的乘法规则详解,含代码案例演示_第2张图片

例3:

Quaternion q3 = q1 * q2; //得到,物体旋转为q1之后(q3 = q1);再以其自身局部坐标坐标的前方向为轴,旋转170°的旋转( * q2)

1.物体先以自身坐标系为参照,绕Vector3.forward轴,旋转-90度。
2.再以物体当前自身坐标系作为参照,绕Cube2.forward轴,旋转170度。
【Unity API】四元数Quaternion的乘法规则详解,含代码案例演示_第3张图片

例4:

Quaternion q3 = q2 * q1; //得到,物体旋转为q2之后(q3 = q2);再以其自身局部坐标坐标的前方向为轴,旋转-90°的旋转( * q2)

1.物体先以自身坐标系为参照,绕Cube2.forward轴,旋转-90度。
2.再以物体当前自身坐标系作为参照,绕Vector3.forward轴,旋转170度。
【Unity API】四元数Quaternion的乘法规则详解,含代码案例演示_第4张图片

2.四元数与向量相乘

public static Vector3 operator * (Quaternion rotation, Vector3 point);

注意:四元数与向量相乘,四元数在*左边。

四元数与向量相乘就比较简单理解了。

官方文档:对点 point 应用旋转 /rotation/。

相乘的结果就是:把点point,旋转rotation之后的位置。

例1:

使物体B,相对于物体A的距离不变,位置坐标跟随物体A的旋转变换。(效果等同于:物体C是物体A的子物体,但旋转物体A,的时候,物体C在世界坐标下的旋转量不变)
在这里插入图片描述

Vector3 distancePos ;
public void Start()
{
	distancePos = CubeB.position - CubeA.position;
}

public void Update()
{
	CubeB.position = CubeA.rotation * distancePos + CubeA.position;
}

这种方式有一个缺点,没有在CubeB和CubeA相对位置的基础上进行旋转。只是保证了CubeB与CubeA的相对距离不变。(不论CubeB在何处,运行代码后,CubeB都在CubeA.right的反方向上,只有距离的差别)

例2:

对例1进行完善,在CubeB和CubeA相对位置的基础上进行旋转。

在例1中,不论CubeB在何处,运行代码后,CubeB都在CubeA.right的反方向上。

所以我们需要得到CubeB从CubeA.right的反方向,旋转到CubeB的世界坐标所需要的旋转量startRot。再把startRot作为修正旋转量,加到CubeA的rotation上。

Vector3 distancePos ;
Quaternion startRot;
public void Start()
{
	distancePos = CubeB.position - CubeA.position;
	//从CubeA.right的反方向,旋转到CubeB的世界坐标所需要的旋转量
	startRot.SetFromToRotation(-CubeA.right, CubeB.position - CubeA.position);
}

public void Update()
{
	//需要注意此处两个四元数相乘的顺序,
	//因为需要将CubeA的旋转量,增加修正旋转量。
	//所以是CubeA.rotation左乘startRot
	CubeB.position = (CubeA.rotation * startRot) * distancePos + CubeA.position;
}

这就完成了使CubeB以CubeA的旋转量两者之间的相对位置为基础,进行旋转的操作。

你可能感兴趣的:(Unity,unity,几何学,游戏开发,unity3d,游戏引擎)