Three.js Rotation: Euler Angles vs Quaternions
Rotating 3D objects in Three.js can be achieved using two primary mathematical representations: Euler angles and Quaternions. While Euler angles are intuitive and easy to understand for simple rotations, they suffer from mathematical limitations like gimbal lock. Quaternions, on the other hand, provide a robust, albeit mathematically complex, solution that avoids gimbal lock and enables smooth interpolation. This article compares how Three.js utilizes both methods, highlights their key differences, and explains when to use each approach for optimal 3D scene development.
Euler Angles in Three.js
Euler angles represent a rotation by rotating an object around three
distinct axes (X, Y, and Z) in a specific sequence. In Three.js, every
Object3D has a rotation property which is an
instance of the Euler class.
How It Works
You rotate an object by directly modifying its axial properties in radians:
// Rotate 45 degrees (PI / 4 radians) around the Y axis
mesh.rotation.y = Math.PI / 4;The Ordering Issue and Gimbal Lock
The order in which these rotations are applied matters. By default, Three.js applies rotations in the ‘XYZ’ order. You can change this using:
mesh.rotation.order = 'YXZ';Because rotations are applied sequentially, rotating an object 90 degrees around one axis can align the other two axes. This causes a loss of one degree of freedom, a phenomenon known as gimbal lock. When gimbal lock occurs, the object can no longer rotate along one of its expected axes, causing unexpected snapping or erratic movement during animations.
Quaternions in Three.js
Quaternions represent rotations in a four-dimensional space using
four values: x, y, z, and
w. Instead of rotating sequentially around three axes, a
quaternion represents a single rotation around a specified 3D vector
(axis) by a specific angle. In Three.js, every Object3D has
a quaternion property.
How It Works
Because four-dimensional numbers are highly non-intuitive to write
manually, Three.js provides helper methods to work with the
Quaternion class:
const quaternion = new THREE.Quaternion();
const axis = new THREE.Vector3(0, 1, 0); // Rotate around the Y axis
const angle = Math.PI / 4; // 45 degrees
quaternion.setFromAxisAngle(axis, angle);
mesh.quaternion.copy(quaternion);Advantages of Quaternions
- No Gimbal Lock: Because rotations are calculated simultaneously around an arbitrary vector rather than sequentially around fixed axes, gimbal lock is mathematically impossible.
- Smooth Interpolation (SLERP): Quaternions allow for
Spherical Linear Interpolation (
slerp). This makes them ideal for smooth transitions between two rotation states, which is essential for character animations and camera paths.
Synchronization in Three.js
Three.js automatically keeps Euler angles and Quaternions
synchronized. By default, when you update mesh.rotation
(Euler), Three.js automatically updates mesh.quaternion
behind the scenes, and vice versa.
If you want to manipulate quaternions directly and prevent automatic overrides, Three.js manages this state internally. However, if you are doing complex manual matrix updates, you can disable automatic updates or force synchronization using:
mesh.rotation.onChangeCallback();
// Or manually copy one representation to another:
mesh.quaternion.setFromEuler(mesh.rotation);Key Differences and Use Cases
| Feature | Euler Angles
(mesh.rotation) |
Quaternions
(mesh.quaternion) |
|---|---|---|
| Data Structure | 3 values: x, y,
z (angles in radians) |
4 values: x, y,
z, w |
| Intuitiveness | High (easy to read and tweak manually) | Low (requires helper methods) |
| Gimbal Lock | Yes, susceptible | No, completely immune |
| Interpolation | Jagged, unpredictable over long transitions | Smooth, linear transitions (SLERP) |
When to Use Euler Angles
- Simple, independent rotations: e.g., spinning a coin around a single axis, adjusting the tilt of a static lamp, or basic UI elements.
- User inputs: When capturing simple slider values from a user interface to rotate an object.
When to Use Quaternions
- Complex animations: e.g., character rigging, joint movements, and skeletal animations.
- Physics engines & flight simulators: Vehicles, aircraft, or space simulations where pitch, yaw, and roll happen simultaneously without axis alignment constraints.
- Smooth camera transitions: Tracking objects smoothly without sudden pops or gimbal lock issues.