JavaFX 8 Schnittpunkt der 3D-Szene

8

Ist es in einer JavaFX 8 3D-Szene möglich, Punkte entlang eines Strahls (z. B. PickRay) zu finden, beginnend an einem beliebigen Punkt im 3D-Raum mit einem 3D-Richtungsvektor, wo der Strahl die Dreiecke in einem Netz schneidet (TriangleMesh in a MeshView)?

Ich weiß, dass dies im Camera / MouseHandler zur Mausauswahl gemacht wird, aber ich kann keine Möglichkeit sehen, dies für beliebige Strahlen zu tun.

    
Rik 09.12.2014, 14:20
quelle

2 Antworten

9

Da @ jdub1581 vorschlägt, ist ein Strahl nur ein geometrischer Vektor. Um also eine Liste von Dreiecken zu finden, die von diesem Vektor geschnitten werden, müssen wir Probleme der Art "Linie schneidet Ebenen" und "Linie schneidet Ebene innerhalb des Dreiecks" lösen Grenzen ".

Nehmen wir an, wir haben eine TriangleMesh , und wir haben eine Liste von Scheitelpunkten und eine Liste von Gesichtern. Jeder Eckpunkt mit 3 Koordinaten, jede Fläche mit 3 Eckpunkten (ohne Berücksichtigung von Textur, Normalen, ...). Der Einfachheit halber verwenden wir zwei Listen von Point3D , um sie zu speichern.

In diesem Link stehen mehrere 3D-Formen zur Verwendung bereit. Lassen Sie uns ein CuboidMesh greifen.

%Vor%

Dies wird uns diese 3D Form geben:

Nun, wenn wir uns das Mesh ansehen, könnten wir zwei Listen mit Vertices und Faces erstellen:

%Vor%

Lassen Sie uns einige 3D-Punkte in unserer Szene hinzufügen, einen Ursprung und ein Ziel, beide in globalen Koordinaten, und definieren Sie die Richtung des Vektors, normalisiert:

%Vor%

Die Strahlengleichung lautet dann:

%Vor%

Wenn wir zwischen diesen beiden Punkten einen schlanken Zylinder hinzufügen, haben wir eine visuelle Darstellung unseres Strahls:

Begrenzung des Begrenzungsrahmens

Im ersten Schritt wird geprüft, ob der Strahl die Begrenzungsbox unserer Form schneidet. In lokalen Koordinaten der Form haben wir 6 Gesichter, die durch ihre Normalen mit ihren 6 Zentren gegeben sind:

%Vor%

Da wir am lokalen System arbeiten werden, brauchen wir unseren Ursprungspunkt in diesen Koordinaten:

%Vor%

Nun erhalten wir für jede der sechs Flächen die Entfernung t zur Ebene, die dieser Link . Dann können wir prüfen, ob der Punkt zu der Box gehört oder nicht.

%Vor%

Wenn counter.get()>0 , dann haben wir einige Schnittpunkte zwischen dem Strahl und der Form, und wir können mit den Dreiecken fortfahren. In diesem Beispiel sind dies die Schnittpunkte: (3,5, -4,5, -2) und (2,5,0,5,2).

Dreiecke Kreuzung

Es gibt mehrere Algorithmen für die Aufgabe, herauszufinden, ob der Strahl irgendein Dreieck des Gitters schneidet, so dass wir das Rad nicht neu erfinden müssen.

Der, den ich benutzt habe, stammt von Tomas Möller & amp; Ben Trumbore . Es liefert den Abstand t vom Ursprung zur Ebene und die Koordinaten u,v innerhalb des Dreiecks für einen gegebenen Schnittpunkt.

Sobald wir den Ursprung in den lokalen Koordinaten der Form haben und wir die Richtung des Strahls kennen, ist die Implementierung dieses Algorithmus folgender:

%Vor%

In diesem Beispiel finden wir drei Gesichter, die durch diese Eckpunkte gegeben sind: (85, 1245, 1274), (85, 1274, 1266) und (351, 1476, 1479).

Wenn wir diese Flächen plotten, sehen wir die Schnittmenge:

Beachten Sie, dass bei der Ausführung aller Operationen im lokalen Koordinatensystem der Form die Operationen zum Transformieren jedes Dreiecks in das globale System gespeichert werden.

Dieser Algorithmus ist sehr schnell. Ich habe bis zu 3M Dreiecke in weniger als 40 ms getestet.

Der gesamte Code für diesen Test ist hier verfügbar .

    
José Pereda 23.12.2014, 01:09
quelle
5

Nun, ich habe das fast abgeschlachtet, also werde ich ein sehr leicht zu verstehendes Tutorial zur Verfügung stellen. Es ist gut geschrieben und muss zugeben, dass ich auch viel gelernt habe!

Ich werde die Mathematik dem Artikel überlassen, da es viel zu tun hat (Punkte transformieren und Matrizen verwenden)

Zusammenfassen:

Jeder Punkt auf ray ist eine Funktion der Entfernung vom Ursprung

%Vor%

Hoffe, das hilft!

BEARBEITEN:

Nach Joses großartigem Beispiel, Ich habe mir die Freiheit genommen, eine Ray-Klasse zu erstellen, und ein SimpleRayTest-Beispiel, um den Weg des Strahls über die Entfernung zu zeigen (man denke an den Strahl als Projektil). Es deckt zwar keine Dreiecksüberschneidungen ab, aber es sollte helfen, die Funktionsweise des Strahls zu visualisieren.

Quellen sind auch im Bibliothekslink Jose zur Verfügung gestellt.

    
jdub1581 20.12.2014 23:30
quelle

Tags und Links