Quaternion

 参考:
 https://www.cnblogs.com/tgycoder/p/5103966.html
 https://www.cnblogs.com/tgycoder/p/5106463.html

重新学习一下Quaternion

using UnityEngine;

public class QF : MonoBehaviour
{

    [ContextMenu("GG")]
    void MM()
    {
        
    }

    void RotateAxisY90()
    {
        // 绕Y轴旋转90度的Quaternion, 顺时针旋转
        Quaternion Q1 = Quaternion.identity;
        Q1.eulerAngles = new Vector3(0, 90, 0);

        Quaternion Q2 = Quaternion.AngleAxis(90, Vector3.up);

        Quaternion Q3 = Quaternion.Euler(new Vector3(0, 90, 0));
        Quaternion Q4 = Quaternion.Euler(0, 90, 0);

        Vector3 v1 = Vector3.forward;
        Vector3 v2 = Vector3.right;
        Quaternion Q5 = Quaternion.FromToRotation(v1, v2);
    }

    Quaternion identity()
    {
        Quaternion identity = Quaternion.identity;
        Debug.Log(identity); // (0.0, 0.0, 0.0, 1.0)
        return Quaternion.identity;
    }

    Vector3 eulerAngles()
    {
        // 使用欧拉角表示的旋转, 绕Z轴旋转eulerAngles.z度, 绕X轴旋转eulerAngles.x度, 绕Y轴旋转eulerAngles.y度(按顺序)
        Quaternion identity = Quaternion.identity;
        Vector3 eulerAngles = identity.eulerAngles;
        Debug.Log(eulerAngles); // (0.0, 0.0, 0.0)
        return Vector3.zero;
    }

    float Angle()
    {
        // 两个旋转状态a达到b时需要旋转的最小夹角。[0, 180]
        Quaternion Q1 = Quaternion.identity;
        Quaternion Q2 = Quaternion.identity;
        Q1.eulerAngles = new Vector3(0, 0, 0);
        Q2.eulerAngles = new Vector3(0, 0, 181);
        Debug.Log(Quaternion.Angle(Q1, Q2)); // 179
        return 0;
    }

    Quaternion AngleAxis()
    {
        // Quaternion AngleAxis(float angle, Vector3 axis);
        // 创建一个旋转, 这个旋转是绕axis轴旋转angle度
        // 按左手定则

        // 写法一和写法二的效果是一样的

        // 写法一
        // transform.rotation = Quaternion.AngleAxis(90, Vector3.up);

        // 写法二
        // Quaternion Q1 = Quaternion.identity;
        // Q1.eulerAngles = new Vector3(0, 90, 0);
        // transform.rotation = Q1;

        return Quaternion.identity;
    }

    float Dot()
    {
        // float Dot(Quaternion a, Quaternion b)
        // 根据点乘的结果,判断a和b对应欧拉角的关系。

        // float f = Dot(Q1, Q2);
        // f = x1 * x2 + y1 * y2 + z1 * z2 + w1 * w2
        // f = [-1, 1]
        // f == 1 => Q1.eulerAngles == Q2.eulerAngles
        // f == -1 => 其中一个比另一个多转了360度, Dot(Q1,Q2)顺序无关

        Quaternion Q1 = Quaternion.identity;
        Quaternion Q2 = Quaternion.identity;
        Q1.eulerAngles = new Vector3(0, 40, 0);
        Q2.eulerAngles = new Vector3(0, 40, 0);
        Debug.LogFormat("Q1四元数{0}, Q1欧拉角{1}", Q1, Q1.eulerAngles);
        Debug.LogFormat("Q1四元数{0}, Q1欧拉角{1}", Q1, Q1.eulerAngles);
        Debug.LogFormat("Dot(Q1, Q2) = {0}", Quaternion.Dot(Q1, Q2)); // 1

        Q1.eulerAngles = new Vector3(0, 40, 0);
        Q2.eulerAngles = new Vector3(0, 400, 0);
        Debug.LogFormat("Q1四元数{0}, Q1欧拉角{1}", Q1, Q1.eulerAngles);
        Debug.LogFormat("Q1四元数{0}, Q1欧拉角{1}", Q1, Q1.eulerAngles);
        Debug.LogFormat("Dot(Q1, Q2) = {0}", Quaternion.Dot(Q2, Q1)); // -1

        Debug.Log("--------------------------------");
        // Q1和Q2越接近, 点乘结果越小, 可用于Lerp插值即将完成时的判断
        for (int i = 40; i > 0; i--)
        {
            Q1.eulerAngles = new Vector3(0, 40, 0);
            Q2.eulerAngles = new Vector3(0, 40 - i, 0);
            Debug.LogFormat("Dot(Q1, Q2) = {0}", Quaternion.Dot(Q1, Q2));
        }

        return 0;
    }

