Three.js TubeGeometry: Create 3D Paths from Custom Curves

In Three.js, rendering a 3D volumetric path along a specific trajectory is achieved using TubeGeometry. This article provides a quick, practical guide on how to define a custom 3D curve using points or mathematical formulas, generate a tube geometry along that path, and render the resulting mesh in your scene.

Step 1: Define the Custom Curve

To create a tube, you first need a path for the tube to follow. The most common way to create a custom path is by passing an array of Vector3 coordinates to CatmullRomCurve3, which interpolates a smooth curve through those points.

import * as THREE from 'three';

// Define a set of 3D points
const points = [
  new THREE.Vector3(-10, 0, 10),
  new THREE.Vector3(-5, 5, 5),
  new THREE.Vector3(0, 0, 0),
  new THREE.Vector3(5, -5, 5),
  new THREE.Vector3(10, 0, 10)
];

// Create a smooth 3D spline curve from the points
const customCurve = new THREE.CatmullRomCurve3(points);

Step 2: Generate the TubeGeometry

Once the curve is defined, instantiate TubeGeometry. This class takes the curve and extrudes a cylindrical shape along its length.

// TubeGeometry parameters:
// 1. path — The curve (customCurve)
// 2. tubularSegments — Number of segments along the length of the tube (default: 64)
// 3. radius — Radius of the tube (default: 1)
// 4. radialSegments — Number of segments around the circumference (default: 8)
// 5. closed — Whether the tube is closed (joined at the ends, default: false)

const tubularSegments = 100;
const radius = 1.5;
const radialSegments = 16;
const closed = false;

const tubeGeometry = new THREE.TubeGeometry(
  customCurve,
  tubularSegments,
  radius,
  radialSegments,
  closed
);

Step 3: Create the Mesh and Add It to the Scene

To make the tube visible, pair the TubeGeometry with a material to create a Mesh, then add it to your Three.js scene.

// Create a material
const material = new THREE.MeshStandardMaterial({ 
  color: 0x00ff00, 
  roughness: 0.4,
  metalness: 0.2
});

// Create the mesh
const tubeMesh = new THREE.Mesh(tubeGeometry, material);

// Add the mesh to your Three.js scene
scene.add(tubeMesh);

Using a Mathematical Custom Curve Class

If you want to generate a path based on a mathematical formula (such as a helix or sine wave) instead of discrete points, you can extend the base THREE.Curve class and implement the getPoint method.

class CustomSinCurve extends THREE.Curve {
  constructor(scale = 1) {
    super();
    this.scale = scale;
  }

  // t is a value between 0 and 1
  getPoint(t, optionalTarget = new THREE.Vector3()) {
    const tx = t * 3 - 1.5;
    const ty = Math.sin(2 * Math.PI * t);
    const tz = 0;

    return optionalTarget.set(tx, ty, tz).multiplyScalar(this.scale);
  }
}

// Instantiate the mathematical curve
const path = new CustomSinCurve(10);

// Generate the tube geometry using the custom mathematical path
const mathTubeGeometry = new THREE.TubeGeometry(path, 64, 1, 8, false);
const mathTubeMesh = new THREE.Mesh(mathTubeGeometry, material);
scene.add(mathTubeMesh);