| 2313 | |
| 2314 | COVERAGE(HMM_SLerp, 1) |
| 2315 | static inline HMM_Quat HMM_SLerp(HMM_Quat Left, float Time, HMM_Quat Right) |
| 2316 | { |
| 2317 | ASSERT_COVERED(HMM_SLerp); |
| 2318 | |
| 2319 | HMM_Quat Result; |
| 2320 | |
| 2321 | float Cos_Theta = HMM_DotQ(Left, Right); |
| 2322 | |
| 2323 | if (Cos_Theta < 0.0f) { /* NOTE(lcf): Take shortest path on Hyper-sphere */ |
| 2324 | Cos_Theta = -Cos_Theta; |
| 2325 | Right = HMM_Q(-Right.X, -Right.Y, -Right.Z, -Right.W); |
| 2326 | } |
| 2327 | |
| 2328 | /* NOTE(lcf): Use Normalized Linear interpolation when vectors are roughly not L.I. */ |
| 2329 | if (Cos_Theta > 0.9995f) { |
| 2330 | Result = HMM_NLerp(Left, Time, Right); |
| 2331 | } else { |
| 2332 | float Angle = HMM_ACosF(Cos_Theta); |
| 2333 | float MixLeft = HMM_SinF((1.0f - Time) * Angle); |
| 2334 | float MixRight = HMM_SinF(Time * Angle); |
| 2335 | |
| 2336 | Result = _HMM_MixQ(Left, MixLeft, Right, MixRight); |
| 2337 | Result = HMM_NormQ(Result); |
| 2338 | } |
| 2339 | |
| 2340 | return Result; |
| 2341 | } |
| 2342 | |
| 2343 | COVERAGE(HMM_QToM4, 1) |
| 2344 | static inline HMM_Mat4 HMM_QToM4(HMM_Quat Left) |