Quaternions

January 4 – Quaternion Fun Times

Background:
I’m building a character customization screen, where a user can mix and match different character parts, like arms, legs, etc. in order to create a custom, character.
Additionally, the entire character will be rotating at a set speed while the user chooses parts.
To properly connect new parts, we need to follow the following steps:

1. Connect the arm shoulder joint position to the torso shoulder joint position
2. Rotate the new arm to match the current body rotation
3. Rotate the new arm to match it’s elbow joint to the torso elbow joint

If we perform the first two steps, we get this:

Improper rotation

The second set of arms is set correctly to the torso shoulder joints, but its elbow joints aren’t properly lined up.
The current code is as follows:

We need to be careful here. The transform structure of the arm is:

arm_hiearchy

If we move the “left_upper_shoulder_joints” transform, we create an offset from it’s parent. We could use local rotation of the joint to work around this issue, but let’s instead keep everything together. We’ll figure the offset of the parent and child, then account for that when moving the parent:

Next we need to rotate each set of arms to match the direction of the torso.
First, we get both the rotation between the torso’s shoulder and elbow joints, and the rotation between the arm’s shoulder and elbow joints, then plug them into this nice little Unity function:

Quaternion.FromToRotation

unity_from_to_method

Our fromDirection is the current arm direction, and our toDirection is the current torso arm direction:


Hmm, it appears that the rotation is off until it gets back to its original instantiation position. This tells us that our code isn’t accounting for the current rotation

In order to add two rotations together, we must actually multiply them. Let’s do a basic assignment operator for multiplication:


Weird, it seems like its rotating in the opposite direction.

While researching quaternions, I remember seeing something about quaternions being “non-commutative”, which simply means:
x*y != y*x

With this in mind, let’s change the last line and test:


Woo! So, quaternion addition being non-commutative, this is correct:

And this is not:

To attempt to explain, adding two quaternions together (by multiplication) is synonymous to performing the first rotation, then the second, one after the other.

In other words, you’re taking the first quaternion rotation, and applying it to the second.

Since we want to rotate the arm itself, we need to apply our arm rotation to the current torso rotation.

The torso rotation (part.transform.rotation) is essentially a constant horizontal spin. If we apply the current torso rotation to our new arm rotation, we’re applying a horizontal spin to our new arm. Then applying the needed arm rotation on a different axis.

That’s how I understand it, but don’t quote me, I could be completely wrong!

Anyway, I hope this helps with quaternion troubles, and everyone can avoid the same hangups I had!

Leave a Reply

Your email address will not be published. Required fields are marked *