Types of rotation
Rotation is typically the most challenging part of working with transforms. This is due to one major problem: how do you define rotation?
Ways of defining rotation
Here's a summary of all the different ways of defining rotation, their benefits and drawbacks:
| Yaw pitch roll | Euler angles | Quaternions | |
|---|---|---|---|
| Human-readable | 🟩 | 🟩 | 🟥 |
| Easy to store | 🟥 | 🟩 | 🟩 |
| Easy to compute | 🟥 | 🟥 | 🟩 |
| Best used in | Simple transform manipulations | Serialization | Complex transform manipulations and computing |
Yaw pitch roll
Yaw pitch roll is the easiest to explain. The idea is to store the rotation in 3 easily identifiable variables: yaw, pitch and roll. This approach has its benefits and drawbacks:
- 🟩 More human-readable
- 🟩 Easiest to understand
- 🟥 Difficult to store (requires 3 separate values)
- 🟥 Difficult to compute
- 🟥 Prone to gimbal lock.
Yaw pitch roll is available in many places during runtime as an alternative to the far-more complex quaternions.
Euler angles
Euler angles are also quite simple to explain. The idea is to store the rotation in 3 axes: X, Y and Z. This approach shares similar benefits and drawbacks with yaw pitch roll:
- 🟩 More human-readable
- 🟩 Easy to understand
- 🟩 Easy to store (requires a single
Vector3) - 🟥 Difficult to compute
- 🟥 Prone to gimbal lock.
Euler angles are best used for setting an entity's initial rotation and serialization, which is why they are used in Game Studio.
Quaternions
Unlike the previous two, Quaternions are almost impossible to explain without going deep into mathematics. They have their own benefits and drawbacks:
- 🟩 Easier to compute
- 🟩 Have less ambiguity
- 🟥 Difficult to understand
- 🟥 Not readable
Quaternions are what is used by Stride during runtime. They can be controlled indirectly using utility methods.
Converting between types
Converting between the three types isn't difficult. You can use the following code to fully utilize the benefits of each approach.
// Quaternion to yaw pitch roll
myQuaternion.YawPitchRoll(out var yaw, out var pitch, out var roll);
// Yaw pitch roll to quaternion
var myQuaternion = Quaternion.RotationYawPitchRoll(yaw, pitch, roll);
// Yaw pitch roll to euler angles (notice the order of variables)
var eulerAngles = new Vector3(pitch, yaw, roll);
// Euler to yaw pitch roll (notice the order of variables)
var pitch = eulerAngles.X;
var yaw = eulerAngles.Y;
var roll = eulerAngles.Z;