from the docs: “Transform.InverseTransformPoint transforms position from world space to local space.”
[some gnarly equation that’s a mystery to me?] transforms rotation from world space to local space.
There is no such thing as Quaternion.InverseTransformRotation, but if there were, that would be exactly
what I’m looking for. It’s also what happens automatically to the localRotation when you parent an arbitrarily rotated object
to some other arbitrarily rotated object, but there has to be a better way than actually parenting and unparenting
objects every frame…?
What Owen said is almost correct.
The correct formula is:
Quaternion LocalRotation = Quaternion.Inverse(Target.transform.rotation) * WorldRotation;
//this will transform WorldRotation to Target's local space
Only partially tested: the local rotation from object P seems like it’s your world rotation “minus” P’s rotation. The opposite of a rotation is the Inverse, so:
Quaternion localRotFromP = transform.rotation * P.rotation.Inverse();
As a check, when you use local to get world, you multiply by the “parent” rotation. If we do that to our computed local, we get trans.rot * P.rot.Inv * P.rot
. The last two terms cancel (Quat mult isn’t commutative, but is still associative) and you get your real rotation back.
Here’s my solution, not elegant but works.
public Quaternion WorldToLocal(Quaternion worldRotation, Transform target)
{
var rotOffset = target.rotation * Quaternion.Inverse(target.localRotation);
var rotWorld = worldRotation * rotOffset;
var rotLocal = Quaternion.Inverse(rotOffset) * rotWorld;
return rotLocal;
}
First, calculate rotation offset.
Then, apply it to desired rotation value to get the “transform.rotation” value for the target transform.
And finally, convert it to transform.localRotation value.