三维数学(二)

欧拉角 

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

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;

  

 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);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值