THREE.CatmullRomCurve3

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.js"></script>

JavaScript

// scene

const scene = new THREE.Scene();

// camera

const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 0, 30 );

// curve

const curve = new THREE.CatmullRomCurve3( [
	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 curve mesh

const geometry = new THREE.Geometry();
geometry.vertices = curve.getPoints( 100 );

const material = new THREE.LineBasicMaterial( { color : 0xff0000 } );
const curveObject = new THREE.Line( geometry, material );
scene.add( curveObject );

// visualize spaced points 

const sphereGeomtry = new THREE.SphereBufferGeometry( 0.1 );
const sphereMaterial = new THREE.MeshBasicMaterial( { color: 0xff0000 } );

const spacedPoints = curve.getSpacedPoints( 20 );

for ( point of spacedPoints ) {

	const helper = new THREE.Mesh( sphereGeomtry, sphereMaterial );
	helper.position.copy( point );
	scene.add( helper );

}

// renderer

const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x20252f );
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );

animate();

window.addEventListener( 'resize', onResize );

function onResize() {

	camera.aspect = window.innerWidth / window.innerHeight;
	camera.updateProjectionMatrix();
	renderer.setSize( window.innerWidth, window.innerHeight );

}

function animate() {

	requestAnimationFrame( animate );

	render();
  
}

function render() {

	renderer.render( scene, camera );

}