    Quaternion Euler()
    {
        // Quaternion Euler(Vector3 euler)
        // Quaternion Euler(float x, float y, float z)
        // 返回一个旋转, 这个旋转是先绕Z轴旋转euler.z/z, 绕X轴旋转euler.y/y, 绕Y轴旋转euler.x/x

        transform.rotation = Quaternion.Euler(new Vector3(0, 0, 45));
        transform.rotation = Quaternion.Euler(0, 90, 0);
        return Quaternion.identity;
    }

    Quaternion FromToRotation()
    {
        Vector3 v1 = Vector3.forward;
        Vector3 v2 = Vector3.right;
        transform.rotation = Quaternion.FromToRotation(v1, v2);
        return Quaternion.identity;
    }

    Quaternion Inverse()
    {
        // Quaternion Inverse(Quaternion rotation)
        // 逆取 
        // q1 = {x, y, z, w}
        // q1_Inverse = {-x, -y, -z, w}
        Quaternion Q1 = new Quaternion(1, 2, 3, 4);
        Quaternion Q2 = Quaternion.Inverse(Q1);
        Debug.LogFormat("Q1四元数{0}, 欧拉角{1}", Q1, Q1.eulerAngles);// Q1四元数(1.0, 2.0, 3.0, 4.0), 欧拉角(352.3, 47.7, 70.3)
        Debug.LogFormat("Q2四元数{0}, 欧拉角{1}", Q2, Q2.eulerAngles);// Q2四元数(-1.0, -2.0, -3.0, 4.0), 欧拉角(318.2, 333.4, 296.6)
        return Quaternion.identity;
    }

    Quaternion Lerp()
    {
        // 线性插值
        // a + (b - a) * t, t被限制在[0, 1]
        Quaternion Q1 = Quaternion.Euler(0, 0, 0);
        Quaternion Q2 = Quaternion.Euler(0, -90, 0);
        for (int i = -10; i <= 10; i++)
        {
            Quaternion Q = Quaternion.Lerp(Q1, Q2, i / 10.0f);
            Debug.DrawLine(Vector3.zero, Q * Vector3.right, Color.red, 10);
        }
        return Quaternion.identity;
    }

    Quaternion LerpUnclamped()
    {
        // 线性插值
        // a + (b - a) * t, t没有限制
        Quaternion Q1 = Quaternion.Euler(0, 0, 0);
        Quaternion Q2 = Quaternion.Euler(0, -90, 0);
        for (int i = -10; i <= 20; i++)
        {
            Quaternion Q = Quaternion.LerpUnclamped(Q1, Q2, i / 10.0f);
            Debug.DrawLine(Vector3.zero + Vector3.right * 2, Q * Vector3.right + Vector3.right * 2, Color.yellow, 10);
        }
        return Quaternion.identity;
    }

    Quaternion LookRotation()
    {
        // Quaternion LookRotation(Vector3 forward)
        // Quaternion LookRotation(Vector3 forward, [DefaultValue("Vector3.up")] Vector3 upwards)

        // 使 transform.up = upwards; transform.forward = forward

        transform.rotation = Quaternion.LookRotation(Vector3.right);
        return Quaternion.identity;
    }

