Advertisement
WavePlayz

Smooth catmull quaternion interpolation

Jun 19th, 2025
376
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const EPSILON = 1e-6    
  2.  
  3. // Rotation order: Yaw (Y) → Pitch (X) → Roll (Z)    
  4. function eulerToQuat(pitch, yaw, roll) {    
  5.     const d2r = Math.PI / 180    
  6.    
  7.     // NEGATE yaw to match left-handed rotation around Y-axis    
  8.     const hy = -yaw * 0.5 * d2r    
  9.     const hp = pitch * 0.5 * d2r    
  10.     const hr = roll  * 0.5 * d2r    
  11.    
  12.     // trig shortcuts    
  13.     const cy = Math.cos(hy), sy = Math.sin(hy)    
  14.     const cp = Math.cos(hp), sp = Math.sin(hp)    
  15.     const cr = Math.cos(hr), sr = Math.sin(hr)    
  16.    
  17.     // q = qYaw * qPitch * qRoll    
  18.     const x = cy * sp * cr + sy * cp * sr    
  19.     const y = sy * cp * cr - cy * sp * sr    
  20.     const z = cy * cp * sr + sy * sp * cr    
  21.     const w = cy * cp * cr - sy * sp * sr    
  22.        
  23.     return [x, y, z, w]    
  24. }    
  25.    
  26. function normalizeQuat(q) {    
  27.     const mag = Math.sqrt(q.w * q.w + q.x * q.x + q.y * q.y + q.z * q.z)    
  28.     if (mag === 0) return { w: 1, x: 0, y: 0, z: 0 }    
  29.     return {    
  30.         w: q.w / mag,    
  31.         x: q.x / mag,    
  32.         y: q.y / mag,    
  33.         z: q.z / mag    
  34.     }    
  35. }    
  36.    
  37. function slerpQuat(a, b, t) {    
  38.     let dot = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w    
  39.    
  40.     if (dot < 0) {    
  41.         b = { x: -b.x, y: -b.y, z: -b.z, w: -b.w }    
  42.         dot = -dot    
  43.     }    
  44.    
  45.     if (dot > 1 - EPSILON) {    
  46.         return normalizeQuat({    
  47.             x: a.x + (b.x - a.x) * t,    
  48.             y: a.y + (b.y - a.y) * t,    
  49.             z: a.z + (b.z - a.z) * t,    
  50.             w: a.w + (b.w - a.w) * t    
  51.         })    
  52.     }    
  53.    
  54.     const theta_0 = Math.acos(dot)    
  55.     const sin_theta_0 = Math.sin(theta_0)    
  56.    
  57.     const theta = theta_0 * t    
  58.     const sin_theta = Math.sin(theta)    
  59.    
  60.     const s0 = Math.cos(theta) - dot * sin_theta / sin_theta_0    
  61.     const s1 = sin_theta / sin_theta_0    
  62.    
  63.     return {    
  64.         x: s0 * a.x + s1 * b.x,    
  65.         y: s0 * a.y + s1 * b.y,    
  66.         z: s0 * a.z + s1 * b.z,    
  67.         w: s0 * a.w + s1 * b.w    
  68.     }    
  69. }    
  70.    
  71. // Catmull-Rom spline interpolation for quaternions (w/x/y/z object format)    
  72. function catmull(q0, q1, q2, q3, t) {    
  73.     let a = slerpQuat(q0, q1, t + 1)    
  74.     let b = slerpQuat(q1, q2, t)    
  75.     let c = slerpQuat(q2, q3, t - 1)    
  76.    
  77.     let d = slerpQuat(a, b, (t + 1) / 2)    
  78.     let e = slerpQuat(b, c, t / 2)    
  79.    
  80.     return slerpQuat(d, e, t)    
  81. }
  82.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement