One of the greatest challenges in XR development is the creation of a robust system of interactions that incorporates both real life physical interactions and interactions among various abstract hierarchical systems. Unlike traditional desktop/mobile game development, where we can design complex systems without the need for constant reparenting of transforms, XR interactions require careful deliberations in transform structures with regards to how they affect each other. This roughly translates to an n x n x d interaction considerations where d is the average nested transform depth of object classes. In that context, one of the most frequently appearing question is how do we get the local rotation of an object with respect to another object, regardless of their actual transform relationship within the scene?
To answer that, we start out with this relationship between the known anchor and object world rotations and the unknown relative rotation of the object with respect to the anchor (we will refer to the anchor and object as “parent” and “child”, but the object doesn’t necessarily have to be parented to the anchor):
Qw = Qp * Qc
Where:
- Qw : Child world rotation
- Qp : Parent world rotation
- Qc : Child local rotation relative to the parent
Qp-1 * Qw = Qp-1 * (Qp * Qc)
Using the property:
Qp-1 * Qp = I
(the identity quaternion), we get:
Qp-1 * Qw = Qc
And in Unity, this is simply:
// Compute the local rotation relative to an anchor
Quaternion RelativeRotation = Quaternion.Inverse(ParentRotation) * ObjectRotation;
So what are some of the use cases? First, using quaternion operation to directly derive local rotation bypasses the need to sequentially reparent an object to the anchor then reparent it back to the object’s original parent. This also gets rid of any unexpected behaviors that may arise from invoking SetParent.
Second, imagine that you have a collection of root level objects within the scene that will dynamically be parented to each other as the game or application evolves. At any point in time you want to save the rotation of these objects relative to a common anchor object, you would have to reparent these objects to the anchor, record the local rotation, then reparent it back to its original parent. Not only is this computationally expensive, this approach is also prone to bugs if not done correctly. By calculating the relative rotation of these objects using the simple line of code above, we effectively separate the concern of rotational calculations from other considerations such as parent-child relationships. Next time we load the scene, we have the option to instantiate these objects unparented from each other, rather than having to instantiate, parent, set local transform, and unparent.
* Please note that we excluded the discussion of positions, because deriving relative position is trivial compared to deriving relative rotation.
Jay Oh – 12/21/2024

Leave a comment