How to create tubes efficiently in three.js

Viewed 402

I'm struggling to make tubes in THREE.js and there are very few tutorials on them so I decided to ask here. How can I create a tube without using this difficult piece of code taken from the official docs?

    class CustomSinCurve extends THREE.Curve {

        constructor( scale = 1 ) {

            super();

            this.scale = scale;

        }

        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 );

        }
    }

Preferably with the use of bezier curves or something intuitive. (To be clear, I'm using React-three-fiber to create these models but I know how to convert vanilla THREE.js to it.)

1 Answers

Try it like so:

let mesh;
let camera, scene, renderer;

init();
animate();

function init() {

  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
  camera.position.z = 4;

  scene = new THREE.Scene();

  const curve = new THREE.QuadraticBezierCurve3(new THREE.Vector3(-1, -1, 0), new THREE.Vector3(-1, 1, 0), new THREE.Vector3(1, 1, 0))

  const geometry = new THREE.TubeGeometry(curve);
  const material = new THREE.MeshNormalMaterial({
    side: THREE.DoubleSide
  });

  mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);

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


}

function animate() {

  requestAnimationFrame(animate);

  mesh.rotation.y += 0.01;

  renderer.render(scene, camera);

}
body {
      margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.133.1/build/three.min.js"></script>

The example code uses a simple quadratic bezier curve in order to generate the tube's shape.

Related