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 ;

所以已知一个向量,已知旋转角度,就能求得新向量。
比起三角函数求向量,更为简单!
unity --22 数学基础- 四元数和欧拉角_第1张图片
练习:

//新向量为 当前物体的位置对应的正前方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 --22 数学基础- 四元数和欧拉角_第2张图片

个人实践

正因为四元数和欧拉角各有优缺点,所以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轴向量旋转到某个向量方向。
unity --22 数学基础- 四元数和欧拉角_第3张图片

void Update () 
	{


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

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

unity --22 数学基础- 四元数和欧拉角_第4张图片
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);

unity --22 数学基础- 四元数和欧拉角_第5张图片
假设想让物体慢慢旋转,可以旋转匀速旋转:

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

Quaternion.Angle 也可以算出角度,简易理解为两个物体的蓝色轴或红色轴之间的夹角。
unity --22 数学基础- 四元数和欧拉角_第6张图片
unity --22 数学基础- 四元数和欧拉角_第7张图片

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

unity --22 数学基础- 四元数和欧拉角_第8张图片
到目前为止我学了算角度:
① 向量之间的三角函数
②向量的dot 点乘
③vector3.angle, 点乘的简化形式
④Quaternion.Angle,旋转后轴之间的夹角。

你可能感兴趣的:(游戏引擎)