A have a "free form" rotation method that looks like this:
Vector3 screenVector = new Vector3(delta.X, -delta.Y, 0.0f);
Vector3 rotationVector = Vector3.Cross(Vector3.UnitZ, screenVector);
float angle = rotationVector.Length();
rotation = Quaternion.Concatenate(rotation, Quaternion.CreateFromAxisAngle(Vector3.Normalize(rotationVector), angle));
world = Matrix.CreateFromQuaternion(rotation);
The values of delta.X/delta.Y are displacement values along the screen coordinates. This allows me to freely rotate an object in 3D, no matter how it is orientated using touch/mouse movements.
I wish to smooth this out by adding a tweener to the rotation. This seems straightforward: split up the X and Y components of the rotation vector (the cross product above), separate the angle value in to two values X and Y, tween the angles, and then create a composite Quaternion. However, this doesn't seem to work in practice. When concatenating the two Quaternions, there is no movement along some arbitrary axis (depending on how much the object has been rotated). Furthermore, the object doesn't rotate freely anymore and instead starts to rotate in a manner similar to a third/first person camera (once the elevation goes past 90 degrees, the orientation is "flipped").
Instead of concatenating the Quaternions, I tried to Matrix.CreateFromQuaternion for each one instead, and then multiply the matrices. But this yields the exact same effect as described above.
Going to the extremes, I tried to tween the rotation vector, instead of manipulating the angles. This doesn't work as expected either. Whenever the direction changes, the normalization of the rotation vector causes it to rotate on the opposite axis to reverse direction. This means that if you're rotating along the X axis in the positive direction and then suddenly start rotating in the negative direction, at some point during the tweening affect, there will be some rotation along the Y axis, as the rotation "falls over" in the opposite direction.
Any recommendations on making this work correctly? Tweening the angle values does feel like the right way to go about it, but how do I construct the correct final rotation matrix if I separate them out?