Convert Local Direction to World Trajectory in Three.js

In Three.js, moving an object along its own local axes requires converting local direction vectors into world space. This article explains how to use the localToWorld method to transform a localized direction vector into a global trajectory, allowing you to move 3D objects relative to their current orientation.

The Challenge with Direction Vectors

The localToWorld method in Three.js is designed to convert a local position coordinate into a world position coordinate. It does this by multiplying the vector by the object’s global transformation matrix (matrixWorld), which applies scale, rotation, and translation (position).

Because localToWorld applies translation, passing a pure direction vector (like 0, 0, -1 for forward) directly into the method will not yield a pure direction vector. Instead, it yields a specific point in world space. To get a global trajectory, you must isolate the direction from the object’s position.

Method 1: The Vector Subtraction Approach

To use localToWorld to find a global direction, you calculate the world position of a point directly in front of the object and subtract the object’s actual world position. This isolates the orientation vector.

Here is the step-by-step implementation:

// 1. Define the local direction (e.g., local forward along the negative Z-axis)
const localDirection = new THREE.Vector3(0, 0, -1);

// 2. Convert the local point to a world position
const worldPoint = object.localToWorld(localDirection.clone());

// 3. Get the object's current world position
const worldPosition = new THREE.Vector3();
object.getWorldPosition(worldPosition);

// 4. Subtract the positions to get the global direction vector
const globalTrajectory = new THREE.Vector3()
    .subVectors(worldPoint, worldPosition)
    .normalize();

The resulting globalTrajectory vector is a normalized unit vector pointing in the object’s global forward direction. You can multiply this vector by a speed scalar to move the object or a projectile along this trajectory in your render loop:

const speed = 0.5;
projectile.position.addScaledVector(globalTrajectory, speed);

Method 2: The Optimized Alternative (transformDirection)

While the subtraction method using localToWorld is highly illustrative, Three.js provides a built-in, computationally cheaper method specifically for converting directions: Vector3.transformDirection.

This method multiplies the vector by the object’s 3D matrix and automatically ignores translation, meaning you do not need to perform subtraction or manually query the object’s world position.

const localDirection = new THREE.Vector3(0, 0, -1);

// Ensure the object's world matrix is up to date
object.updateMatrixWorld();

// Transform the direction vector directly using the object's world matrix
const globalTrajectory = localDirection.clone().transformDirection(object.matrixWorld);

Both methods yield the exact same global trajectory. Use the localToWorld subtraction method if you are already working with relative point distances, and use transformDirection for clean, high-performance vector transformations.