# LWJGL 3D Picking Identifizierung



## javaPanther (21. Okt 2011)

Hallo liebe Leute,
ich baue derzeit an meinem ersten kleinen 3D Spiel und habe meines Erachtens nach bereits Level 2 der 3D Fähigkeiten erlangt, allerdings fehlen immernoch einige Kenntnisse. Daher falls das Problem zu offensichtlich ist bitte nicht hauen 

Ich habe ein online Tutorial so umgebaut, dass es meinen Anforderungen in etwa entspricht, allerdings ist ein Teil noch etwas nebulös:


```
private void selection() {                                            // This Is Where Selection Is Done
    	int buffer[] = new int[512];                                        // Set Up A Selection Buffer
        int hits;                                               // The Number Of Objects That We Selected
    	
    	// The Size Of The Viewport. [0] Is <x>, [1] Is <y>, [2] Is <length>, [3] Is <width>

        int viewport[] = new int[4];

        // This Sets The Array <viewport> To The Size And Location Of The Screen Relative To The Window
        IntBuffer temp = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder()).asIntBuffer();
        temp.order();
        GL11.glGetInteger(GL11.GL_VIEWPORT, temp);
        temp.get(viewport);
        temp = ByteBuffer.allocateDirect(2048).asIntBuffer();
        GL11.glSelectBuffer(temp);                                // Tell OpenGL To Use Our Array For Selection
        temp.get(buffer);

        // Puts OpenGL In Selection Mode. Nothing Will Be Drawn.  Object ID's and Extents Are Stored In The Buffer.
        GL11.glRenderMode(GL11.GL_SELECT);

        GL11.glInitNames();                                              // Initializes The Name Stack
        GL11.glPushName(0);                                              // Push 0 (At Least One Entry) Onto The Stack

        GL11.glMatrixMode(GL11.GL_PROJECTION);                                // Selects The Projection Matrix
        GL11.glPushMatrix();                                             // Push The Projection Matrix
        GL11.glLoadIdentity();                                           // Resets The Matrix

        // This Creates A Matrix That Will Zoom Up To A Small Portion Of The Screen, Where The Mouse Is.
        GLU.gluPickMatrix((float) mouse_x, (float) (viewport[3] - mouse_y), 1.0f, 1.0f, IntBuffer.wrap(viewport));

        // Apply The Perspective Matrix
        GLU.gluPerspective(45.0f, (float) (viewport[2] - viewport[0]) / (float) (viewport[3] - viewport[1]), 0.1f, 100.0f);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);                                 // Select The Modelview Matrix
        drawTargets();                                              // Render The Targets To The Selection Buffer
        GL11.glMatrixMode(GL11.GL_PROJECTION);                                // Select The Projection Matrix
        GL11.glPopMatrix();                                              // Pop The Projection Matrix
        GL11.glMatrixMode(GL11.GL_MODELVIEW);                                 // Select The Modelview Matrix
        hits = GL11.glRenderMode(GL11.GL_RENDER);                               // Switch To Render Mode, Find Out How Many
                                                                    // Objects Were Drawn Where The Mouse Was
        if(hits > 0) {                                               // If There Were More Than 0 Hits
            int choose = buffer[3];                                 // Make Our Selection The First Object
            int depth = buffer[1];                                  // Store How Far Away It Is

            for (int i = 1; i < hits; i++) {                // Loop Through All The Detected Hits
                // If This Object Is Closer To Us Than The One We Have Selected
                if (buffer[i * 4 + 1] < (int)depth) {
                    choose = buffer[i * 4 + 3];                      // Select The Closer Object
                    depth = buffer[i * 4 + 1];                       // Store How Far Away It Is
                }
            }

            if (!objects.get(choose).hit) {                               // If The Object Hasn't Already Been Hit
                System.out.println(objects.get(choose).id);
            }
        }
    }
```

in der Liste Objects werden momentan 2 Zielobjekte (Quads) gespeichert und dargestellt. Beide werden bei einem Klick darauf erkannt und es erfolgt eine Ausgabe, dass ein Objekt erkannt wurde. Leider fehlt an dieser Stelle noch die Unterscheidung zwischen beiden. Gleich auf welches Objekt man klickt wird zunächst immer das erste in der Liste ausgegeben (was vermutlich auf der Auswahl innerhalb der "Objekt gefunden" Abfrage basiert). Hier nun meine Frage:

