mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
101.82k stars 35.31k forks source link

Raycaster on Line should match line width in screen space units #29353

Closed tommie closed 1 week ago

tommie commented 1 week ago

Description

Since Line commonly uses LineBasicMaterial, I would have expected Raycaster to honor the LineBasicMaterial.lineWidth. It also seems the threshold is interpreted in world units, not screen space, going against the general intuition of LineBasicMaterial.

Solution

Alternatives

There have been a few additions to the Line2 and LineSegments2 examples in recent years, but I'm wondering why that hasn't reached core.

Additional context

The Raycaster does not look much at materials when determining intersections, with few exceptions:

  1. Mesh et al. will make no intersection if the material is undefined.
  2. Sprite looks at sizeAttenuation and rotation (i.e. it assumes a SpriteMaterial is being used.)

Both Line and Points use thresholds that are static for the Raycaster, and don't care about materials. As with lineWidth, the PointMaterial.size would be useful to honor, though it would also have to take sizeAttenuation into account.

tommie commented 1 week ago

PoC for OrthographicCamera which does roughly what I suggest, but with a separate params boolean: https://gist.github.com/tommie/1a4b485d9f34ed9ca7cb78d4ae78310b

The actual implementation could come from LineSegments2 in the examples.

Mugen87 commented 1 week ago

Normal lines primitives can't have a width greater than 1 pixel. This is a restriction of WebGL (and WebGPU). The existing linewidth of LineBasicMaterial is not WebGL related since lines can also be rendered with SVGRenderer (an previously CanvasRenderer).

So you have to use the wide line implementation from the addons.

tommie commented 1 week ago

Thanks for the reply.

My WebGLRenderer seems to be able to render wider lines than 1px using Line(LineBasicMaterial), so I assumed it worked in general. Looks like up to 8px works. (This is on Chrome.)

Though, reading https://stackoverflow.com/a/47445400, it seems this is not something to rely on. I guess I was lucky.

https://github.com/mrdoob/three.js/issues/27034 suggests contributions for add-on documentation are welcome, so I might have a look at that, for discoverability.

donmccurdy commented 1 week ago

I would just add – if you want to do selection in screen space, with support for all of the effects that materials might have, then it might be better to use gpu picking rather than the raycaster.