• Two kinds of Quaternion SlerpImp (Unity)


    using UnityEngine;
    using System.Collections;

    public class SlerpImp
    {
    static float Dot(Quaternion a, Quaternion b)
    {
    return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
    }

    static Quaternion Lerp(Quaternion a, Quaternion b, float t)
    {
    return new Quaternion(a.x * (1 -t) + b.x * t,
    a.y * (1 -t) + b.y * t,
    a.z * (1 -t) + b.z * t,
    a.w * (1 -t) + b.w * t);
    }

    static Quaternion Inverse(Quaternion a)
    {
    a.x = -a.x;
    a.y = -a.y;
    a.z = -a.z;

    return a;
    }

    public static Quaternion Slerp1(Quaternion a, Quaternion b, float t)
    {
    t = Mathf.Clamp01 (t);

    float similar = Dot(a,b);
    float sign = 1.0f;
    if(similar >= 1f - Mathf.Epsilon)
    return a == Quaternion.identity ? Quaternion.identity : Lerp(a,b,t);
    else if (similar < 0f)
    {
    a.x = -a.x;
    a.y = -a.y;
    a.z = -a.z;
    a.w = -a.w;
    sign = -1f;
    }

    Quaternion result = Quaternion.identity;

    // 0-pi, otherwise, inverse the xyz axis space
    float aw = Mathf.Acos(a.w);
    float bw = Mathf.Acos(b.w);

    float saw = new Vector3(a.x, a.y, a.z).magnitude;
    float sbw = new Vector3(b.x, b.y, b.z).magnitude;

    aw = saw != 0.0f ? aw * (1 - t) / saw : 0.0f;
    bw = sbw != 0.0f ? bw * t / sbw : 0.0f;
    result.x = a.x * aw + b.x * bw;
    result.y = a.y * aw + b.y * bw;
    result.z = a.z * aw + b.z * bw;

    Vector3 v = new Vector3(result.x, result.y, result.z);
    float theta = v.magnitude;
    if (theta == 0f)
    return Quaternion.identity;

    float sintheta = sign * Mathf.Sin(theta) / theta;
    result.x *= sintheta;
    result.y *= sintheta;
    result.z *= sintheta;
    result.w = sign * Mathf.Cos(theta);

    return result;
    }

    public static Quaternion Slerp2(Quaternion a, Quaternion b, float t)
    {
    t = Mathf.Clamp01 (t);

    float sign = 1.0f;
    float similar = Dot(a,b);
    if(similar >= 1f - Mathf.Epsilon)
    return a == Quaternion.identity ? Quaternion.identity : Lerp(a,b,t);
    else if (similar < 0f)
    {
    a.x = -a.x;
    a.y = -a.y;
    a.z = -a.z;
    a.w = -a.w;
    sign = -1.0f;
    }

    Quaternion result = Inverse(a);
    result *= b;
    Vector3 v = new Vector3(result.x, result.y, result.z);
    float sintheta = v.magnitude;
    // 0-pi, otherwise, inverse the xyz axis space
    float theta = Mathf.Acos(result.w);
    theta *= t;
    sintheta = sign * Mathf.Sin(theta) / sintheta;
    result.x *= sintheta;
    result.y *= sintheta;
    result.z *= sintheta;
    result.w = sign * Mathf.Cos(theta);
    return a * result;
    }

    }


    [ExecuteInEditMode]
    public class SlerpTest : MonoBehaviour {


    public int callTimes = 1000000;
    [Range(0,1)]
    public float t = 0.3f;
    // Use this for initialization
    void Start ()
    {

    int callCount = callTimes;
    float time = Time.realtimeSinceStartup;
    while(callCount-- > 0)
    {
    SlerpImp.Slerp1(this.transform.rotation, Camera.main.transform.rotation, t);
    }
    Debug.LogWarning("Slerp1 "+ callTimes + " calls took: " + (Time.realtimeSinceStartup - time));

    callCount = callTimes;
    time = Time.realtimeSinceStartup;
    while(callCount-- > 0)
    {
    SlerpImp.Slerp2(this.transform.rotation, Camera.main.transform.rotation, t);
    }
    Debug.LogWarning("Slerp2 "+ callTimes + " calls took: " + (Time.realtimeSinceStartup - time));

    callCount = callTimes;
    time = Time.realtimeSinceStartup;
    while(callCount-- > 0)
    {
    Quaternion.Slerp(this.transform.rotation, Camera.main.transform.rotation, t);
    }
    Debug.LogWarning("UnityS "+ callTimes + " calls took: " + (Time.realtimeSinceStartup - time));
    }


    void Update()
    {
    Debug.LogWarning("------------------");
    Debug.LogWarning("Slerp1: " + SlerpImp.Slerp1(this.transform.rotation, Camera.main.transform.rotation, t).eulerAngles);
    Debug.LogWarning("Slerp2: " + SlerpImp.Slerp2(this.transform.rotation, Camera.main.transform.rotation, t).eulerAngles);
    Debug.LogWarning("UnitySLerp: " + Quaternion.Slerp(this.transform.rotation, Camera.main.transform.rotation, t).eulerAngles);
    }
    }

  • 相关阅读:
    git使用记录
    【转】话说我打算一天学完object c语法,系列1--------来自书Objective-c程序设计
    【转】看源代码那些事
    中英文对照 —— 数学定律定理(公式及其描述)
    CUDA+OpenGL混合编程
    简明欧洲史
    简明欧洲史
    CUDA一维纹理内存
    CUDA中的常量内存__constant__
    CUDA线程协作之共享存储器“__shared__”&&“__syncthreads()”
  • 原文地址:https://www.cnblogs.com/bearworks/p/5250319.html
Copyright © 2020-2023  润新知