Wie kann ich herausfinden, welches der beiden Objekte aus der Liste tatsächlich angesprochen wurde?

Falls noch Fragen / Daten offen sind die zur Lösung des Problems fehlen fragt bitte einfach nach!

Beste Grüße und Danke im Voraus!


----------



## Marco13 (21. Okt 2011)

Ich hab' diese OpenGL-Selection nur mal kurz für einen Test benutzt - für die meisten Dinge liefert es einfach nicht genug Information (z.B. WO genau man ein Dreieck angeklickt hat) aber soweit ich mich erinnere, muss man jedem Objekt mit Hilfe der Befehle, die mit solchen wie
GL11.glPushName(0);   
zu tun haben, einen eigenen "Namen" geben...

Warte aber erstmal ab, was Fancy dazu sagt...


----------



## Guest2 (21. Okt 2011)

Moin,



Marco13 hat gesagt.:


> Warte aber erstmal ab, was Fancy dazu sagt...



glPushName ist auch mein erster Gedanke. 

Bei mehr als einem Objekt, sollte glPopName() vermutlich auch noch eingestreut werden. Ob der Rest des snippets so stimmt, kann ich aber auch nicht sagen, ohne nachsehen zu müssen. Selektion Mode ist im Allgemeinen nicht schön, aber hier in dem Fall vermutlich erstmal richtig, da einfach und vermutlich ausreichend.

Gruß,
Fancy


----------



## javaPanther (22. Okt 2011)

Ich ahne hier einen eindeutig negativen Touch meiner Lösung. Falls Jemand einen besseren Vorschlag (am besten mit Beispielimplementierung) hat bin ich gerne bereit diesen auszuprobieren. Wie bereits geschrieben habe stellen dies meine ersten Versuche im 3D Rahmen dar. Leider ist mir die Verwendung des Namestacks nicht ganz klar wie ich mit diesem eindeutig meine in Java realisierten Objekte referenziere. Momentan werden sie wie folgt aufgebaut:


```
front = new Objects(target, "front");   
        back = new Objects(target, "back"); 
        back.rotation = 90;
        back.x = 0.6f;
        back.y = 0f;
        back.z = 0f;
        objects = new LinkedList<Objects>();
        objects.add(front);
        objects.add(back);
```


```
class Objects {
	
    boolean hit;                                            // Object Hit?
    int  texid;                                             // Object Texture ID
    float x = 0;                                                // Object X Position
    float y = 0;                                                // Object Y Position
    public String id;
    public int rotation = 0;
                                        // Object Distance
    public Texture texture;
    
    public float sizeX = 0.1f, sizeY= 0.1f, z = -0.9f;
    
    public Objects(Texture texture, String id) {
    	this.id = id;
    	this.texture = texture;
        hit = false;                                      // Reset Object Has Been Hit Status To False
        texid = (int)(Math.random() * 5);                                 // Assign A New Texture
    }
}
```

Zugegebenermaßen ist der Code noch etwas unaufgeräumt, aber ich möchte erstmal die Funktion sicherstellen bevor ich sauber mache ^^

Danke für die Antworten soweit.


----------



## Marco13 (22. Okt 2011)

Wieder mit dem Halbwissen und dem Fallback Fancy als Notretter falls ich bullshit rede  : Soweit ich mich erinnere, war dieses "Aufbauen der Picking-Informationen" so gedacht, dass man etwa sowas macht wie

```
glInitNames();

// Male ein pickbares Auto
glPushName(AUTO); // (Großgeschriebenes = int-Konstanten)
maleKarossierie();

glPushName(RAD_VORNE_LINKS);
maleRadVorneLinks();
glPopName();

glPushName(RAD_VORNE_RECHTS);
maleRadVorneRechts();
glPopName();
...
glPopName(); // AUTO
```

So dass man beim Picking später feststellen kann, dass man ein AUTO angeklickt hat, und bei bedarf genauer: Ein AUTO und davon das RAD_VORNE_LINKS

Aber nochmal: Das müßte ich mir das auch nochmal genauer anschauen. Im Redbook unter Chapter 13 - OpenGL Programming Guide ist das so ähnlich und etwas ausführlicher (ganz gut) erklärt.


