Advertisement
VirtLands

Quaternions by Wavey

Jun 23rd, 2014
336
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; ID: 490
  2. ; Author: Wavey
  3. ; Date: 2002-11-15 13:05:49
  4. ; Title: Quaternions
  5. ; Description: Some basic quaternion functions (useful for rotating objects)
  6.  
  7. ; Quat.bb : v1.0 : 15/11/02
  8.  
  9. ; A tutorial on how to use this file is at http://www.dscho.co.uk/blitz/tutorials/quaternions.shtml
  10.  
  11. ; Types
  12. Type Rotation
  13.     Field pitch#, yaw#, roll#
  14. End Type
  15.  
  16. Type Quat
  17.     Field w#, x#, y#, z#
  18. End Type
  19.  
  20. ; Change these constants if you notice slips in accuracy
  21. Const QuatToEulerAccuracy# = 0.001
  22. Const QuatSlerpAccuracy#   = 0.0001
  23.  
  24. ; convert a Rotation to a Quat
  25. Function EulerToQuat(out.Quat, src.Rotation)
  26.     ; NB roll is inverted due to change in handedness of coordinate systems
  27.     Local cr# = Cos(-src\roll/2)
  28.     Local cp# = Cos(src\pitch/2)
  29.     Local cy# = Cos(src\yaw/2)
  30.  
  31.     Local sr# = Sin(-src\roll/2)
  32.     Local sp# = Sin(src\pitch/2)
  33.     Local sy# = Sin(src\yaw/2)
  34.  
  35.     ; These variables are only here to cut down on the number of multiplications
  36.     Local cpcy# = cp * cy
  37.     Local spsy# = sp * sy
  38.     Local spcy# = sp * cy
  39.     Local cpsy# = cp * sy
  40.  
  41.     ; Generate the output quat
  42.     out\w = cr * cpcy + sr * spsy
  43.     out\x = sr * cpcy - cr * spsy
  44.     out\y = cr * spcy + sr * cpsy
  45.     out\z = cr * cpsy - sr * spcy
  46. End Function
  47.  
  48. ; convert a Quat to a Rotation
  49. Function QuatToEuler(out.Rotation, src.Quat)
  50.     Local sint#, cost#, sinv#, cosv#, sinf#, cosf#
  51.     Local cost_temp#
  52.  
  53.     sint = (2 * src\w * src\y) - (2 * src\x * src\z)
  54.     cost_temp = 1.0 - (sint * sint)
  55.  
  56.     If Abs(cost_temp) > QuatToEulerAccuracy
  57.         cost = Sqr(cost_temp)
  58.     Else
  59.         cost = 0
  60.     EndIf
  61.  
  62.     If Abs(cost) > QuatToEulerAccuracy
  63.         sinv = ((2 * src\y * src\z) + (2 * src\w * src\x)) / cost
  64.         cosv = (1 - (2 * src\x * src\x) - (2 * src\y * src\y)) / cost
  65.         sinf = ((2 * src\x * src\y) + (2 * src\w * src\z)) / cost
  66.         cosf = (1 - (2 * src\y * src\y) - (2 * src\z * src\z)) / cost
  67.     Else
  68.         sinv = (2 * src\w * src\x) - (2 * src\y * src\z)
  69.         cosv = 1 - (2 * src\x * src\x) - (2 * src\z * src\z)
  70.         sinf = 0
  71.         cosf = 1
  72.     EndIf
  73.  
  74.     ; Generate the output rotation
  75.     out\roll = -ATan2(sinv, cosv) ;  inverted due to change in handedness of coordinate system
  76.     out\pitch = ATan2(sint, cost)
  77.     out\yaw = ATan2(sinf, cosf)
  78. End Function
  79.  
  80. ; use this to interpolate between quaternions
  81. Function QuatSlerp(res.Quat, start.Quat, fin.Quat, t#)
  82.     Local scaler_w#, scaler_x#, scaler_y#, scaler_z#
  83.     Local omega#, cosom#, sinom#, scale0#, scale1#
  84.  
  85.     cosom = start\x * fin\x + start\y * fin\y + start\z * fin\z + start\w * fin\w
  86.  
  87.     If cosom <= 0.0
  88.         cosom = -cosom
  89.         scaler_w = -fin\w
  90.         scaler_x = -fin\x
  91.         scaler_y = -fin\y
  92.         scaler_z = -fin\z
  93.     Else
  94.         scaler_w = fin\w
  95.         scaler_x = fin\x
  96.         scaler_y = fin\y
  97.         scaler_z = fin\z
  98.     EndIf
  99.  
  100.     If (1 - cosom) > QuatSlerpAccuracy
  101.         omega = ACos(cosom)
  102.         sinom = Sin(omega)
  103.         scale0 = Sin((1 - t) * omega) / sinom
  104.         scale1 = Sin(t * omega) / sinom
  105.     Else
  106.         ; Angle too small: use linear interpolation instead
  107.         scale0 = 1 - t
  108.         scale1 = t
  109.     EndIf
  110.  
  111.     res\x = scale0 * start\x + scale1 * scaler_x
  112.     res\y = scale0 * start\y + scale1 * scaler_y
  113.     res\z = scale0 * start\z + scale1 * scaler_z
  114.     res\w = scale0 * start\w + scale1 * scaler_w
  115. End Function
  116.  
  117. ; result will be the same rotation as doing q1 then q2 (order matters!)
  118. Function MultiplyQuat(result.Quat, q1.Quat, q2.Quat)
  119.     Local a#, b#, c#, d#, e#, f#, g#, h#
  120.  
  121.     a = (q1\w + q1\x) * (q2\w + q2\x)
  122.     b = (q1\z - q1\y) * (q2\y - q2\z)
  123.     c = (q1\w - q1\x) * (q2\y + q2\z)
  124.     d = (q1\y + q1\z) * (q2\w - q2\x)
  125.     e = (q1\x + q1\z) * (q2\x + q2\y)
  126.     f = (q1\x - q1\z) * (q2\x - q2\y)
  127.     g = (q1\w + q1\y) * (q2\w - q2\z)
  128.     h = (q1\w - q1\y) * (q2\w + q2\z)
  129.  
  130.     result\w = b + (-e - f + g + h) / 2
  131.     result\x = a - ( e + f + g + h) / 2
  132.     result\y = c + ( e - f + g - h) / 2
  133.     result\z = d + ( e - f - g + h) / 2
  134. End Function
  135.  
  136. ; convenience function to fill in a rotation structure
  137. Function FillRotation(r.Rotation, pitch#, yaw#, roll#)
  138.     r\pitch = pitch
  139.     r\yaw = yaw
  140.     r\roll = roll
  141. End Function
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement