pmndrs / react-three-fiber

🇨🇭 A React renderer for Three.js
https://docs.pmnd.rs/react-three-fiber
MIT License
26.74k stars 1.51k forks source link

onPointerOver only listens when mouse moves #2243

Closed lgxm3z closed 1 year ago

lgxm3z commented 2 years ago

If the cursor is stopped and an element enters the contact area, the event is only called when the mouse moves. No "last cursor position" is recorded and there is no recalculation during frames.

drcmda commented 2 years ago

that's expected behaviour. i think even the dom operates that way. but either way it would cost too much to run raycasting on every frame. if you want that you can do it in userland by calling onpointermove inside useFrame, the handlers are all in the state object, state.events.handlers i believe it was.

lgxm3z commented 2 years ago

There are ways to solve 'this problem' without webworkers or alternatives like that, it's not necessary for all objects in a scene to be recalculated within raycasting, since everything outside the camera's view area never listens to "onPointerOver" becoming an impossible scenario, elements that don't call the same property in their declaration also never need to be calculated.

that's expected behaviour. i think even the dom operates that way. but either way it would cost too much to run raycasting on every frame. if you want that you can do it in userland by calling onpointermove inside useFrame, the handlers are all in the state object, state.events.handlers i believe it was.

CodyJasonBennett commented 2 years ago

R3F only raycasts against interactable objects that have handlers registered, so I'm not sure much more can be done there as far as optimizing events' filtering. Three's also intelligent enough to not recalculate bounding boxes/spheres needlessly. I would still advise doing this in a web worker since this is otherwise too slow to maintain a stable framerate.

lgxm3z commented 2 years ago

At first, I couldn't say a smart way to do this, I think the solution doesn't need to depend on an implementation with webworkers (of course it would be ideal but it's good to think about cases where this feature is not available). Speaking of use cases, I really see this as a problem, because it's not interesting for the person to have to implement their own handlers if the library already has it as a resource and apparently you also have this perspective. Of course, tests need to be done, but I really don't rule out a smart solution for this, considering that if you move the mouse quickly, the FPS doesn't go away even with several calls per second. The question is figuring out the factor that should tell when a recalculation needs to be done.

lgxm3z commented 2 years ago

An initial solution could be to provide some kind of hook that would force the raycast to be recalculated. So it's up to the user to handle this in their Event Loop/Physics Loop, although I think this should be automatic someway

CodyJasonBennett commented 2 years ago

We're only as fast as threejs here with actual raycasting overhead, but a faster solution could use something like three-mesh-bvh.

CodyJasonBennett commented 1 year ago

Currently, we can't support this due to the performance ramifications of three's built-in raycaster. I'd consider this as a feature request if we do use https://github.com/gkjohnson/three-mesh-bvh to partition the scene to where this is feasible.