Dieses Picking kann für einige Fälle sehr praktisch und völlig ausreichend sein. Der (für mich) entscheidende Nachteil dieses Picking-Verfahrens ist aber, dass man eben nur erkennt: Ja, ich habe das Vorderrad angeklickt. Aber man weiß nicht, an welcher Stelle man das Rad angeklickt hat. D.h. man bekommt nicht die echte Position im 3D-Raum, an der die Maus das Rad getroffen hat, sondern nur die Information: "Joa, das war das Rad".

Für Detailliertere Informationen wird sicher Fancy etwas mit Tesselation-Feedback-Extensions im Tangentialraum des Geometrieshaders erzählen können   ... Ich habe immer die Geometrie in einer echten "Mesh-Datenstruktur" gespeichert, bei einem Klick dann einen "Picking-Strahl" berechnet, und detailliert nachgeschaut, welches Dreieck des Meshes an welcher Stelle von diesem Strahl getroffen wurde. Ich könnte dazu zwar ein paar Klassen posten, aber die sind so für sich betrachtet vielleicht gar nicht sooo hilfreich, da gehört ein bißchen was an "Infrastruktur" drumrum. Wenn es dir primär um OpenGL an sich geht, gibt es sicher Dinge, die am Anfang interessanter und relevanter sind (VAOs, Shader & Co...)


----------



## Empire Phoenix (22. Okt 2011)

Ich kann die bei der gelgenheit jbullet empfehlen, eigentlich zwa eine vollwertie physic engine, kann man auch nur den collision detection teil benutzen. Das schwierige wird seind iene meshes /objecte jbullet zu verstehen zu geben, dannach wird es aber schnelelr sein als alles was man alleine in einem jahr geschreiben bekommt, da es intern sehr ausgereift algorithmen verwendet.


----------



## Guest2 (22. Okt 2011)

Also ich würde immer zu einer dieser 4 Varianten greifen.

Variante 1 ist die, an welcher sich javaPanther gerade versucht.
Zu Variante 2 gibt es hier ein jogl Beispiel.
Zu Variante 4 gibt es hier einen Ansatz.
Zu Variante 3 gibt es hier einen Anriss, wie man sich das in etwa vorstellen könnte.

Variante 3 ist zwar mit Abstand die technisch anspruchsvollste, bietet dafür aber auch die meisten Möglichkeiten und passt sauber in eine GL3.1+ Umgebung. Imho lässt sie sich auch immer so in den normalen renderablauf integrieren, das sie zeitlich praktisch kostenlos ist. Ich kann mir nicht vorstellen, wie jBullet da schneller sein könnte. (ich kenne jBullet dazu aber auch nicht gut genug)

Trotzdem halte ich es für sinnvoll die erste Variante Mal implementiert zu haben, weil es imho hilft, zu verstehen, wie OpenGL im Allgemeinen funktioniert und aufgerufen wird. Variante 2 dürfte die am häufigsten Genutzte sein.

Gruß,
Fancy


----------



## javaPanther (22. Okt 2011)

Wie gesagt bin ich Allen Ansätzen gegenüber offen. Color Picking hört sich schon sehr gut an wenn ich es über die Graka realisieren kann. Allgemein möchte ich aber vorwegnehmen, dass ich keine sehr aufregenden Sachen geplant habe. Im eigentlichen Sinne ist nur eine Skybox geplant innerhalb derer man sich zentriert befindet. Um einen herum sind verschiedene Objekte (in Form von Billboards) mit denen man interagieren kann (vorrangig durch darauf zentrieren und klicken).

Das einfachste und schnellste Verfahren wäre mir somit am liebsten. Teilweise handelt es sich bei den Objekten auch um "Wegepunkte" die ein Eregins auslösen und nur transparent vorhanden sind. Lassen die sich auch auf den beiden Wegen (1 und 2) realisieren?


----------



## Guest2 (23. Okt 2011)

In Deinem Fall dürfte es keinen Unterschied machen, ob Du dich für Variante 1 oder 2 entscheidest. Auch wenn Variante 1 intern in Software vom Grafikkartentreiber erledigt wird, ist das nicht so langsam das man das spüren wird. Mit Deinem Code von oben und dem was Marco schrieb, solltest Du eigentlich bereits alles für Variante 1 haben. 



