spite / THREE.MeshLine

Mesh replacement for THREE.Line
MIT License
2.14k stars 381 forks source link

Feature request: line endings #19

Open Wilt opened 8 years ago

Wilt commented 8 years ago

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

dmitru commented 3 years ago

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! 🙏

jacopocolo commented 3 years ago

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 🤔

dmitru commented 3 years ago

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:

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