Shinmera / 3d-math

A library implementing the necessary linear algebra math for 2D and 3D computations
https://shinmera.github.io/3d-math/
zlib License
14 stars 2 forks source link

Add to documentation a note about quaternion convention #5

Open KislyjKisel opened 3 weeks ago

KislyjKisel commented 3 weeks ago

q*q and maybe some other functions use the less popular Shuster's convention, which may be confusing to some. (Maybe add traditional variants?) (qmat uses the formula that is used with traditional quaternions (e.g. second element in the first column uses +, whereas with alternative convention - is used))

KislyjKisel commented 3 weeks ago
* (defvar q1 (qfrom-angle (vec3 0 1 0) (/ pi 2.0)))
* (defvar q2 (qfrom-angle (vec3 0 0 1) (/ pi 2.0)))
* (defvar v (vec3 0 0 1))
* (q* q1 v)
(VEC3 0.99999994 0.0 0.0)
* (q* q2 *)
(VEC3 0.0 0.9999999 0.0)
* (q* (q* q2 q1) v)
(VEC3 0.9999999 0.0 2.9802322e-8)
* (q* (alt-q* q2 q1) v)
(VEC3 0.0 0.9999999 2.9802322e-8)
* (q* (q* q1 q2) v)
(VEC3 0.0 0.9999999 2.9802322e-8)

Rotating (0 0 1) around (0 1 0) by pi/2 is (1 0 0) (as is); rotating (1 0 0) around (0 0 1) by pi/2 is (0 1 0), but if the two rotations are combined in RTL order then the result is (1 0 0). If the traditional (here alt-q*) multiplication is used then the result is correct. If the order is LTR then the result is correct as is. Quote from the current docstring for q*: "If a quaternion is passed, the rotations are combined in a right-to-left order". I've also confirmed (on 1 example only) that (q* q3 (q* (q* q1 q2) v)) = (q* (q* q1 q2 q3) v) = (q* (alt-q* q3 (alt-q* q2 q1)) v).

Shinmera commented 3 weeks ago

I've fixed the order issue in the presence of more than two quaternions. As for the convention I'm afraid you'll have to elaborate a bit for me to understand the issue.

KislyjKisel commented 2 weeks ago

The article "Quaternions and spatial rotation" on wikipedia states that there are 2 conventions used for quaternions and they have differently defined multiplication (and some other operations, the article mentions vector rotation and conversion to a matrix). q* in this library uses the one where there is a minus before the cross product: for example (+ (* yb za)) + (- (* zb ya)) is equal to the x component of the negated cross product. This corresponds to the alternative convention. There is a paper linked in the article that argues against using it to avoid confusion.