javaPanther hat gesagt.:


> Teilweise handelt es sich bei den Objekten auch um "Wegepunkte" die ein Eregins auslösen und nur transparent vorhanden sind. Lassen die sich auch auf den beiden Wegen (1 und 2) realisieren?



Beiden Verfahren ist gemein, das es einen extra durchgang gibt, bei dem alle picking objekte an OpenGL weitergereicht werden ("gerendert"). Das wirkt zwar wie das normale "Zeichnen" mit OpenGL, wird aber nicht auf dem Bildschirm sichtbar. Insofern kannst Du auch Deine transparenten picking objekte "zeichnen" (bei Variante 2 würden Sie dann eine eindeutige Farbe bekommen, aber die ist eben auf dem Bildschirm nicht sichtbar).

Gruß,
Fancy


----------



## javaPanther (23. Okt 2011)

Momentan habe ich mich an den 3 vorgeschlagenen Varianten probiert und kann nicht sagen, dass bis jetzt etwas zu Zufriedenheit geklappt hätte. Hier mal meine Interpretation der 2. Variante in LWJGL. 


```
private final ByteBuffer color = ByteBuffer.allocateDirect(4);
    public void colorPickTest() {
 
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        GL11.glLoadIdentity();
 
        // picking pass
        GL11.glEnable(GL11.GL_SCISSOR_TEST);
        GL11.glScissor(400, 300, 1, 1);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
 
        int i = 0;
        for (float y = -0.75f; y <= +0.75f; y += 0.5)
            for (float x = -0.75f; x <= +0.75f; x += 0.5) {
                i += 1;
 
                GL11.glColor3ub((byte) ((i >> 0) & 0xff), (byte) ((i >> 8) & 0xff), (byte) ((i >> 16) & 0xff));
                drawTargets();
            }
 
        GL11.glDisable(GL11.GL_SCISSOR_TEST);
        GL11.glReadPixels(400, 300, 1, 1, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, color);
        final int selected = color.getInt(0);
 
 
        // color pass
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
        GL11.glColor3f(1.0f, 0.0f, 0.0f);
 
        i = 0;
        for (float y = -0.75f; y <= +0.75f; y += 0.5)
            for (float x = -0.75f; x <= +0.75f; x += 0.5) {
 
                i += 1;
 
                if (i == selected)
                	GL11.glColor3f(0.0f, 0.0f, 1.0f);
 
                else
                	GL11.glColor3f(1.0f, 0.0f, 0.0f);
 
                drawTargets();
            } 
    }
```

Leider funktioniert sie auch nicht, wobei ich hier auch keine Anhaltspunkte habe wie die Daten ausgewertet werden und wie sie erhoben werden. Zumindest Compiliert es und wird ausgeführt, aber es endet ausschließlich in der else Passage bei der selected Abfrage.  Ich wär schon zufrieden, wenn mir angezeigt wird, wenn ich ein Objekt getroffen habe und welches es ist ^^ Es muss nicht präzise sein...

Gäbe es bei meiner 1. geposteten Variante eine Möglichkeit über den Name-Stack herauszufinden, welches Objekt angewählt wurde? Ich weis, es ist viel Quelltext, aber der Fehler könnte in all diesen Passagen liegen 
Ich hoffe es erbarmt sich trotzdem Jemand ^^


