三维数学(二)

欧拉角 

使用物体在三个旋转轴上的旋转角度来保存方位 

API:

Transform.eulerAngles:返回或设置物体的欧拉角

优点

1.仅使用三个数字表达方位,占用空间小

2.沿坐标轴旋转的单位为角度,符合人的思考方式

3.任意三个数字都是合法的,不存在不合法的欧拉角

缺点

1.方位的表达方式不唯一:对于一个方位,存在多个欧拉角描述,因此无法判断多个欧拉角代表的角位移是否相同

例如:

  • 角度(0,5,0)与角度(0,365,0)
  • 角度(0,-5,0)与角度(0,355,0)
  • 角度(250,0,0)与角度(290,180,180)

为了保证任意方位都只有独一无二的表示,Unity引擎限制了角度范围,即沿X轴旋转限制在-90~90之间,沿Y与Z轴旋转限制在0~360之间

2.万向节死锁

  • 物体沿X轴旋转±90度,自身坐标系Z轴与世界坐标系Y轴将重合,此时再沿Y或Z轴旋转时,将失去一个自由度
  • 在万向节死锁情况下,规定沿Y轴完成绕竖直轴的全部旋转,即此时Z轴旋转为0
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EulerDemo : MonoBehaviour
{
    private void OnGUI()
    {
        if (GUILayout.RepeatButton("沿x轴旋转"))
        {
            Vector3 pos = this.transform.position;
            //有方向(从世界原点指向当前位置),有大小(当前位置到世界原点的间距)
            //向量x,y,z,表示各个轴向上的有向位移

            Vector3 euler = this.transform.eulerAngles;
            //是向量类型,但没有方向和大小
            //欧拉角x,y,z表示各个轴上的旋转角度

            //各分量相加,欧拉角x增加1度
            this.transform.eulerAngles += new Vector3(1, 0, 0);
        }

        if (GUILayout.RepeatButton("沿y轴旋转"))
        {
            //this.transform.eulerAngles+=new Vector3(0,1,0);
            this.transform.eulerAngles += Vector3.up;
        }

        if (GUILayout.RepeatButton("沿z轴旋转"))
        {
            this.transform.eulerAngles += new Vector3(0, 0, 1);
            this.transform.eulerAngles += Vector3.forward;
        }
    }
}

四元数

Quaternion在3D图形学中代表旋转,由一个三维向量(X/Y/Z)和一个标量(W)组成 

旋转轴为V,旋转弧度为0,如果使用四元数表示,则四个分量为:

  • x=sin(0/2)*V.x
  • y=sin(0 /2)*V.y
  • z=sin(0 /2)*V.z
  • w=cos(0 /2)

X、Y、Z、W的取值范围是-1~1

//旋转轴
Vector3 axis = Vector3.up;
//旋转弧度
float rad = 50 * Mathf.Deg2Rad;

Quaternion qt = new Quaternion();
qt.x = Mathf.Sin(rad / 2) * axis.x;
qt.y = Mathf.Sin(rad / 2) * axis.y;
qt.z = Mathf.Sin(rad / 2) * axis.z;
qt.w = Mathf.Cos(rad / 2);

this.transform.rotation = qt;

以上代码可简化为

//旋转轴
Vector3 axis = Vector3.up;
//旋转弧度
float rad = 50 * Mathf.Deg2Rad;

this.transform.rotation = Quaternion.Euler(0, 50, 0);

API:

Quaternion.Euler(float x, float y, float z): 返回一个围绕z轴旋转z度、围绕x轴旋转 x度、围绕y轴旋转y度(按该顺序应用)的旋转

private void OnGUI()
{

    if (GUILayout.Button("沿x轴旋转"))
    {
        this.transform.rotation *= Quaternion.Euler(1, 0, 0);
        //this.transform.Rotate(1, 0, 0);
    }

    if (GUILayout.Button("沿y轴旋转"))
    {
        this.transform.rotation *= Quaternion.Euler(0, 1, 0);
    }

    if (GUILayout.Button("沿z轴旋转"))
    {
        this.transform.rotation *= Quaternion.Euler(0, 0, 1);
    }
}

其中

this.transform.rotation *= Quaternion.Euler(1, 0, 0);

等同于

this.transform.Rotate(1, 0, 0);

优点:避免万向节死锁

缺点

  • 难于使用,不建议单独修改某个数值
  • 存在不合法的四元数

基本运算 

1.与向量相乘:四元数左乘向量,表示将该向量按照四元数表示的角度旋转 

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

三维数学(二)_第1张图片  

 2.与四元数相乘:两个四元数相乘可以组合旋转效果

Quaternion rotation01 = Quaternion.Euler(0, 30, 0) * Quaternion.Euler(0, 20, 0);

 等同于

Quaternion rotation02 = Quaternion.Euler(0, 50, 0);

常用API

Quaternion.LookRotation(Vector3 forward, Vector3 upwards= Vector3.up) ​:

forward 要查看的方向
upwards 定义向上方向的向量

原理:Z轴将与forward对齐,X轴与forward和upwards之间的交叉乘积对齐,Y轴与Z和X之间的交叉乘积对齐 

public Transform target;

//当前物体注视target旋转
Vector3 dir = target.position - this.transform.position;
this.transform.rotation = Quaternion.LookRotation(dir);
//this.transform.LookAt(target);

Quaternion.Lerp(Quaternion a, Quaternion b, float t)

a 起始值,当 t = 0 时返回
b 结束值,当 t = 1 时返回
t 插值比率
public Transform target;

//差值旋转
Quaternion dir = Quaternion.LookRotation(target.position - this.transform.position);
this.transform.rotation = Quaternion.Lerp(this.transform.rotation, dir, 0.1f);
if (Quaternion.Angle(this.transform.rotation, dir) < 0.1f)
{
    this.transform.rotation = dir;
}

Quaternion.FromToRotation​(Vector3 fromDirection, Vector3 toDirection) :创建一个从fromDirection旋转到toDirection的旋转

public Transform target;

//x轴注视旋转
//this.transform.right = target.position - this.transform.position;
Quaternion dir = Quaternion.FromToRotation(Vector3.right, target.position - this.transform.position);
this.transform.rotation = dir;

Quaternion.AngleAxis(float angle, Vector3 axis):创建一个围绕axis旋转angle度的旋转

public Transform target;

//轴/角旋转
this.transform.rotation = Quaternion.AngleAxis(50, Vector3.up);

你可能感兴趣的:(回收站,游戏引擎,unity)