Reputation: 3883
Three.js r85
When raycasting with Three JS, a series of points is returned, and I'd like to find the point that is closest to the cursor. The first point returned seems to be the point that is closest to the camera.
Is there a way to find the distance between the cursor position and a point?
Here's the code I'm using to debug this right now:
var raygun = new THREE.Raycaster();
raygun.setFromCamera(mouse, camera);
var hits = raygun.intersectObjects([plotpoints]);
if (hits.length > 0) {
scope.remove(dotPlot);
scope.remove(dotPlot2);
// All points except the first one - Grey
dotGeo = new THREE.Geometry();
for (var i=1; i < hits.length; i++) {
dotGeo.vertices.push(plotpoints.geometry.vertices[hits[i].index]);
}
dotPlot = new THREE.Points(dotGeo, dotMat);
scope.add(dotPlot);
// First point - Orange
var geo2 = new THREE.Geometry();
geo2.vertices.push(plotpoints.geometry.vertices[hits[0].index]);
dotPlot2 = new THREE.Points(geo2, dotMat2);
scope.add(dotPlot2);
scope.render();
}
And here's what I'm seeing:
Upvotes: 2
Views: 2208
Reputation: 3883
Ah, figured it out with math!
First thing to note is that hits[].points
returns a point directly under the cursor, but it doesn't "snap" to points.
In order to get the actual position of the point, we need to use hits[].index
first to get the index number of the point/vertex we hit. We can then access that vertex directly by using GEOMETRY.vertices[]
which returns a THREE.Vector3
of the vertex point we hit with our raycast.
So by feeding in the index, we can get the exact position of each vertex hit by our raycast:
GEOMETRY.vertices[hits[i].index]
This provides rudimentary "snapping" to vertices.
Note: When using THREE.LineSegments
, the result will always be the starting point, and not the ending point. To get the ending point, you can just add 1 to the index value:
GEOMETRY.vertices[hits[i+1].index]
To snap directly to the vertex closest to the cursor, we need to find the vertex that has the shortest perpendicular distance from the raycaster's ray. To do this we use a cross product of 2 vectors. This is more of a math concept than a programming concept though, so if you want to understand the why behind this, look up something like: perpendicular distance from a point to a line
I just took the code from this question and translated it: http://answers.unity3d.com/questions/568773/shortest-distance-from-a-point-to-a-vector.html
And the end result:
// Variables to record and compare
var smallestDist = 99;
var smallestPointIndex = 0;
// Declare variables outside of loop to save memory
var m_ray = raycaster.ray;
var raydir = m_ray.direction;
var origin = m_ray.origin;
var hitray = new THREE.Vector3(0,0,0);
var dist = 1;
// Loop over all points to find the closest
for (var i=0; i<hits.length; i++){
// Math is magic
hitray.subVectors(plotpoints.geometry.vertices[hits[i].index], origin);
dist = new THREE.Vector3().crossVectors(raydir, hitray).lengthSq();
// Record the closest point
if (dist < smallestDist) {
smallestDist = dist;
smallestPointIndex = i;
}
}
// Now we can use that single point
Here's the result :)
Upvotes: 1