I want to find a relative rotation between two quaternions quatA and quatB, i.e. quatC is a quaternion rotation that if applied to quatA would result in quatB. Basically I want something like this:
quatC = Quaternion.RelativeRotation( quatA, quatB );
The only way I can think of to do it is to make two Transforms modA and modB, with modB the child of modA, and use the following code:
modA.rotation = quatA;
modB.rotation = quatB;
quatC = modB.localRotation;
However I would prefer not to use Transforms, and just use quaternions instead.
This previous answer suggests the following code would work:
Quaternion rotationDelta = Quaternion.FromToRotation(modelA.transform.forward, modelB.transform.forward);
But it doesn't appear to work after all, as it only inputs two direction vectors, not rotations. To demonstrate this, attach the following script to a basic cube dragged into an empty scene. The code will position and size the cube.
Modify rotations for models A and/or B. Model C should display the RELATIVE rotation FROM A TO B. In other words, applying C's rotation to A's rotation should result in B's rotation.
Model D shows the ACTUAL result of applying C's rotation to A's rotation. If C showed the actual relative rotation, D would be identical to B. As you will see, this is NOT the case. Hopefully I'm just missing something, but if not, is there a way to get quatC only with code?
var modA : Transform;
var modB : Transform;
var modC : Transform;
var modD : Transform;
var D_Rot_Equals_B_Rot = true;
// Nothing in Start is important to the question, it just sets up
// other objects to help demonstrate the problem
function Start() {
modA = transform;
modA.gameObject.name = "Model A";
modA.position = Vector3(0,0,0);
modA.rotation = Quaternion.identity;
modA.localScale = Vector3(.1,.1,.8);
modB = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;
modB.gameObject.name = "Model B";
modB.position = Vector3(1,0,0);
modB.localScale = Vector3(.1,.1,.8);
modC = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;
modC.gameObject.name = "Model C";
modC.position = Vector3(2,0,0);
modC.localScale = Vector3(.1,.1,.8);
modD = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;
modD.gameObject.name = "Model D";
modD.position = Vector3(3,0,0);
modD.localScale = Vector3(.1,.1,.8);
var bump : Transform;
bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
bump.gameObject.name = "Angle Helper";
bump.localScale = Vector3(.2,.2,.2);
bump.position = Vector3(0,.15,-.3);
bump.parent = modA;
bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
bump.gameObject.name = "Angle Helper";
bump.localScale = Vector3(.2,.2,.2);
bump.position = Vector3(1,.15,-.3);
bump.parent = modB;
bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
bump.gameObject.name = "Angle Helper";
bump.localScale = Vector3(.2,.2,.2);
bump.position = Vector3(2,.15,-.3);
bump.parent = modC;
bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
bump.gameObject.name = "Angle Helper";
bump.localScale = Vector3(.2,.2,.2);
bump.position = Vector3(3,.15,-.3);
bump.parent = modD;
}
function Update () {
// Modify rotations for models A and/or B.
// Model C should display the RELATIVE rotation FROM A TO B.
// In other words, applying C's rotation to A's rotation should result in B's rotation.
// Model D shows the ACTUAL result of applying C's rotation to A's rotation.
// If C showed the actual relative rotation, D would be identical to B.
// As you will see, this is NOT the case.
modC.rotation = Quaternion.FromToRotation(modA.forward, modB.forward);
modD.rotation = modA.rotation * modC.rotation;
if (modD.rotation==modB.rotation) {
D_Rot_Equals_B_Rot = true;
} else {
D_Rot_Equals_B_Rot = false;
}
}