    // NO
    Quaternion RotateTowards()
    {
        // Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)
        // 插值方法,即从返回参数from到to的插值,且返回值的最大角度不超过maxDegreesDelta。
        // maxDegreesDelta是角度值,不是插值系数,当maxDegreesDelta < 0时,将进行逆向插值即从to到from的方向进行插值计算。
        Quaternion Q1 = Quaternion.Euler(0, 0, 0);
        Quaternion Q2 = Quaternion.Euler(0, -90, 0);
        Quaternion Q = Q1;
        for (int i = 0; i <= 10; i++)
        {
            Q = Quaternion.RotateTowards(Q, Q2, 10);
            Debug.DrawLine(Vector3.zero, Q * Vector3.right, Color.yellow, 10);
        }

        return Quaternion.identity;
    }

    Quaternion Slerp()
    {
        return Quaternion.identity;
    }

    Quaternion SlerpUnclamped()
    {
        return Quaternion.identity;
    }

    int GetHashCode()
    {
        Quaternion Q1 = new Quaternion(1, 2, 3, 4);
        Quaternion Q2 = new Quaternion(1, 2, 3, 4);
        Debug.Log(Q1.GetHashCode()); // 265289728
        Debug.Log(Q2.GetHashCode()); // 265289728
        return 0;
    }

    void Set()
    {
        Quaternion Q = new Quaternion(1, 2, 3, 4);
        Q.Set(4, 3, 2, 1);
        Debug.Log(Q);
    }

    void SetFromToRotation()
    {
        // SetFromToRotation(Vector3 fromDirection, Vector3 toDirection)
        // 同 Quaternion FromToRotation()
        // 成员方法,静态方法
    }

    void SetLookRotation()
    {
        // void SetLookRotation(Vector3 view)
        // void SetLookRotation(Vector3 view, [DefaultValue("Vector3.up")] Vector3 up)
        // 同 Quaternion LookRotation()
        // 成员方法,静态方法
    }

    void ToAngleAxis()
    {
        // ToAngleAxis(out float angle, out Vector3 axis)
        // 得到一个旋转是绕哪个轴旋转了多少度

        Quaternion Q1 = Quaternion.Euler(45, 90, 60);
        float angle;
        Vector3 axis;
        Q1.ToAngleAxis(out angle, out axis);
        Debug.LogFormat("绕{0} 旋转{1}度", axis, angle); // 绕(0.8, 0.6, 0.1) 旋转90.9762度

        Quaternion Q2 = Quaternion.identity;
        Q2 = Quaternion.AngleAxis(angle, axis); 
        Debug.LogFormat("Q1 四元数{0}, 欧拉角{1}", Q1, Q1.eulerAngles); // Q1 四元数(0.6, 0.4, 0.1, 0.7), 欧拉角(45.0, 90.0, 60.0)
        Debug.LogFormat("Q2 四元数{0}, 欧拉角{1}", Q2, Q2.eulerAngles); // Q2 四元数(0.6, 0.4, 0.1, 0.7), 欧拉角(45.0, 90.0, 60.0)
    }

    Quaternion OperatorQQ()
    {
        // Quaternion operator *(Quaternion lhs, Quaternion rhs)
        // 先按lhs旋转, 再按rhs旋转, 顺序反了效果也会不一样

        transform.rotation = Quaternion.Euler(0, 45, 0) * Quaternion.Euler(0, 45, 0);
        return Quaternion.identity;
    }

    Vector3 OperatorQV()
    {
        // Vector3 operator *(Quaternion rotation, Vector3 point)
        // 将point旋转rotation
        Debug.Log(Quaternion.Euler(0, 90, 0) * Vector3.forward); // (1, 0, 0)
        return Vector3.zero;
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值