作用:四元数和向量相乘表示这个向量按照这个四元数进行旋转之后得到的新的向量。

Unity - Scripting API: Quaternion.operator * (unity3d.com)

比如:向量vector3(0,0,10),绕着Y轴旋转90度,得到新的向量是vector3(10,0,0)。

在unity中表示为:

1
2
3
4
5
6
7
8
9
10
11
12
using UnityEngine;

public class QuaternionMultVector : MonoBehaviour
{
void Start()
{
Vector3 v = new Vector3(0, 0, 10);
Quaternion q = Quaternion.Euler(0, 90, 0);
Vector3 nv = q * v; // Quaternion必须在Vector前面乘,因为只有Quaternion重载了*运算符
Debug.Log(nv);
}
}

输出结果

复合旋转就是四元数依次相乘,最后乘以向量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class QuaternionMultVector : MonoBehaviour
{
void Start()
{
Transform target = new GameObject("TestTarget").transform;
Transform b = new GameObject("B_GameObject").transform;
b.position = new Vector3(2, 0, 0);

//1.物体的正前方10米的位置点
target.position = transform.position + Vector3.forward * 10f;
Debug.DrawRay(target.position, Vector3.up, Color.blue, 100f);

//2.物体前方世界坐标系Y轴45度,10米位置的坐标点
Quaternion q = Quaternion.Euler(0, 45, 0);
Vector3 v = q * Vector3.forward * 10f;
target.position = transform.position + v;
Debug.DrawRay(target.position, Vector3.up, Color.red, 100f);

//3.物体到B点方向,10米位置的坐标点
Vector3 dir = b.position - transform.position;
Quaternion q2 = Quaternion.LookRotation(dir);
target.position = transform.position + q2 * Vector3.forward * 10f;
//target.position = dir.normalized * 10 + transform.position; 与上述结果等价,dir.normalized = q2 * Vector3.forward
Debug.DrawRay(target.position, target.up, Color.green, 100f);

//4.物体到B点方向Y轴偏移45度,10米位置的坐标点
target.position = transform.position + q * q2 * Vector3.forward * 10f;//Quaternion之间也可以相乘
Debug.DrawRay(target.position, target.up, Color.yellow, 100f);
}
}

结果

想了解其中的运算过程的可以往下看。

将四元数的四个值分别计为:(w,x,y,z),unity中的四元数中的四个数字是(x,y,z,w),不影响下面的计算过程。

绕任意轴旋转任意角度的四元数为:

四元数旋转

Y轴向量为(0,1,0)

那么绕着Y轴旋转90度的四元数就是**q = (√2/2 , 0 , √2/2 , 0)**;

1
2
3
4
5
6
7
8
9
10
11
12
using UnityEngine;

public class QuaternionMultVector : MonoBehaviour
{
void Start()
{
Vector3 v = new Vector3(0, 0, 10);
Quaternion q = Quaternion.Euler(0, 90, 0);
Vector3 nv = q * v; // Quaternion必须在Vector前面乘,因为只有Quaternion重载了*运算符
Debug.Log(nv);
}
}

unity中这个Quaternion.Euler(0,90,0)打debug的话是(0,√2/2 , 0 , √2/2 ),因为排列顺序是(x,y,z,w),不影响下面的计算过程

四元数乘以向量的运算规则为:q * v = (q) *( v) *( q−1);

其中:

q = (√2/2 , 0 , √2/2 , 0);

v,将v向量扩充为四元数(0,v),也就是v = (0 , 0,0 , 10);

q−1是四元数q的逆,求逆过程如下:

共轭四元数:q*=(w,-x,-y,-z),也就是(√2/2 , 0 , -√2/2 , 0)
四元数的模:N(q) = √(x^2 + y^2 + z^2 +w^2),即四元数到原点的距离,计算结果为1
四元数的逆:q−1=q*/N(q),也就是q−1 = (√2/2 , 0 , -√2/2 , 0)
q * v = q * v * q−1 = (√2/2 , 0 , √2/2 , 0) * (0 , 0,0 , 10)*(√2/2 , 0 , -√2/2 , 0);

四元数乘法公式:

四元数叉乘

按照上述计算公式: q * v = q * v * q−1

(√2/2 , 0 , √2/2 , 0) * (0 , 0,0 , 10) = (0,5√2,0,5√2)

(0,5√2,0,5√2) * (√2/2 , 0 , -√2/2 , 0)=(0,10,0,0);

将最后得到的四元数(0,10,0,0)变为向量(0,newV),就是newV(10,0,0)。