# LWJGL: 3D Picking



## Rubber (14. Sep 2013)

Hi,
ich such ne Möglichkeit, Picking in 3D zu realisieren.

Leider finde ich kaum eine Anleitung im Netz dazu, mit der ich klar komme.

Soweit ich weis, ist die Methode mit OpenGL (GL_SELECT) veraltet und wird nicht mehr unterstützt.

Da ich ein Objekt zu einem Schnittpunkt mit (erstmal) einer Ebene bewegen möchte, würde es sich anbieten einen Strahl zu berechnen und dann den Schnittpunkt mit der Ebene zu berechnen.

Der Strahl müsste dann ja von der Kamera durch die Maus gehen.
Und da scheiter ich momentan dran.

Ich hab zwar bereits einige Code Beispiele gefunden, steig aber noch nicht ganz durch, was was macht.

Hier mal ein Stück Code und dazu ein Paar fragen:

```
public static Ray getScreenCenterRay() {
		//Der Mittelpunkt des Fensters wird ermittelt
		float winX = Display.getWidth() / 2, winY = Display.getHeight() / 2;
		
		//hier werden dann irgendwelche matritzen ausgelsen und gespeichert. Aber was steht in denen drin? Was machen sie?
		IntBuffer viewport = BufferUtils.createIntBuffer(16);
		GL11.glGetInteger( GL11.GL_VIEWPORT, viewport );

		FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
		GL11.glGetFloat( GL11.GL_MODELVIEW_MATRIX, modelview );
		
		FloatBuffer projection = BufferUtils.createFloatBuffer(16);
		GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
		
		FloatBuffer positionNear = BufferUtils.createFloatBuffer(3);
		FloatBuffer positionFar = BufferUtils.createFloatBuffer(3);
		
		//und hier verstehe ich auch noch nicht, was genau vorgeht.
		//wenn ich richtig verstanden habe, wird in der oberen Zeile die 3D Koordinaten
		//für die fenstermitte an der stelle, die am Dichtesten an der Kamera ist berechnet.
		//und in der Zeile dadrunter die koordinaten an der stelle, die am weitesten weg
		//von der Kamera ist.
		//das müsste dann ja mit Maus koordinaten ebenso funktionieren.
		//bringt mich aber nicht weiter(?), weil ich den Vektor aus Kamera und Mausüosition brauche
		//Also müsste ich hier 
		//GLU.gluUnProject(Mouse.getx(), Mouse.getY(), 0, modelview, projection, viewport, positionFar);
		//nehmen, damit ich die Mauskoordinaten an der dichtesten Stelle der Kamera habe?
		//und dann brauch ich noch die koorinaten der Kamera und kann einen Vektor aufstellen.
		//dann gilt PosKamera + Vector * länge als glecihung für den Strahl?
		//Aber wie komm ich an die Kamera position?
		GLU.gluUnProject(winX, winY, 0, modelview, projection, viewport, positionNear);
		GLU.gluUnProject(winX, winY, 1, modelview, projection, viewport, positionFar);
		
		Vector3f nearVec = new Vector3f(positionNear.get(0), positionNear.get(1), positionNear.get(2));
		Vector3f farVec = new Vector3f(positionFar.get(0), positionFar.get(1), positionFar.get(2));
		return new Ray(nearVec, Vector3f.sub(farVec, nearVec, null).normalise(null));
```

Bleibt also die Frage:
wie an die Koordinaten der Kamera kommen?
Und stimmt meine vermutung zu den Koordinaten der Maus?

Danke für eure Hilfe.
Gruß,
David


----------



## Hestalon (17. Sep 2013)

Hi,

der meiner Meinung nach wichtigste Punkt ist es zu wissen in welchen "Raum"/"Space" wie auch immer man sich befindet. 
Beispielsweise befinden sich die Mauskoordinaten im Screenspace. Linke obere Ecke (0,0) rechts unten (1024,768).







Anhand von dem Bild könnte man es erläutern. Dein Bild auf dem Bildschirm ist die "near clipping lane".
Somit bin ich den Weg gegangen mir einen Vector zu erstellen vom Mittelpunkt der near cliplane zur aktuellen Mausposition (teilen und abziehen der Hälfte der Auflösung).
Anschließen die Größe der near cliplane im Worldspace (3D-Umwelt mit allen Objekten deiner Szene) berechnen (Tangens).

Von der Camera sollten Richtungs-,Up- und Left-Vektor bekannt sein (muss iwo schonmal in die Projektionsmatrix gesteckt worden sein). Denn diese Vektoren müssen skaliert werden. 
Richtung: auf near cliplane entfernung
Left: X-Richtung der Maus
Up: Y-Richtung der Maus
Zuletzt werden diese Aufaddiert und du hast den Vektor den du beliebig skalieren kannst. 

Bsp: Kamerapos + scale * Vek = TestPos.
___________________________________

Das was ich hier beschrieben habe, eventuell unverständlich, sollte machbar sein.
Es kann natürlich sein, dass das kopierte Beispiel schneller/besser ist, weil es OpenGL selbst macht über die Matrizen, jedoch ist das genau der Punkt, dass du es nicht verstehst.
Dein 2. Kommentar ist das beste Beispiel dafür: "irgendwelche matrizen" => google Rotationsmatrizen Projektionsmatrizen etc 
z.b. Projectionmatrix



Aber deine Vermutung selbst stimmt ja, anstatt der Mitte des Bildschirms die Mauskoordinaten übergeben und sollte gehn.
Und die Position der Kamera musst! du zuvor schon angegeben haben.

Gruß


----------



## Rubber (17. Sep 2013)

Hi,
danke für deinen Beitrag.
So langsam ergibt alles einen Sinn *g

Auch das mit den Matrizen hab ich so langsam verstanden.

Und gerade auch dein schönes Bild und die Ausführungen geben mir ein weiteres verständnis.

Vielen Dank!


----------



## Hestalon (18. Sep 2013)

Hast du es denn hinbekommen ?
Denn das "schöne" bei solchen Dingen, besonders bei Shadern, ist dass man wissen muss was man tut sonst passiert entweder gar nichts, Fehler oder Magic dass es doch geht ;D


----------



## Rubber (18. Sep 2013)

Hi,
hab heute Nacht was funktionierendes hinbekommen.

Das Tutorial unter OpenGL Picking in 3D hat mir dabei auch gut weiter geholfen.
Und als dann von dir noch der Zusammenhang Projektionsmatrix und Camera-Vektoren kam, hab ich dann acuh raus gefunden, wie ich dort die Vektoren wieder auslesen kann.

Inzwischen dürfte es bei mir also eine Mischung aus "Magic" und wissen sein 
Aber es klappt.

*freu*


----------

