Constant Width Using Line2D

Is there a way to have a constant line width when zooming in or zooming out regardless of camera radius? I try to use line2D meshes since they can show different widths for different lines. I have an issue to update the width of the line2D lines according to camera radius in order to keep them constant when zooming in or out.

https://www.babylonjs-playground.com/#KNMZ0#34

1 Like

One approach is to use camera.onViewMatrixChangedObservable to scale the mesh proportionate to the camera radius, like on this updated playground. The new code is at line 215:

const initialCameraRadius = camera.radius;
camera.onViewMatrixChangedObservable.add(() => {
    const scale = camera.radius / initialCameraRadius;
    line.scaling.set(scale, scale, scale);
});
2 Likes

@Blake Thanks for the quick response on this. Is it possible to keep the line width constant and still vary the length of the line with the camera? The vertex coordinates of the line should not change. I am trying to avoid the situation when the meshes are zoomed out, it is hard to see the line since the width becomes very small.

1 Like

This seems to maintain visibility by keeping the line width more constant. It might not be an exact fit but seems to work well I think. Here’s the new playground with this method. :slightly_smiling_face:

Note: I’m creating a new line here each time its width changes but it would prob be better to change the line2D function to allow the vertex positions of a current line to be updated with a new width (by using setVerticesData to set the newly calculated positions).

const initialCameraRadius = camera.radius;
camera.onViewMatrixChangedObservable.add(() => {
    let factor = camera.radius / initialCameraRadius;
    factor = Math.pow(factor, 2 / 3);

    line.dispose();
    line = line2D("line", {path: path, width:0.5 * factor, closed: true}, scene);
});

Edit: I started out using square root but I think 2/3 is a much better fit than 1/2 for the exponent…

1 Like

@Blake Thanks a lot on this. Your responses help me understand this issue much better. I am still not able to solve my problem because the line2D meshes I have are also being rotated and scaled for other reasons. I couldn’t dispose the line and recreate it because I couldn’t locate the end points for an existing line created using line2D. As you suggested, it would be nice to have functionality added for existing line2D meshes to gain access to the width, and end point coordinates/locations and make them updatable. This would require some updates on line2D function.

2 Likes

You could search THREE.MeshLine to make something similar in BJS.

1 Like

Actually updatability can be added to jhuang’s line2D function quite readily IMO. For example this playground does it with just 4 more lines of code (at line 197 at the end of the line2D function) to check if an existing line is passed in the options and, if so, update it’s vertex data instead of creating a new mesh. :slightly_smiling_face:

Also updatable: true is passed in the options so that Babylon can be informed that the vertex data is updatable (this makes the API similar to what Babylon uses for updatable meshes).

Note the same options for path and closed are passed each time, but for example the options could be cached with line.options = options to make this part easier to handle…

So now the scaling, position, etc. are maintained and the width is kept visibly constant (nearly) to maintain visibility of the lines. Maybe there’s a more efficient way to change the width but hopefully this will be a helpful starting point. :beers:

2 Likes

More info on Line2D Draw a Line With a Set Width | Babylon.js Documentation

1 Like

Thanks @JohnK for the documentation.

@Blake It resolved my issue. This is awesome!! Small change makes a big difference.

As a side topic, do you think we can create a 2D line with text embedded? As an example dashed lines as follows:

--------S--------S--------S--------
-------- BFOC(B)--------

Thanks again.

1 Like