```
Objects front = new Objects(target, 111);   
        Objects back = new Objects(target, 222); 
        back.rotation = 90;
        back.x = 0.6f;
        back.y = 0f;
        back.z = 0f;
        objects = new LinkedList<Objects>();
        objects.add(front);
        objects.add(back);

private void selection() {                                            // This Is Where Selection Is Done
    	int buffer[] = new int[512];                                        // Set Up A Selection Buffer
        int hits;                                               // The Number Of Objects That We Selected
    	
    	// The Size Of The Viewport. [0] Is <x>, [1] Is <y>, [2] Is <length>, [3] Is <width>

        int viewport[] = new int[4];

        // This Sets The Array <viewport> To The Size And Location Of The Screen Relative To The Window
        IntBuffer temp = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder()).asIntBuffer();
        temp.order();
        GL11.glGetInteger(GL11.GL_VIEWPORT, temp);
        temp.get(viewport);
        temp = ByteBuffer.allocateDirect(2048).asIntBuffer();
        GL11.glSelectBuffer(temp);                                // Tell OpenGL To Use Our Array For Selection
        temp.get(buffer);

        // Puts OpenGL In Selection Mode. Nothing Will Be Drawn.  Object ID's and Extents Are Stored In The Buffer.
        GL11.glRenderMode(GL11.GL_SELECT);

        GL11.glInitNames();                                                 // Push 0 (At Least One Entry) Onto The Stack

        GL11.glMatrixMode(GL11.GL_PROJECTION);                                // Selects The Projection Matrix
        GL11.glPushMatrix();                                             // Push The Projection Matrix
        GL11.glLoadIdentity();                                           // Resets The Matrix

        // This Creates A Matrix That Will Zoom Up To A Small Portion Of The Screen, Where The Mouse Is.
        GLU.gluPickMatrix((float) width / 2, (float) (viewport[3] - height / 2), 1.0f, 1.0f, IntBuffer.wrap(viewport));

        // Apply The Perspective Matrix
        GLU.gluPerspective(45.0f, (float) (viewport[2] - viewport[0]) / (float) (viewport[3] - viewport[1]), 0.1f, 100.0f);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);                                 // Select The Modelview Matrix
        drawTargets();                                              // Render The Targets To The Selection Buffer
        GL11.glMatrixMode(GL11.GL_PROJECTION);                                // Select The Projection Matrix
        GL11.glPopMatrix();                                              // Pop The Projection Matrix
        GL11.glMatrixMode(GL11.GL_MODELVIEW);                                 // Select The Modelview Matrix
        hits = GL11.glRenderMode(GL11.GL_RENDER);                               // Switch To Render Mode, Find Out How Many
                                                                    // Objects Were Drawn Where The Mouse Was
        if(hits > 0) {     
            int choose = buffer[3];                                 // Make Our Selection The First Object
            int depth = buffer[1];                                  // Store How Far Away It Is

            for (int i = 1; i < hits; i++) {                // Loop Through All The Detected Hits
                // If This Object Is Closer To Us Than The One We Have Selected
                if (buffer[i * 4 + 1] < (int)depth) {
                    choose = buffer[i * 4 + 3];                      // Select The Closer Object
                    depth = buffer[i * 4 + 1];                       // Store How Far Away It Is
                }
            }

            if (!objects.get(choose).hit) {                               // If The Object Hasn't Already Been Hit
                System.out.println(objects.get(choose).id);
            }
        }
    }

void drawTargets() {         
        for(int i=0; i < objects.size(); i++){
        	Objects object = objects.get(i);
        	
            // Initializes The Name Stack
        	GL11.glPushName(object.id);   
        	GL11.glPushMatrix();                                    // Push The Modelview Matrix
        	
        	GL11.glTranslatef(object.x, object.y, object.z);
        	GL11.glRotatef(object.rotation, 0, 1, 0);
        	
        	object.texture.bind();
            GL11.glBegin(GL11.GL_QUADS);                                          // Start Drawing A Quad
                GL11.glTexCoord2f(0.0f,0.0f); GL11.glVertex3f(-object.sizeX,-object.sizeY, 0);   // Bottom Left
                GL11.glTexCoord2f(1.0f,0.0f); GL11.glVertex3f( object.sizeX,-object.sizeY, 0);   // Bottom Right
                GL11.glTexCoord2f(1.0f,1.0f); GL11.glVertex3f( object.sizeX, object.sizeY, 0);   // Top Right
                GL11.glTexCoord2f(0.0f,1.0f); GL11.glVertex3f(-object.sizeX, object.sizeY, 0);   // Top Left
            GL11.glEnd(); 
            
            GL11.glPopMatrix();
            GL11.glPopName();
        }
    }

class Objects {
	
    boolean hit;                                            // Object Hit?
    int  texid;                                             // Object Texture ID
    float x = 0;                                                // Object X Position
    float y = 0;                                                // Object Y Position
    public int id;
    public int rotation = 0;
                                        // Object Distance
    public Texture texture;
    
    public float sizeX = 0.1f, sizeY= 0.1f, z = -0.9f;
    
    public Objects(Texture texture, int id) {
    	this.id = id;
    	this.texture = texture;
        hit = false;                                      // Reset Object Has Been Hit Status To False
        texid = (int)(Math.random() * 5);                                 // Assign A New Texture
    }
}
```


