nnyby
nnyby

Reputation: 4668

three.js: finding nearest point of a Mesh to mouse cursor

Imagine this three.js scene, set up with an OrthographicCamera and OrbitControls:

Picture of three.js globe scene

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:

Another angle of the three.js scene

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-interactives/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-interactives/sun-motion-simulator/

For reference, the sun should behave like this: https://cse.unl.edu/~astrodev/flashdev2/sunMotions/sunMotions068.html (requires Flash)

Upvotes: 1

Views: 1107

Answers (2)

manthrax
manthrax

Reputation: 5016

The raycaster returns all objects hit by the ray.. all of the hit points in worldspace.. (which you can convert to/from model space via object3d.worldToLocal and localToWorld)

It returns the hit distances.. which you can sort by whatever heuristic you need...

What I usually do is cast on mouseDown.. record the object and point.. then on mouseMove get the same objects hit point, and apply my edit operation using the difference between those 2 points.

Is this what you're talking about?

Upvotes: 0

stdob--
stdob--

Reputation: 29172

The simplest version:

  • get a point on disk
  • make a projection in the plane of the circle
  • knowing the radius of the circle, calculate the multiplier for multiplying the vector by the scalar

var point = res.point.clone();
point.z = 0; // Project on circle plane
var scale = circleRadius / point.length();
point.multiplyScalar(circleRadius / point.length())

[ https://jsfiddle.net/c4m3o7ht/ ]

Upvotes: 1

Related Questions