hch
2025-06-19 35f08360f1e07c7a8301f7b2031c0779e2998fb5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 
public class MathUtils
{
    public static float GetQuatLength(Quaternion q)
    {
        return Mathf.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
    }
 
    public static Quaternion GetQuatConjugate(Quaternion q)
    {
        return new Quaternion(-q.x, -q.y, -q.z, q.w);
    }
 
    /// <summary>
    /// Logarithm of a unit quaternion. The result is not necessary a unit quaternion.
    /// </summary>
    public static Quaternion GetQuatLog(Quaternion q)
    {
        Quaternion res = q;
        res.w = 0;
 
        if (Mathf.Abs(q.w) < 1.0f)
        {
            float theta = Mathf.Acos(q.w);
            float sin_theta = Mathf.Sin(theta);
 
            if (Mathf.Abs(sin_theta) > 0.0001)
            {
                float coef = theta / sin_theta;
                res.x = q.x * coef;
                res.y = q.y * coef;
                res.z = q.z * coef;
            }
        }
 
        return res;
    }
 
    public static Quaternion GetQuatExp(Quaternion q)
    {
        Quaternion res = q;
 
        float fAngle = Mathf.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
        float fSin = Mathf.Sin(fAngle);
 
        res.w = Mathf.Cos(fAngle);
 
        if (Mathf.Abs(fSin) > 0.0001)
        {
            float coef = fSin / fAngle;
            res.x = coef * q.x;
            res.y = coef * q.y;
            res.z = coef * q.z;
        }
 
        return res;
    }
 
    /// <summary>
    /// SQUAD Spherical Quadrangle interpolation [Shoe87]
    /// </summary>
    public static Quaternion GetQuatSquad(float t, Quaternion q0, Quaternion q1, Quaternion a0, Quaternion a1)
    {
        float slerpT = 2.0f * t * (1.0f - t);
 
        Quaternion slerpP = Slerp(q0, q1, t);
        Quaternion slerpQ = Slerp(a0, a1, t);
 
        return Slerp(slerpP, slerpQ, slerpT);
    }
 
    public static Quaternion GetSquadIntermediate(Quaternion q0, Quaternion q1, Quaternion q2)
    {
        Quaternion q1Inv = GetQuatConjugate(q1);
        Quaternion p0 = GetQuatLog(q1Inv * q0);
        Quaternion p2 = GetQuatLog(q1Inv * q2);
        Quaternion sum = new Quaternion(-0.25f * (p0.x + p2.x), -0.25f * (p0.y + p2.y), -0.25f * (p0.z + p2.z), -0.25f * (p0.w + p2.w));
 
        return q1 * GetQuatExp(sum);
    }
 
    /// <summary>
    /// Smooths the input parameter t.
    /// If less than k1 ir greater than k2, it uses a sin.
    /// Between k1 and k2 it uses linear interp.
    /// </summary>
    public static float Ease(float t, float k1, float k2)
    {
        float f; float s;
 
        f = k1 * 2 / Mathf.PI + k2 - k1 + (1.0f - k2) * 2 / Mathf.PI;
 
        if (t < k1)
        {
            s = k1 * (2 / Mathf.PI) * (Mathf.Sin((t / k1) * Mathf.PI / 2 - Mathf.PI / 2) + 1);
        }
        else
            if (t < k2)
            {
                s = (2 * k1 / Mathf.PI + t - k1);
            }
            else
            {
                s = 2 * k1 / Mathf.PI + k2 - k1 + ((1 - k2) * (2 / Mathf.PI)) * Mathf.Sin(((t - k2) / (1.0f - k2)) * Mathf.PI / 2);
            }
 
        return (s / f);
    }
 
    /// <summary>
    /// We need this because Quaternion.Slerp always uses the shortest arc.
    /// </summary>
    public static Quaternion Slerp(Quaternion p, Quaternion q, float t)
    {
        Quaternion ret;
 
        float fCos = Quaternion.Dot(p, q);
 
        if ((1.0f + fCos) > 0.00001)
        {
            float fCoeff0, fCoeff1;
 
            if ((1.0f - fCos) > 0.00001)
            {
                float omega = Mathf.Acos(fCos);
                float invSin = 1.0f / Mathf.Sin(omega);
                fCoeff0 = Mathf.Sin((1.0f - t) * omega) * invSin;
                fCoeff1 = Mathf.Sin(t * omega) * invSin;
            }
            else
            {
                fCoeff0 = 1.0f - t;
                fCoeff1 = t;
            }
 
            ret.x = fCoeff0 * p.x + fCoeff1 * q.x;
            ret.y = fCoeff0 * p.y + fCoeff1 * q.y;
            ret.z = fCoeff0 * p.z + fCoeff1 * q.z;
            ret.w = fCoeff0 * p.w + fCoeff1 * q.w;
        }
        else
        {
            float fCoeff0 = Mathf.Sin((1.0f - t) * Mathf.PI * 0.5f);
            float fCoeff1 = Mathf.Sin(t * Mathf.PI * 0.5f);
 
            ret.x = fCoeff0 * p.x - fCoeff1 * p.y;
            ret.y = fCoeff0 * p.y + fCoeff1 * p.x;
            ret.z = fCoeff0 * p.z - fCoeff1 * p.w;
            ret.w = p.z;
        }
 
        return ret;
    }
    #region 进制转换
    private static char[] symbolsArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '+', '/' };
    static string symbolStr = new string(symbolsArray, 0, 64);
    /// <summary>
    /// 讲字符串由64进制转为10进制,前缀没用的可用字符-代替
    /// </summary>
    /// <param name="val"></param>
    /// <returns></returns>
    public static int Convert64To10(string val)
    {
        val=val.Trim('-');
        int result = 0;
        long longResult = 0;
        val = val.Trim();
        if (string.IsNullOrEmpty(val)) {
            return result;
        }
        if (val.Equals("0")) return 0;
        for (int i = 0; i < val.Length; i++) {
            if(!symbolStr.Contains(val[i].ToString())) {
                //DesignDebug.LogError(string.Format("64进制格式错误{0}", val));
                return 0;
            }
            else {
                try {
                    int index = 0;
                    for (int j = 0; j < symbolsArray.Length; j++) {
                        if (symbolsArray[j] == val[val.Length - i - 1]) {
                            index = j;
                        }
                    }
                    longResult += (long)System.Math.Pow(64, i) * index;
                    if(longResult>int.MaxValue) {
                        Debug.LogError("超出Int最大值,尝试转换为long类型");
                        return 0;
                    }
                    result = (int)longResult;
                }
                catch {
                    Debug.LogError("运算溢出");
                    return 0;
                }
            }
        }
        return result;
    }
    static char[] outSymbol = new char[65];
    /// <summary>
    /// 将10进制转为64进制的字符串
    /// </summary>
    /// <param name="val"></param>
    /// <returns></returns>
    public static string Convert10To64(int val)
    {
        if (0 == val) return "0";
        int index = 0;
        long longPositive = Mathf.Abs(val);
        for (index = 0; index <= 64; index++) {
            if (longPositive == 0) break;
            outSymbol[outSymbol.Length - index - 1] = symbolsArray[longPositive % 64];
            longPositive /= 64;
        }
        return new string(outSymbol,outSymbol.Length-index,index);
    }
    #endregion
}