2017-05-13 4 views
0

Three.js R85Drei JS Raycasting - Finden Punkt am nächsten

Wenn Raycastings mit drei JS, eine Reihe von Punkten Cursor zurückgegeben wird, und ich möchte den Punkt finden, die am nächsten an der Cursor befindet. Der erste zurückgegebene Punkt scheint der Punkt zu sein, der der Kamera am nächsten ist.

Gibt es eine Möglichkeit, den Abstand zwischen der Cursorposition und einem Punkt zu finden?

Hier ist der Code, den ich jetzt mit diesem Recht zu debuggen:

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(); 
} 

Und hier ist, was ich sehe:

First point is not close to cursor

Antwort

0

Ah, es rechnete mit Mathe heraus!

Zunächst ist zu beachten, dass hits[].points einen Punkt direkt unter dem Cursor zurückgibt, aber nicht an Punkten "einrastet".

Um die tatsächlichen Position des Punktes zu erhalten, müssen wir hits[].index zuerst bekommen die Indexnummer des Punktes/Vertex wir schlagen verwenden. Wir können dann direkt auf diesen Vertex zugreifen, indem wir GEOMETRY.vertices[] verwenden, was eine THREE.Vector3 des Vertexpunkts zurückgibt, den wir mit unserem Raycast getroffen haben.

So von im Index Fütterung, können wir die genaue Position von jedem Eckpunkt unserer Raycast getroffen zu werden:
GEOMETRY.vertices[hits[i].index]

Dies bietet rudimentär Ecken „schnappen“.

Hinweis: Bei THREE.LineSegments verwenden, das Ergebnis wird immer der Ausgang Punkt und nicht der Endpunkt. Um den Endpunkt zu erhalten, können Sie fügen Sie einfach 1 auf den Indexwert:
GEOMETRY.vertices[hits[i+1].index]

schnappen direkt an den Scheitelpunkt am nächsten auf die Cursor, müssen wir den Scheitelpunkt finden, der den kürzesten senkrechten Abstand von der hat Rajasters Strahl. Um dies zu tun, verwenden wir ein Kreuzprodukt von 2 Vektoren. Dies ist eher ein mathematisches Konzept als ein Programmierungskonzept, also, wenn Sie das Warum dahinter verstehen wollen, suchen Sie etwas wie: senkrechter Abstand von einem Punkt zu einer Linie

Ich nahm nur den Code von dieser Frage und es übersetzt: http://answers.unity3d.com/questions/568773/shortest-distance-from-a-point-to-a-vector.html

Und das Endergebnis:

// 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 

Hier ist das Ergebnis :)

Success

+0

Wie viele 'Vector3's Instanziieren Sie? Erstellen Sie einen und verwenden Sie ihn erneut, insbesondere wenn Sie diesen Code in einer engen Schleife aufrufen. – WestLangley

+0

@WestLangley richtig, das ist nicht optimiert, aber es ist funktional. Ich komme später zurück und bearbeite es mit besserem Code. –

Verwandte Themen