四元数-Quaternion

<p>
回顾一下四元数中的属性和方法。
</p>

属性:

public Vector3 eulerAngles
功能说明 此属性用来返回或设置Quaternion实例对应的欧拉角
进行赋值的方式通常有两种:

public Transform A, B;
Quaternion rotations=Quaternion.identity;
Vector3 eulerAngle = Vector3.zero;

第一种是将Quaternion实例赋值给transform的rotation 
rotations.eulerAngles = new Vector3(0.0f, speed * Time.time, 0.0f);
A.rotation = rotations;

第二种是将三维向量代表的欧拉角直接赋值给transform的eulerAngles
eulerAngle = new Vector3(0.0f, speed * Time.time, 0.0f);
B.eulerAngles = eulerAngle;

Quaternion类实例方法:

在Quaternion类中涉及的实例方法有SetFromToRotation方法、SetLookRotation方法和ToAngleAxis方法

SetFromToRotation方法

public void SetFromToRotation(Vector3 fromDirection, Vector3 toDirection);
用于创建一个从fromDirection到toDirection的rotation,同样也不能够直接对Transform.rotation直接进行操作,先对四元数进行旋转,然后将四元数赋值给rotation,例如:

//不可直接使用transform.rotation.SetFromToRotation(v1,v2)方式进行设置
//只能将实例化的Quaternion赋值给transform.rotation。
Quaternion q1 = Quaternion.identity;
q1.SetFromToRotation(v1,v2);
transform.rotation = q1;

首先会把该物体的xyz轴方向和世界坐标的xyz一致(即rotation在世界坐标系中为0,如果是父对象有旋转的话也不影响),然后旋转的rotation为:V1指向的方向旋转到V2指向的方向:

image.png

A为v1,B为V2,如果B向上移动一定距离,那么C也会朝上旋转;

SetLookRotation方法

基本语法
(1) public void SetLookRotation(Vector3 view);
(2) public void SetLookRotation(Vector3 view, Vector3 up);
用来对一个Quaternion实例的朝向进行设置。例如:

Quaternion q1 = Quaternion.identity;
q1.SetLookRotation(v1); //1.
q1.SetLookRotation(v1, v2); //2.
transform.rotation = q1;

q1.SetLookRotation(v1):transform.right垂直于由Vector3.zero、v1、v1.up构成的平面,transform.forward为v1向量,下图中A为v1:

image.png

q1.SetLookRotation(v1, v2):
transform.right垂直于由Vector3.zero、v1和v2这3点构成的平面。
v2除了与Vector3.zero和v1构成平面来决定transform.right的方向外,还用来决定transform.up的朝向,因为当transform.forward和transform.right方向确定后, transform.up方向剩下两种可能,到底选用哪一种便由v2来影响。transform.up方向的选取方式总会使得transform.up的方向和v2方向的夹角小于或等于90度。

image.png

当v1为Vector3.zero时,方法失效,即不要在使用此方法时把v1设置成Vector3.zero。
<pre>
提示
不可以直接使用transform.rotation.SetLookRotation(v1, v2)的方式来使用SetLookRotation方法,否则会不起
作用。应该使用上述代码所示的方式,首先实例化一个Quaternion,然后对其使用SetLookRotation,最后将其赋给transform.rotation。
</pre>

ToAngleAxis方法

基本语法
public void ToAngleAxis(out float angle, out Vector3 axis);
其中参数angle为旋转角,参数axis为轴向量。
功能说明 此方法用于将Quaternion实例转换为角轴表示。
在transform.rotation.ToAngle Axis(out angle, out axis)中,输出值angle和axis的含义为:要将GameObject对象的rotation从Quaternion.Identity状态变换到当前状态,只需要将GameObject对象绕着axis的轴向(指世界坐标系中)旋转angle角度即可。通常和静态方法AngleAxis (angle : float, axis : Vector3)联合使用,使得一个物体的rotation始终和另一个物体的rotation保持一致,例如:

void Update()
    {
        //使用ToAngleAxis获取A的Rotation的旋转轴和角度
        A.rotation.ToAngleAxis(out angle, out axis);
        //使用AngleAxis设置B的rotation,使得B的rotation状态的和A相同
        //当然也可以只使得B与A的axis相同,而angle不同
        //可以在程序运行时修改A的rotation查看B的状态
        B.rotation = Quaternion.AngleAxis(angle, axis);
    }

运行效果如下,B会随着A的旋转保持和A一致:

image.png

Quaternion类静态方法

在Quaternion类中主要的静态方法有Angle方法、Dot方法、Euler方法、FromToRotation方法、Inverse方法、Lerp方法、LookRotation方法、RotateTowards方法和Slerp方法:

Angle方法:Quaternion实例间夹角

基本语法 public static float Angle(Quaternion a, Quaternion b);
功能说明 此方法用于返回从参数a到参数b变换的夹角。需要注意的是,返回的夹角不是某个局部坐标轴向变换的夹角,而是GameObject对象从状态a转换到状态b时需要旋转的最小夹角。

Dot方法:点乘

基本语法 public static float Dot(Quaternion a, Quaternion b);
a●b=|a||b|cos夹角 可以判断a在b的前方和后方.

Euler方法:欧拉角对应的四元数

基本语法
(1) public static Quaternion Euler(Vector3 euler);
(2) public static Quaternion Euler(float x, float y, float z);
功能说明 此方法用于返回欧拉角Vector3(x,y,z)对应的四元数Quaternion实例。

