unity --22 數學基礎- 四元數和歐拉角

歐拉角

三個數字來保存方位,共用vector3,但此時它不代表向量。

優點
•僅使用三個數字表達方位,佔用空間小。
•沿座標軸旋轉的單位爲角度,符合人的思考方式。
•任意三個數字都是合法的,不存在不合法的歐拉角。

//歐拉角,每次疊加(1,0,0)旋轉
  transform.eulerAngles+=transform.right;
         
//與前者等效,但實際涵義不同,內部使用的四元數
  transform.Rotate(transform.right);

缺點:
對於一個方位,存在多個歐拉角描述,因此無法判斷多個歐 拉角代表的角位移是否相同。
例如角度250,0,0與角度290,180,180是同一個歐拉角,難以直觀判斷。

爲了保證任意方位都只有獨一無二的表示,Unity引擎限制 了角度範圍,即沿X軸旋轉限制在-90到90之間,沿Y與Z軸 旋轉限制在0到360之間。

歐拉角會造成萬向節死鎖。

四元數

因爲歐拉角的缺點,數學家提出了四元數。
缺點:
難於使用,不建議單獨修改某個數值。
•存在不合法的四元數。

兩個四元數相乘可以組合旋轉效果,四元數不能使用+號,表示疊加關係是*號

//物體沿自身y軸旋轉1°
  transform.rotation *= Quaternion.Euler(0,1,0);

//下面兩行等價
//Quaternion.Euler(0, 30, 0) *Quaternion.Euler(0, 20, 0)
//Quaternion.Euler(0, 50, 0);

四元數左乘向量,表示將該向量按照四元數表示的角度旋轉:

Vector3 point = new Vector3(0,0,10);
Vector3 newPoint= Quaternion.Euler(0,30,0) * point ;

所以已知一個向量,已知旋轉角度,就能求得新向量。
比起三角函數求向量,更爲簡單!
在這裏插入圖片描述
練習:

//新向量爲 當前物體的位置對應的正前方10米,偏轉30°
         Vector3 newpoint=  transform.position+ Quaternion.Euler(0, 30, 0) * transform.rotation * new Vector3(0, 0, 10);

練習:求兩個物體之間的切線:
腳本綁定在球體上。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class aaa : MonoBehaviour 
{

    public Transform cube;
	
	// Update is called once per frame
	void Update () 
	{
             
            Vector3 sub = transform.position - cube.position;
            float c = sub.magnitude;
            //算出夾角,球體半徑0.5f
            float angle = Mathf.Asin(0.5f / c) * Mathf.Rad2Deg;
            //要加上cube.position,因爲需要平移
            Vector3 leftpoint =cube.position+ Quaternion.Euler(0, angle, 0) * sub;
            Vector3 rightpoint = cube.position + Quaternion.Euler(0, -angle, 0) * sub;

            Debug.DrawLine(cube.position, leftpoint);
            Debug.DrawLine(cube.position, rightpoint);


    }
}

在這裏插入圖片描述

個人實踐

正因爲四元數和歐拉角各有優缺點,所以unity提供了Rotate函數,它的參數是歐拉角,提供了方便,但內部使用四元數,又避免了歐拉角的缺點。
歐拉角與四元數也廣泛使用在unity開發中。

處了前面的那些,Quaternion結構還提供了不少常用的函數:
比如 Quaternion.AngleAxis,作用與 Quaternion.Euler相似;
Quaternion.LookRotation,作用與transform.LookAt相似;
Quaternion.RotateTowards,勻速旋轉,類比結構vector3中的vector3.MoveTowards 勻速移動。
Quaternion.Lerp,變速旋轉,類比結構vector3中的vector3.Lerp 變速移動。

個人實踐經驗,可以通過向量來理解四元數的旋轉,但必須記住,四元數是一種角度,而不是向量。
Quaternion.LookRotation其含義是把z軸藍色旋轉到某個向量方向需要的角度。
如果unity沒有提供LookRotation,完全可以自己實現—需要先算出兩個向量的夾角,再根據夾角旋轉。
簡單用向量理解,把藍色z軸向量旋轉到某個向量方向。
在這裏插入圖片描述

void Update () 
	{


        if (Input.GetButtonDown("Jump"))
        {

         transform.rotation = Quaternion.LookRotation(cube.position - transform.position);
        }
       
    }

在這裏插入圖片描述
Quaternion.FromToRotation的含義:把某個軸旋轉到某個向量方向需要的角度。

 transform.rotation=  Quaternion.FromToRotation(transform.forward, cube.position-transform.position);

此時的Quaternion.FromToRotation和Quaternion.LookRotation等價。
當我需要把紅軸旋轉到某個向量方向時:

  transform.rotation=  Quaternion.FromToRotation(transform.right, cube.position-transform.position);

在這裏插入圖片描述
假設想讓物體慢慢旋轉,可以旋轉勻速旋轉:

//需要的角度
  Quaternion targ = Quaternion.LookRotation(cube.position - transform.position);
  //當前物體角度,需要的角度,每次的增量歐拉角1°
   transform.rotation=  Quaternion.RotateTowards(transform.rotation, targ, 1);

Quaternion.Angle 也可以算出角度,簡易理解爲兩個物體的藍色軸或紅色軸之間的夾角。
在這裏插入圖片描述
在這裏插入圖片描述

 angle = Quaternion.Angle(transform.rotation, cube.rotation);

在這裏插入圖片描述
到目前爲止我學了算角度:
① 向量之間的三角函數
②向量的dot 點乘
③vector3.angle, 點乘的簡化形式
④Quaternion.Angle,旋轉後軸之間的夾角。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章