I have a Quaternion class that I'm fairly certain is mathematically correct, and can create a quaternion from an axis and an angle; it normalizes itself, and the multiplication operator is overloaded to perform a proper multiplication.

However, don't understand how to transform the player's input into a quaternion representing a change in rotation. The player can input changes into the Pitch, Yaw and Roll, potentially all three at once. The object they are controlling is supposed to then rotate according to this input along its LOCAL axes.

Suppose the player wanted to change the Pitch by 30°, the Yaw by 45° and the Roll by 10° all at the same time (I'm using that example because it's the most complex possible situation my code will have to deal with). So I have these nice little values, 30-45-10 (which I could also convert to radians), but what do I do with them?

I've read dozens of tutorials, and what little I can make sense of them seems to indicate I need to make the change quaternion like this (pseudocode):

Qaternion xChange = Quaternion.FromAxisAngle(30, 1, 0, 0); Qaternion yChange = Quaternion.FromAxisAngle(45, 0, 1, 0); Qaternion zChange = Quaternion.FromAxisAngle(10, 0, 0, 1); Qaternion totalChange = zChange * yChange * xChange;

Where FromAxisAngle takes the parameters (float Angle, float X, float Y, float Z). Then I apparently need to perform this on the object's current Orientation, also a quaternion:

Orientation = totalChange * Orientation;

And finally derive a matrix from Orientation and pass that to glMultMatrix().

Unfortunately, my current code doesn't really work. Trying to change the yaw or roll just makes the object shiver, and trying to change the pitch makes the object spin correctly for a moment and then start to roll and grow enormously large at the same time.

The thing is, deep down I know my code shouldn't work, because quaternion multiplications are non-commutative. I can't just willy-nilly multiply quaternions for three different orientations with one another - the order will end up influencing the result, right? What do I do when a particular axis isn't supposed to be rotating at the moment?

I've got this not-working system in place, but I've tried half a dozen other configurations that don't work either. Rotation is the user-input rotation around the X,Y,Z axes respectively. I'n not doing any translation at the moment.

void Entity::Transform(sf::Vector3<float> Translation, sf::Vector3<float> Rotation) { if (Rotation.x != 0) { Quaternion Offset = Quaternion(); Offset.FromAxisAngle(Rotation.x, 1, 0, 0); m_Orientation = Offset * m_Orientation; } if (Rotation.y != 0) { Quaternion Offset = Quaternion(); Offset.FromAxisAngle(Rotation.y, 0, 1, 0); m_Orientation = Offset * m_Orientation; } if (Rotation.z != 0) { Quaternion Offset = Quaternion(); Offset.FromAxisAngle(Rotation.z, 0, 0, 1); m_Orientation = Offset * m_Orientation; } //Derive a rotation matrix m_Orientation.RotationMatrix(m_RotationMatrix); }

Can somebody tell me how I'm supposed to transform my player input into the appropriate quaternion transformations?

Note that I've also tried directly creating a quaternion from stored PYR variables, but this didn't work and I was told by someone reading my code that that was the wrong way to implement this sort of thing (unfortunately, his explanation of the right way to do it was extremely vague, at least to me).