Tested and confirmed to work:
Say you have two objects: a source and a target object.
The target must keep a certain relative orientation with respect to a source object.
This is really the case with most fundamental camera tracking scenarios (e.g. camera behind a flying entity - plane, spaceship, etc.).
If a given reference pose of this binary system is given, say at start-up, then we must grab hold on the orientations of the source and target objects:
- Qtgt0 = the quaternion describing how the frame of the target relates to the world frame
- Qsrc0 = the quaternion describing how the frame of the source object relates to the world frame
The 0 suffix denotes the initial state. These two quats shouldn't change from now on, they remain untouched. The relative orientation of a target with respect to a source is
not the difference of the quaternions, but this guy: Qsrc0.inverse * Qtgt0 (something similar to a division operator for quaternions - but since the quaternion multiplication does not commute, such an operator is "left or right handed").
At a certain time instance, the source has the Qsrc orientation. To couple the orientation of the target to that of the source, set the orientation of the target to be:
Qtgt = Qsrc * Qrelative = Qsrc * Qsrc0.inverse * Qtgt0
The picture below illustrates an experiment where a cube gets the camera's quat and a
parabolic tube springing from one of the cube's faces rotates with the cube although they are not attached to the same scene node, nor is the cube's node a child of the cube's node (talking hierarchical node transformations in a scene graph). Both objects are linked to the world independently, but when the scene is created, their relative orientation is stored separately for future updates.
Say you have a ship and a camera object in a simple scene.
Let Qs be the ship's current quat and Qc the camera's current quaternion. Let this configuration Qs,Qc be the initial, reference position you are talking about.
If the ship changes its orientation from Qs to Qs', then you could write:
Qs' = Qs' * inv(Qs) * Qs
Qs' * Qs is a relative rotation transformation. If you apply it to the camera's
initial orientation, you get a new camera orientation that should be in tune to your ship's change in orientation, as desired. The inv(Qs) factor tells us that there is an intricate orientation coupling that is initially set, between our camera and ship objects.
inv(q) denotes the inverse of a quat, which is the same as its conjugate q* if the quat is normalized.
To get a result, the camera's orientation, when the ship changes heading, should look like:
Qc' = Qs' * inv(Qs) * Qc
Be aware that the *_ operator is the quaternion multiplication. When rotating vectors, you will multiply the orientation quat q with (0,v) and then right multiply it by q*.