----------



## javaPanther (23. Okt 2011)

Eventuell kann das Problem auch daran liegen, dass der Buffer scheinbar leer ist. Zumindest ist dieser zu jedem Zeitpunkt wenn ich ihn mit dem Debugger aufrufe ausschließlich mit 0en befüllt. Ich nehme mal an, dass dies nicht so sein sollte...


----------



## javaPanther (23. Okt 2011)

Hallo liebe Leute,
ich konnte das Problem nun mit Hilfe des folgenden Threads und einem Vergleich der Beispielcodes lösen. 
Picking Buffer always empty.

Das Problem war, dass das Tutorial von Nehe nicht (mehr) korrekt funktioniert. Meines erachtens nach hat sich der Fehler an der Stelle eingeschlichen in welcher der Buffer ausgelesen wird.


```
private void selection() {                                             // Set Up A Selection Buffer
        int hits;                                               // The Number Of Objects That We Selected
    	
    	// The Size Of The Viewport. [0] Is <x>, [1] Is <y>, [2] Is <length>, [3] Is <width>

        int viewport[] = new int[4];

        int buffer[] = new int[256];  // Set Up A Selection Buffer
        IntBuffer temp = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder()).asIntBuffer();
        temp.order();
        GL11.glGetInteger(GL11.GL_VIEWPORT, temp);
        temp.get(viewport);
        temp = ByteBuffer.allocateDirect(1024).order(ByteOrder.nativeOrder()).asIntBuffer();
        GL11.glSelectBuffer(temp);	// Tell OpenGL To Use Our Array For Selection

        // Puts OpenGL In Selection Mode. Nothing Will Be Drawn.  Object ID's and Extents Are Stored In The Buffer.
        GL11.glRenderMode(GL11.GL_SELECT);
        GL11.glInitNames();                                                 // Push 0 (At Least One Entry) Onto The Stack
        GL11.glPushName(0);
        
        GL11.glMatrixMode(GL11.GL_PROJECTION);                                // Selects The Projection Matrix
        GL11.glPushMatrix();                                             // Push The Projection Matrix
        GL11.glLoadIdentity();                                           // Resets The Matrix

        // This Creates A Matrix That Will Zoom Up To A Small Portion Of The Screen, Where The Mouse Is.
        GLU.gluPickMatrix((float) width / 2, (float) (viewport[3] - height / 2), 1.0f, 1.0f, IntBuffer.wrap(viewport));

        // Apply The Perspective Matrix
        GLU.gluPerspective(45.0f, (float) (viewport[2] - viewport[0]) / (float) (viewport[3] - viewport[1]), 0.00001f, 1000.0f);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);                                 // Select The Modelview Matrix
        drawTargets();                                              // Render The Targets To The Selection Buffer
        GL11.glMatrixMode(GL11.GL_PROJECTION);                                // Select The Projection Matrix
        GL11.glPopMatrix();                                              // Pop The Projection Matrix
        GL11.glMatrixMode(GL11.GL_MODELVIEW);                                 // Select The Modelview Matrix
        hits = GL11.glRenderMode(GL11.GL_RENDER);                               // Switch To Render Mode, Find Out How Many
        temp.get(buffer);        // HIER MUSS DER BUFFER EIGENTLICH STEHEN!
        if(hits > 0) {     
            int choose = buffer[3];                                 
            int depth = buffer[1];                                  

            for (int i = 1; i < hits; i++) {                // Loop Through All The Detected Hits
                // If This Object Is Closer To Us Than The One We Have Selected
                if (buffer[i * 4 + 1] < (int)depth) {
                    choose = buffer[i * 4 + 3];                      // Select The Closer Object
                    depth = buffer[i * 4 + 1];                       // Store How Far Away It Is
                }
            }

            System.out.println(choose);
        }
    }
```

Wie man sieht wurde in meiner 1. Version der Buffer direkt nach der Erzeugung ausgelesen, wohingegen er jetzt erst abgerufen wird wenn auch wirklich Ergebnisse darinstehen. (Beachte Stelle "HIER MUSS DER BUFFER EIGENTLICH STEHEN!"). Für mich funktioniert der Code nun. Danke für die Einblicke soweit !^^


----------

