Three.js Spherical Class for Orbital Coordinates

This article explains how the Spherical class in Three.js is used to calculate orbital coordinates for 3D objects. You will learn the mathematical concept behind spherical coordinates, why they are highly efficient for simulating orbital paths like planets or camera rigs, and how to implement them in your Three.js projects.

Understanding Spherical Coordinates

In a standard 3D Cartesian coordinate system, a position is defined by three perpendicular axes: X, Y, and Z. While Cartesian coordinates are ideal for positioning objects on a grid, they make calculating curved or circular paths mathematically complex, requiring manual trigonometric equations involving sines and cosines.

The Spherical class in Three.js solves this by representing coordinates using a spherical coordinate system. Instead of X, Y, and Z, a point is defined by three values: * Radius (\(r\)): The distance from the origin (the center of the sphere or the object being orbited). * Phi (\(\phi\)): The polar angle (or inclination) from the positive Y-axis (ranging from \(0\) to \(\pi\) radians). * Theta (\(\theta\)): The equator or azimuthal angle around the Y-axis (ranging from \(0\) to \(2\pi\) radians).

Why Use the Spherical Class for Orbits?

When simulating an orbit—such as a planet orbiting a sun, a satellite orbiting Earth, or a camera rotating around a target—the distance (radius) usually remains constant, while the angles change.

Using the Spherical class simplifies orbital calculations because you only need to increment the angles (\(\theta\) or \(\phi\)) over time to move an object along a perfect orbital sphere. Three.js handles the complex translation from these spherical angles back into the Cartesian (X, Y, Z) coordinates required by the GPU for rendering.

How to Calculate Orbital Coordinates in Code

To position an orbiting object using the Spherical class, you define the spherical coordinates, update them over time, and map them to a Vector3 object.

1. Initialize the Spherical Coordinates

First, create an instance of the Spherical class and a Vector3 to store the target Cartesian coordinates.

import * as THREE from 'three';

const radius = 10;      // Distance from the orbital center
const phi = Math.PI / 2; // Positioned on the equator (vertical angle)
const theta = 0;         // Starting horizontal angle

const spherical = new THREE.Spherical(radius, phi, theta);
const orbitalPosition = new THREE.Vector3();

2. Update the Angles in the Animation Loop

To create the orbiting motion, increment the theta value (for horizontal orbits) or phi value (for vertical orbits) in your animation loop. Once updated, use the setFromSpherical() method to convert the spherical coordinates to Cartesian coordinates.

function animate() {
    requestAnimationFrame(animate);

    // Increment theta to make the object orbit horizontally
    spherical.theta += 0.01; 

    // Keep phi within bounds to avoid gimbal lock if adjusting vertically
    // spherical.phi = Math.max(0.1, Math.min(Math.PI - 0.1, spherical.phi));

    // Convert spherical coordinates back to Cartesian (X, Y, Z)
    orbitalPosition.setFromSpherical(spherical);

    // Apply the coordinates to your orbiting mesh
    orbitingMesh.position.copy(orbitalPosition);

    renderer.render(scene, camera);
}

By leveraging the Spherical class, you avoid manual trigonometric calculations, making your code cleaner, more readable, and less prone to mathematical errors when creating complex orbital systems.