-
Notifications
You must be signed in to change notification settings - Fork 27
Support thick lines #1889
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Support thick lines #1889
Conversation
/approve |
extends BufferGeometry<Record<'position', BufferAttribute>> | ||
implements H5WebGeometry | ||
{ | ||
class LineConstantGeometry extends ThreeLineGeometry implements H5WebGeometry { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend reviewing the diff of LineGeometry
first 😉
// Parts of `LineGeometry#setPositions` that don't need to be called on every update | ||
// https://github.com/mrdoob/three.js/blob/40728556ec00833b54be287807cd6fb04a897313/examples/jsm/lines/LineSegmentsGeometry.js#L97 | ||
const { array } = this.positions; | ||
const instancedBuffer = new InstancedInterleavedBuffer(array, 2 * 3); // two sets of `xyz` coords per line segment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In LineGeometry
, the positions
buffer attribute has to contain line segments rather than connected points. It is wrapped in an InstancedInterleavedBuffer
, which is exposed via two InterleavedBufferAttribute
: instanceStart
and instanceEnd
, which provide LineMaterial
with access to the start and end points of the line segments.
if (index >= this.length - 1) { | ||
this.setInvalidSegment(posIndex); | ||
continue; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Skipping the last data point, since it's the end of the second last data point's segment.
|
||
const nextValue = ordinates[index + 1]; | ||
|
||
if (ignoreValue?.(value) || ignoreValue?.(nextValue)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't render the segment either if:
- its start and/or end value is ignored
- its computed positions are not finite (see further down).
At long last, fix #1817
I've decided to completely replace
Line
andLineBasicMaterial
withLine2
andLineMaterial
fromthree/addons/lines
, since they no longer require installing a separate package and seem to now be official add-ons rather than just examples.Technically, since the viewer doesn't use this feature yet, there's a slight impact on memory with no actual gain in
@h5web/app
— indeed, the position buffers are now twice as long because the new geometries (based onLineGeometry
) require line segments rather than points. However, I think it's an acceptable compromise considering that the alternative would probably be to duplicate theLine
component and its two (for now) geometries.It's worth noting that by default,
LineMaterial
assumes that the specifiedlinewidth
is in CSS pixels, which means that it remains constant regardless of zoom level. This is exactly what we want, which is great. It's possible to change this behaviour by setting theworldUnits
boolean prop, but I didn't document it as I'm not sure there's a valid use case for it.Screencast.from.2025-10-02.12-46-18.webm
The new constant interpolation added a bit more work, but it was manageable.
So overall, the only consumer-facing changes for now are as follows:
[DataCurve, Line]
Add newwidth
prop to control the thickness of the line[DataCurve, Line]
PropmaterialProps
now accepts properties of Three'sLineMaterial
instead ofLineBasicMaterial
[Line]
Accept extra props from Three'sLine2
instead ofLine
EDIT I tried to add support for dashed lines. The idea is to compute the cumulative distances to the start and end of every segment. The problem, which we had identified a long time ago, is that these distances are in world space so the size of the dashes and gaps increase when zooming.
Line2
solves this problem for the line width, butLineSegments2
doesn't solve it for dashes... and I'm not fond of the idea of updating the geometry on every R3F frame, obviously. So I'm putting this work on the back burner.