Quaternions are used as a replacement for Euler angles. Thus, your approach defeats their goal. Instead of trying to use Euler angles, apply the properties of a quaternion.
A quaternion has 4 components, 3 vector components and a scalar component.
q = x*i + y*j + z*k + w
Thus, the quaternion has the vector part x*i + y*j + z*k and the scalar part w . Thus, the vector is a quaternion with a zero scalar or real component.
It is important to note that a vector multiplied by a quaternion is another vector. This can be easily proved using the rules of multiplication of quaternion elements (on the left as an exercise for the reader).
The reverse quaternion is simply its conjugate divided by its magnitude. The quaternion conjugate w + (x*i + y*j + z*k) is simply w - (x*i + y*j + z*k) , and its value is sqrt(x*x + y*y + z*z + w*w) .
The rotation of a vector is simply a vector obtained by rotating this vector at an angle around its axis. Rotational quaternions represent such a rotation on the angular axis, as shown here.
The vector v can be rotated around the axis and through the angle represented by the quaternion of rotation q by conjugating v from q . In other words,
v' = q * v * inverse(q)
Where v' is the rotated vector, and q * v * inverse(q) is the pairing operation.
Since the quaternion is a rotation, it can be reasonably assumed that its value is unity, which makes inverse(q) = q* where q* conjugate to q .
When dividing q into the real part s and the vector part u and simplifying the operation of the quaternion (as shown here here ),
v' = 2 * dot(u, v) * u + (s*s - dot(u, u)) * v + 2 * s * cross(u, v)
Where dot returns the product of the points of two vectors, and cross returns the transverse product of two vectors.
By entering the above code (pseudo),
function rotate(v: vector3, q: quaternion4) -> vector3 { u = vector3(qx, qy, qz) s = qw return 2 * dot(u, v) * u + (s*s - dot(u, u)) * v + 2 * s * cross(u, v) }
Now that we know how to rotate a vector with a quaternion, we can use the global rotation quaternion to find the corresponding world direction (or axis) for the local direction by matching the local direction using the rotation quaternion.
The local front axle is always specified by the symbol 0*i + 0*j + 1*k . Therefore, to find the main front axis for the object, you must hide the vector (0, 0, 1) with the quaternion of rotation of the world.
Using the above function, the front axle becomes
forward = rotate(vector3(0, 0, 1), rotationQuaternion)
Now that you have the world front axle, the force exerted along it will be just a scalar multiple of the world front axle.