Effizientes Einrasten an Eckpunkten in drei Js

Ich wollte eine Fangfunktion erstellen, um an meinen Netzscheitelpunkten zu fangen. Ich habe mit mehreren Lösungen experimentiert.

Eine Lösung ist, @ hinzuzufügTHREE.Sprite Instanzen für alle Vertices in meiner Szene und dann mit einemrayCaster um zu entscheiden, ob es ein @ gisnap Punkt imintersects array. Es funktioniert ziemlich gut; Hier ist eine Geige mit einer Demo.
Die Idee ist, die Sprites in der endgültigen Lösung zu verbergen, damit sie nicht gerendert werden, aber meine Szenen sind ziemlich groß, sodass es immer noch bedeuten würde, meiner Szene viele Sprites hinzuzufügen (für jeden Scheitelpunkt also möglicherweise Tausende von Sprites) Fangpunkte mit meinem @ erkennrayCaster.

var intersects = rayCaster.intersectObject(scene, true);
var snap = null;
if (intersects.length > 0) {
    var index = 0;
    var intersect = intersects[index];
    while (intersect && intersect.object.name === 'snap') {
        snap = sprite.localToWorld(sprite.position.clone());
        index++
        intersect = intersects[index];
    }
    if (intersect) {
        var face = intersect.face;
        var point = intersect.point;
        var object = intersect.object;
        mouse3D.copy(point);
    }
}
if (snap) {
    renderer.domElement.style.cursor = 'pointer';
} else {
    renderer.domElement.style.cursor = 'no-drop';
}

Ich dachte auch über eine alternative Lösung nach, indem ich die Ergebnisse aus demrayCaster. Diese Lösung wird @ demonstriein dieser Geige.
Die Idee hier ist, alle zu testenvertices aus der Geometrie desobject (mesh), das sich überschneidet, und prüfen Sie dann, ob dasdistance zwischen der Kreuzungpoint und diesevertices aus der Geometrie ist kleiner als der Snapthreshold.

var intersects = rayCaster.intersectObject(mesh, true);
if (intersects.length > 0) {
    var distance, intersect = intersects[0];
    var face = intersects[0].face;
    var point = intersects[0].point;
    var object = intersects[0].object;
    var snap = null;
    var test = object.worldToLocal(point);
    var points = object.geometry.vertices;
    for (var i = 0, il = points.length; i < il; i++) {
        distance = points[i].distanceTo(test);
        if (distance > threshold) {
            continue;
        }
        snap = object.localToWorld(points[i]);
    }
    if (snap) {
        sphereHelper.position.copy(snap);
        sphereHelper.visible = true;
        renderer.domElement.style.cursor = 'pointer';
    } else {
        sphereHelper.visible = false;
        renderer.domElement.style.cursor = 'no-drop';
    }
}

Das Traurige ist, dass der Fang in der zweiten Lösung nur funktioniert, wenn die Maus von der Oberfläche des geschnittenen Objekts in Richtung eines Scheitelpunkts bewegt wird. Wenn die Maus von außerhalb des Objekts bewegt wird (es gibt also keine Schnittmenge), funktioniert das Fangen nicht. In dieser Hinsicht ist die erste Lösung mit Sprites viel nützlicher ...

Meine Frage, bin ich überkompliziert und gibt es eine bessere / einfachere / effizientere Möglichkeit, dies zu tun? Vorschläge für alternative Ansätze sind willkommen.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage