Imagine this three.js scene, set up with an OrthographicCamera and OrbitControls:
When the user drags the yellow disc (meant to represent the Sun), the disc needs to move along its yellow circle in response to this action. Here’s the scene from another angle, so you can see the full yellow circle:
So, my event handler must determine which point on this circle is closest to the current cursor position. This yellow circle is a THREE.Mesh, by the way.
I’m using THREE.Raycaster to determine some mouseover events, using its
intersectObjects() function, but it’s not clear to me how to find the nearest point of a single object with this Raycaster. I’m guessing there is some simple math I can do after translating the mouse’s position to world co-ordinates. Can someone help me with this? Is Three.js’s Raycaster useful here? If not, how do I determine the nearest point of this mesh?
The full source code is here, if it’s helpful: https://github.com/ccnmtl/astro-simulations/blob/master/sun-motion-simulator/src/HorizonView.jsx Search for
this.sunDeclination , which corresponds to the yellow circle’s Mesh object.
For a working demo, go here: https://ccnmtl.github.io/astro-simulations/sun-motion-simulator/
For reference, the sun should behave like this: https://cse.unl.edu/~astrodev/flashdev2/sunMotions/sunMotions068.html (requires Flash)
As far as I can see at your code, you are using a
TorusBufferGeometry to visualize the yellow circle, right? If so, why don’t you just move the sun disc to the next intersection point between the ray and the torus geometry? I’m not sure why you need the nearest vertex for this
Maybe this demo helps you further: https://jsfiddle.net/f2Lommf5/14253/
I’ve just put together something like the jsfiddle you linked to.
intersectObject() only returns intersections of a mesh that the mouse is over. What if I’m dragging the sun and the mouse doesn’t happen to be over the yellow sunDeclination orbit line? That’s where I’m having trouble imagining how to use the Raycaster.
Okay, I see what you mean. I’ve changed the fiddle to something different. It’s not perfect but it should produce your desired result: https://jsfiddle.net/f2Lommf5/14316/
The idea is to do a ray intersection test with a plane in which the torus lies. Next, the code searches for the closest point to the torus geometry. This is done via
Triangle.closestPointToPoint() for all triangles. Keep in mind that this approach is computationally expensive, so use it carefully.
Maybe it’s better to use
THREE.LineSegments() for a circle and set bigger value for
But it’s just a thought
Yeah, this could be a fast alternative. However, normal lines are drawn with a width of one which is not super
user-friendly if users should interact with them (I refer to the visual feedback not to the actual intersection test).
Well, a line could be wrapped with a tube (for better visual), but a raycaster will check for intersection with the line only
Good idea. This is something that @nikolas could try and see how good it works.
Actually, the line can be even invisible (with the visible wrapping tube), we need it just to find a point
Thank you, that’s exactly what I’m looking for! I’ll take a closer look at this example and implement it in my scene.
@prisoner849, thanks for the invisible Line tip. I’ll probably end up modifying Mugen87’s solution to do it your way.
This is your scene, so feel free to use any approach you want
Haha woops i wasn’t clear. I meant… I’ll use your method, but building off @Mugen87’s.
So, this solution is almost working for me. But, the marker isn’t sticking to my torus (the yellow ring). Is this because my torus is rotated?
You can see the marker as a red dot here, is off, though the transparent red plane is in the correct position.
So, in your example @Mugen87, imagine the torus is rotated when certain values in the simulation change, like this: https://github.com/ccnmtl/astro-simulations/blob/971875aeb3b564c9e7427dddb8f415a8c66af2e4/sun-motion-simulator/src/CelestialSphere.jsx#L236
How would I then apply the same rotation to the triangle code here? https://github.com/ccnmtl/astro-simulations/blob/971875aeb3b564c9e7427dddb8f415a8c66af2e4/sun-motion-simulator/src/CelestialSphere.jsx#L966
It seems the like the geometry.index needs the rotation info applied to it, or something like that.
Okay, well I solved my issues by applying some rotations to the closestPoint that the mouse position finds. Now it seems to be working perfectly. https://github.com/ccnmtl/astro-simulations/pull/1921/files