THREE.MeshLine icon indicating copy to clipboard operation
THREE.MeshLine copied to clipboard

Feature request: line endings

Open Wilt opened this issue 8 years ago • 3 comments

Feature request:

Maybe a nice idea to support different line endings, i.e. rounded / straight.

I see there is interest in such feature for example here in this question on StackOverflow

Wilt avatar Jul 13 '16 14:07 Wilt

I'd very much appreciate this feature, along with round joins. 👍

@spite Thanks for creating this library! It's been super-helpful and inspiring.

Just in case you have some ideas how one might implement it, could you please describe a possible approach, if only briefly? Thanks in advance! 🙏

dmitru avatar Feb 05 '21 09:02 dmitru

True round endings are quite difficult with the way this library works right now as you would need to modify the shader to achieve them. If you need round endings, you could probably use the native and undocumented Line2. But different pointy endings are possible by adjusting the width of the line in its ending points and, eventually, adding extra points.

What I'm doing is:

this.line.setPoints(
                this.geometry.attributes.position.array,
                (p) => {
                    let length = this.geometry.attributes.position.array.length / 3;
                    function map(n, start1, stop1, start2, stop2) {
                        return (
                            ((n - start1) / (stop1 - start1)) * (stop2 - start2) + start2
                        );
                    }
                    let index = Math.round(p * (length - 1));
                    let minWidth = 0;
                    let baseWidth = 3;
                    let width = 2;
                    let tailLength = 3;

                    //Beginning of the line
                    if (index < tailLength) {
                        return map(
                            index,
                            minWidth,
                            tailLength,
                            minWidth,
                            baseWidth + width
                        ); 
                    }
                    //End of the line
                    else if (index > length - tailLength) {
                        return map(
                            index,
                            length - tailLength,
                            length - 1,
                            baseWidth + width,
                            minWidth
                        );
                    }
                    //bulk of the line
                    else {
                        return baseWidth + width;
                    }
                }
            );

I'm using a map function because my lines have dynamic length but I think you could also hard-code some of these variables 🤔

jacopocolo avatar Feb 05 '21 09:02 jacopocolo

Thanks for sharing that!

In my case, I only need MeshLine to render 2d lines, so I ended up doing some post-processing with Canvas API to achieve rounded ends:

  • knowing the geometry of the path, I'm subtracting the end shapes from the result canvas rendered with Three.js

But now I'd need to modify the way the library joins the lines to achieve the look I want:

  • textured thick paths that can join under 90 degrees.

dmitru avatar Feb 06 '21 07:02 dmitru