FromToRotation方法:Quaternion变换

基本语法
public static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection);
功能说明 此方法用来创建一个从参数fromDirection到toDirection的Quaternion变换。其功能和实例方法SetFromToRotation (fromDirection : Vector3, toDirection : Vector3)相同:
测试代码如下:

 void Update()
    {
        //使用实例方法
        //不可直接使用C.rotation.SetFromToRotation(A.position,B.position);
        q1.SetFromToRotation(A.position, B.position);
        C.rotation = q1;
        //使用类方法
        D.rotation = Quaternion.FromToRotation(A.position, B.position);
        //在Scene视图中绘制直线
        Debug.DrawLine(Vector3.zero, A.position, Color.white);
        Debug.DrawLine(Vector3.zero, B.position, Color.white);
        Debug.DrawLine(C.position, C.position + new Vector3(0.0f, 1.0f, 0.0f),
        Color.white);
        Debug.DrawLine(C.position, C.TransformPoint(Vector3.up * 1.5f), Color.white);
        Debug.DrawLine(D.position, D.position + new Vector3(0.0f, 1.0f, 0.0f),
        Color.white);
        Debug.DrawLine(D.position, D.TransformPoint(Vector3.up * 1.5f), Color.white);
    }
AB夹角.png

C和D的旋转角度:

旋转角度.png
Inverse方法:逆向Quaternion值

基本语法
public static Quaternion Inverse(Quaternion rotation);

功能说明 此方法用于返回参数rotation的逆向Quaternion值。例如,设有实例rotation=(x,y,z,w),则Inverse(rotation)=(-x,-y,-z,w)。从效果上说,设rotation.eulerAngles=(a,b,c),则transform.rotation=Inverse(rotation)相当于transform依次绕自身坐标系的z轴、x轴和y轴分别旋转-c度、-a度和-b度。由于是局部坐标系内的变换,最后transform的欧拉角的各个分量值并不一定等于-a、-b或-c。
示例:
代码如下:

 public Transform A, B;
    void Start()
    {
        Quaternion q1 = Quaternion.identity;
        Quaternion q2 = Quaternion.identity;
        q1.eulerAngles = new Vector3(0, -90, 0);
        q2 = Quaternion.Inverse(q1);
        A.rotation = q1;
        B.rotation = q2;
    }

运行后的结果如下(Cube蓝色为正面):

结果.png
Lerp方法:线性插值

基本语法
public static Quaternion Lerp(Quaternion from, Quaternion to, float t);
功能说明 此方法用于返回从参数from到to的线性插值。当参数t≤0时返回值为from,当参数t≥1时返回值为to。此方法执行速度比Slerp方法快,一般情况下可代替Slerp方法。

示例:
代码如下:


public Transform A, B, C, D;
float speed = 0.2f;
void Update()
{
C.rotation = Quaternion.Slerp(A.rotation, B.rotation, Time.time * speed);
D.rotation = Quaternion.Lerp(A.rotation, B.rotation, Time.time * speed);

运行时会发现,C和D会渐渐由A的rotation旋转到B的rotation:

运行结果.png
LookRotation方法:设置Quaternion的朝向(和类实例方法SetLookRotation 类似,可以往上查看实例方法)

基本语法
(1) public static Quaternion LookRotation(Vector3 forward);
(2) public static Quaternion LookRotation(Vector3 forward, Vector3 upwards);

其中参数forward为返回Quaternion的forward朝向。
功能说明 此方法用于返回一个Quaternion实例,使GameObject对象的z轴朝向参数forward方向(使GameObject的forward为参数的向量)。此方法与方法SetLookRotation (view : Vector3, up : Vector3 = Vector3.up)功能相同。

RotateTowards方法:Quaternion插值

基本语法
public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);
其中参数from为起始Quaternion,参数to为结束Quaternion,参数maxDegreesDelta为每帧最大角度值。

功能说明 此方法用于返回从参数from到to的插值,且返回值的最大角度不超过maxDegreesDelta。此方法功能与方法Slerp相似,只是maxDegreesDelta指的是角度值,不是插值系数。当maxDegreesDelta<0时,将沿着从to到from的方向插值计算。

Quaternion类运算符

在Quaternion类中涉及的运算符运算有两个Quaternion实例相乘的运算、一个Quaternion实例和一个Vector3相乘的运算。

两个Quaternion实例相乘的运算

功能说明 此运算符用于返回两个Quaternion实例相乘后的结果。设A和B均为GameObject对象的一个实例,有如下代码:
B.rotation *= A.rotation;

代码每执行一次,B都会绕着B的局部坐标系的z、x、y轴分别旋转A.eulerAngles.z度、A.eulerAngles.x度和A.eulerAngles.y度,注意它们的旋转次序一定是先饶z轴再绕x轴最后绕y轴进行相应的旋转。另外由于是绕着局部坐标系旋转,故而当绕着其中一个轴旋转时,很可能会影响其余两个坐标轴方向的欧拉角(除非其余两轴的欧拉角都为0才不受影响)。

一个Quaternion实例和一个Vector3相乘的运算

功能说明 此运算符的作用是对参数坐标点point进行rotation变换。例如,设A为Vector3实例,有如下代码:

transform.position += transform.rotation *A;
则每执行一次代码,transform对应的对象便会沿着自身坐标系中向量A的方向移动A的模长的距离。transform.rotation与A相乘主要来确定移动的方向和距离。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容