• 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);
    }
    }

  • 相关阅读:
    使用ZooKeeper实现Java跨JVM的分布式锁
    基于ZooKeeper的分布式锁和队列
    activiti数据库表结构剖析
    visualvm监控jvm及远程jvm监控方法
    使用visualvm 远程监控 JVM
    java jprofile
    Linux服务器上监控网络带宽的18个常用命令
    Redis-sentinel哨兵模式集群方案配置
    电容的去耦半径
    DC-DC BUCK电源芯片的基本原理和组成
  • 原文地址:https://www.cnblogs.com/bearworks/p/5250319.html
Copyright © 2020-2023  润新知