zl程序教程

您现在的位置是:首页 >  Java

当前栏目

[学习笔记]三维数学(4)-物体的旋转

2023-02-18 16:42:45 时间

欧拉角

什么是欧拉角

用三个数去存储物体在x、y、z轴的旋转角度。

补充:

  • 为了避免万向节死锁,y和z轴取值范围都是0~360°,x轴是-90°~90°。
  • x和z轴是旋转是相对于自身坐标轴的,y轴旋转永远是相对于世界坐标轴的。 优点
  • 好理解,使用方便
  • 只用三个数表示,占用空间少,在表示方位的数据结构中是占用最少的 缺点
  • 万向节死锁 四元数 什么是四元数
  • 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; 四元数的运算

优点

  • 避免万向节死锁
    • 可使物体沿自身坐标Y轴旋转 this.transform.rotation *= Quaternion.Euler(0,1,0);
    • rotate内部就是使用四元数相乘实现 this.transform.Rotate(Vector3 eulerAngles)缺点
  • 难于使用,不建议单独修改某个数值。
  • 存在不合法的四元数。

实例

使用欧拉角旋转

代码如下:

public class EulerDemo : MonoBehaviour
{
    public Vector3 euler;
    void Update()
    {
        euler = this.transform.eulerAngles;
    }
    private void OnGUI()
    {
        if (GUILayout.RepeatButton("沿x轴旋转"))
        {
            this.transform.eulerAngles += Vector3.right;
        }
        if (GUILayout.RepeatButton("沿y轴旋转"))
        {
            this.transform.eulerAngles += Vector3.up;
        }
        if (GUILayout.RepeatButton("沿z轴旋转"))
        {
            this.transform.eulerAngles += Vector3.forward;
        }
    }

}

使用四元数旋转

代码如下:

public class QuaternionDemo : MonoBehaviour
{
    public Vector3 euler;
    void Update()
    {
        euler = this.transform.eulerAngles;
    }
    private void OnGUI()
    {
        if (GUILayout.RepeatButton("沿x轴旋转"))
        {
            /*
             //方法一
             Quaternion qt = new Quaternion();
            //旋转轴
            Vector3 axis = this.transform.right;
            //旋转角度
            float rad = 1 * Mathf.Deg2Rad;
            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(Vector3.right);

            //方法三
            this.transform.Rotate(Vector3.right);
            */

            this.transform.Rotate(Vector3.right);
        }
        if (GUILayout.RepeatButton("沿y轴旋转"))
        {
            this.transform.Rotate(Vector3.up);
        }
        if (GUILayout.RepeatButton("沿z轴旋转"))
        {
            this.transform.Rotate(Vector3.forward);
        }
    }
}