Thickness of lines using THREE.LineBasicMaterial

Viewed 46684

I am using the code below to create hundreds of lines in my three.js scene

edgeGeometry[i] = new THREE.Geometry();
edgeGeometry[i].vertices[0] = v(x1,y1,z1);
edgeGeometry[i].vertices[1] = v(x2,y2,z2);
edgesMat[i] = new THREE.LineBasicMaterial({
    color: 0x6699FF, linewidth: 1, fog:true});
edge[i] = new THREE.Line(edgeGeometry[i], edgesMat[i]);
edge[i].type = THREE.Lines;
scene2.add(edge[i]);

It works just fine, but when i change the value of "linewidth" to a bigger OR smaller value, i see NO difference in the scene.
How should i change the thickness of the lines? Any ideas?
Thanks, Dimitris

9 Answers

I use TubeGeometry to create a Thick line between two points:

See Green lines in Helix

enter image description here

// line material
var lineMaterial = new THREE.LineBasicMaterial({ color: 0x00ff00 });


let startVector = new THREE.Vector3(
    RADI * Math.cos(t),
    RADI * Math.sin(t),
    3 * t
  );
  let endVector = new THREE.Vector3(
    RADI * Math.cos(t + 10),
    RADI * Math.sin(t + 10),
    3 * t
  );

  let linePoints = [];
  linePoints.push(startVector, endVector);

  // Create Tube Geometry
  var tubeGeometry = new THREE.TubeGeometry(
    new THREE.CatmullRomCurve3(linePoints),
    512,// path segments
    0.5,// THICKNESS
    8, //Roundness of Tube
    false //closed
  );

  let line = new THREE.Line(tubeGeometry, lineMaterial);
  scene.add(line);

You can achieve the same effect using extrude-polyline to generate a simplicial complex for the thickened (poly)line and three-simplicial-complex to convert this to a three.js Mesh:

const THREE = require('three');
const extrudePolyline = require('extrude-polyline');
const Complex = require('three-simplicial-complex')(THREE);

function thickPolyline(points, lineWidth) {
  const simplicialComplex = extrudePolyline({
    // Adjust to taste!
    thickness: lineWidth,
    cap: 'square',  // or 'butt'
    join: 'bevel',  // or 'miter',
    miterLimit: 10,
  }).build(points);

  // Add a z-coordinate.
  for (const position of simplicialComplex.positions) {
    position[2] = 0;
  }

  return Complex(simplicialComplex);
}

const vertices = [[0, 0], [10, 0], [10, 10], [20, 10], [30, 00]];
const geometry = thickPolyline(vertices, 10);

const material = new THREE.MeshBasicMaterial({
  color: 0x009900,
  side: THREE.DoubleSide
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

If you want to texture map the polyline, things get a little more complicated.

Thanks to Wilt's answer for pointing me in the right direction with THREE.MeshLine.

It can be slightly trickier than they make it out to be, however... So here's my solution following their docs and their demo code very carefully... (assuming you've already included Three and MeshLine):

    renderer = new THREE.WebGLRenderer({ canvas });

    //...

    function createCircle(resolution) {
        let circleGeometry = new THREE.Geometry();
        for (let rotation = 0; rotation <= Math.PI * 2.0; rotation += Math.PI * 0.1) {
            circleGeometry.vertices.push(
                new THREE.Vector3(Math.cos(rotation), Math.sin(rotation), 0));
        }
        let circleLine = new MeshLine();
        circleLine.setGeometry(circleGeometry);
        //Bonus: parabolic width! (See Z rotation below.)
        //circleLine.setGeometry(circleGeometry, function(point) {
            //return Math.pow(4 * point * (1 - point), 1);
        //});

        //Note: resolution is *required*!
        return new THREE.Mesh(circleLine.geometry,
            new MeshLineMaterial({
                color: 'blue',
                resolution,
                sizeAttenuation: 0,
                lineWidth: 5.0,
                side: THREE.DoubleSide
            }));
    }

    let circle = createCircle(new THREE.Vector2(canvas.width, canvas.height));
    circle.rotation.x = Math.PI * 0.5;
    circle.position.y = 20.0;
    scene.add(circle);

    //In update, to rotate the circle (e.g. if using parabola above):
    world.circle.rotation.z += 0.05;

With size attenuation off and using THREE.DoubleSide, like I did above, the circle will look like a nice, consistent circle no matter where you're looking at it from (not "true 3D").

For just a line, you can obviously easily adapt.

Why not set the opacity to something like 0.1? NOTE: This only works if you are giving borders to something, if there's nothing behind it the it won't work.

Related