Skip to content

Conversation

axelboc
Copy link
Contributor

@axelboc axelboc commented Oct 2, 2025

At long last, fix #1817

I've decided to completely replace Line and LineBasicMaterial with Line2 and LineMaterial from three/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 on LineGeometry) require line segments rather than points. However, I think it's an acceptable compromise considering that the alternative would probably be to duplicate the Line component and its two (for now) geometries.

It's worth noting that by default, LineMaterial assumes that the specified linewidth 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 the worldUnits 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 new width prop to control the thickness of the line
  • ⚠️ [DataCurve, Line] Prop materialProps now accepts properties of Three's LineMaterial instead of LineBasicMaterial
  • ⚠️ [Line] Accept extra props from Three's Line2 instead of Line

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, but LineSegments2 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.

@axelboc
Copy link
Contributor Author

axelboc commented Oct 2, 2025

/approve

extends BufferGeometry<Record<'position', BufferAttribute>>
implements H5WebGeometry
{
class LineConstantGeometry extends ThreeLineGeometry implements H5WebGeometry {
Copy link
Contributor Author

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
Copy link
Contributor Author

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.

Comment on lines +48 to +51
if (index >= this.length - 1) {
this.setInvalidSegment(posIndex);
continue;
}
Copy link
Contributor Author

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)) {
Copy link
Contributor Author

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).

@axelboc axelboc requested a review from loichuder October 2, 2025 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Line thickness
1 participant