Unity—欧拉角,四元数

今天继续学习了欧拉角和四元数,明天开始“合成大西瓜”!

目录

向量的运算(续)

点乘,又称“内积”或“点积”

公式:

几何意义:

应用:

结果与角度的关系

叉乘

公式

几何意义

应用:

叉乘所得向量的模长与角度关系:

欧拉角

什么是欧拉角

优点:

缺点:

1.方位的表达方式不唯一

2.万向节死锁

四元数

什么是四元数

优点:

缺点

四元数运算

·与向量相乘

·与四元数相乘


向量的运算(续)

点乘,又称“内积”或“点积”

公式:

各分量乘积和[x1,y1,z1]·[x2,y2,z2]=x1x2+y1y2+z1z2

几何意义:

两个向量的单位向量相乘后再乘以二者夹角的余弦值

a·b=|a|·|b|cos

API:float dot=Vector3.Dot(va,vb);

用点乘求夹角:

把两向量做narmalized处理,两个标准化向量结果就是cos,再反余弦Mathf.Acos就得到角度

点乘结果得到的角是小角

应用:

对于标准化过的向量,点乘结果等于两向量夹角的余弦值

计算两向量夹角

public Transform t1, t2;

float dot = Vector3.Dot(t1.position.normalized, t2.position.normalized);

float  angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

结果与角度的关系

对于标准化过的向量,方向完全相同,点乘结果为1,完全相反,点乘结果为-1,互相垂直为0

Unity—欧拉角,四元数_第1张图片

 

如果两个向量夹角大于60度,则

if(angle>60){}或if(dot<0.5f){}//优点:省着CPU再去算角度

private void Update()

    {

        Debug.DrawLine(Vector3.zero, t1.position,Color.red);

        Debug.DrawLine(Vector3.zero, t2.position,Color.red);

        float dot = Vector3.Dot(t1.position.normalized, t2.position.normalized);

        float  angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

}

Unity—欧拉角,四元数_第2张图片

 

叉乘

又称“叉积”或“外积”

公式

[x1,y1,z1]*[x2,y2,y3]=[y1*z2-z1*y2,z1*x2-x1*z2,x1*y2-y1*x2]

几何意义

结果为两个所组成面的垂直向量,模长为两向量模长乘积再乘夹角的正弦值

API:Vector3 vector=Vector3.Cross(a,b);

应用:

·创建垂直于平面的向量

·判断两条向量相对位置,即顺逆时针关系

Unity—欧拉角,四元数_第3张图片

Unity—欧拉角,四元数_第4张图片

 private void Update()

    {

       Debug.DrawLine(Vector3.zero, t1.position, Color.red);

        Debug.DrawLine(Vector3.zero, t2.position, Color.red);

        dot = Vector3.Dot(t1.position.normalized, t2.position.normalized);

        angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

        Vector3 cross = Vector3.Cross(t1.position, t2.position);

        if (cross.y < 0)

            angle = 360 - angle;

        Debug.DrawLine(Vector3.zero, cross, Color.green);

}

Unity—欧拉角,四元数_第5张图片

 

叉乘所得向量的模长与角度关系:

0~90度角

Vector3 cross=Vector3.Cross(a.normalized,b.normalized);

float angle=Mathf.Asin(cross.magnitude)*Mathf.Rad2Deg;

(很少应用)

Unity—欧拉角,四元数_第6张图片

Unity—欧拉角,四元数_第7张图片 

 

欧拉角

什么是欧拉角

使用三个角度来保存方位

x与z沿自身坐标系旋转,y沿世界坐标系旋转

API:Vector3 eulerAngle=this.transform.eulerAngles;

优点:

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

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

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

缺点:

1.方位的表达方式不唯一

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

例:角度0,5,0与角度0,365,0

角度250,0,0与角度290,180,180

为了保证任意方位都只有独一无二的表示,unity限制了角度的范围,即沿x轴旋转限制在-90到90之间,沿y与x轴旋转限制在0到360之间(在unity编译器中不限制,在代码中限制)

Vector3 euler=this.transform.eulerAngles;

注意:欧拉角没有方向、大小的概念

因为三维向量,包含x,y,z,所以在Unity中欧拉角的数据类型为Vector3

欧拉角的x,y,z表示各个轴上的旋转角度

Vector3 por=this.transform.position;

位置,有方向(从世界原点指向当前位置),有大小(当前位置到世界原点间距)

向量的x,y,z,表示各个轴上的有向位移

可用来检测欧拉角  

public Vector3 euler;

    //可以用来检测欧拉角

    public void OnGUI()

    {

        euler = this.transform.eulerAngles;

        if (GUILayout.RepeatButton("沿X轴旋转"))

            this.transform.eulerAngles += new Vector3(1, 0, 0);

        if (GUILayout.RepeatButton("沿y轴旋转"))

            this.transform.eulerAngles += Vector3.up;

        if (GUILayout.RepeatButton("沿z轴旋转"))

            this.transform.eulerAngles += new Vector3(0, 0,1);

}

2.万向节死锁

物体沿x轴旋转+(-)90度,自身坐标系z轴与世界坐标系y轴将重合,此时再沿y或z轴旋转时,将失去一个自由度。

在万向节死锁情况下,规定沿z轴完成绕数值轴的全部旋转,即此时y轴旋转为0

Unity—欧拉角,四元数_第8张图片

 

四元数

什么是四元数

Quaternion在3D图形学中代表旋转,由一个三维向量(x,y,z)和一个标量(w)组成

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

x=sin(θ/2)*V.x     y=sin(θ/2)*V.y

z=sin(θ/2)*V.z     w=cos(θ/2)

x,y,z,w的取值范围是-1到1

API:Quaternion  qt=this.transform.rotation;

 public void OnGUI()

    {

        euler = this.transform.eulerAngles;

        if (GUILayout.Button("设置物体旋转角度"))

        {

            //旋转轴

            Vector3 axis = t1.position - t2.position;

            //旋转弧度

            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;

        }

}

优点:

避免万向节死锁

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

可使物体沿自身坐标Y轴旋转

public void OnGUI()

    {

        euler = this.transform.eulerAngles;

        if (GUILayout.RepeatButton("沿X轴旋转"))

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

        if (GUILayout.RepeatButton("沿y轴旋转"))

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

        if (GUILayout.RepeatButton("沿z轴旋转"))

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

    }

this.transform.Rotate(Vector3 eulerAngles)

内部就是使用四元数相乘实现

缺点

·难于使用,不建议单独修改某个数值

Unity—欧拉角,四元数_第9张图片

 

·存在不合法的四元数

四元数运算

·与向量相乘

四元数左乘向量,表示将该向量按照四元数表示的角度旋转

例:Vector3 point =new Vector3(0,0,10);//向前走10米

Vector3 newpoint=Quaternion.Euler(0,30,0)(沿y轴旋转30度)*point;

·与四元数相乘

两个四元数相乘可以组合旋转效果

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

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

rotation01与rotation02相同

Unity—欧拉角,四元数_第10张图片

你可能感兴趣的:(UNITY基础,unity,游戏引擎)