OpenGL Selection Mode - Komische Z-Werte



  • Moin!

    Ich komm mit meinem Picking-System unter OpenGL nicht weiter. Ich verwende den OpenGL internen Selection Mode. Im resultierenden Selection Buffer scheint er korrekte Treffer zu liefern, allerdings sind die Z-Werte (min/max) komisch. Laut Red Book Kapitel 13 soll ich die Werte durch 0x7fffffff teilen, aber auch das ändert nichts.

    sSelectionNode* pNearestNode = NULL;
    sSelectionNode* pCurrentNode = NULL;
    CR3DVector3D vPos(0,0,0);
    float fNearest = (float)0xffffffff;
    
    GLuint* pBufferOffset = m_pSelectionBuffer;
    for (GLuint nHit = 0; nHit < m_nSelectionHitCnt; nHit++) 
    { 
    	GLuint nNameCnt = *pBufferOffset;
    	pBufferOffset++;
    
    	float fMinZ = (float)*pBufferOffset / 0x7fffffff;
    	pBufferOffset++;
    
    	float fMaxZ = (float)*pBufferOffset / 0x7fffffff;
    	pBufferOffset++;
    
    	for (GLuint nEntry = 0; nEntry < nNameCnt; nEntry++) 
    	{  
    		pCurrentNode = (sSelectionNode*)*pBufferOffset;
    		if (pCurrentNode != NULL)
    		{						
    			if (fMinZ < fNearest)
    			{
    				fNearest = fMinZ;
    				pNearestNode = pCurrentNode;
    			}
    		}
    
    		pBufferOffset++;
    	}
    }
    

    ... Dieser Code liefert für fMinZ/fMaxZ immer 1.99997 auch wenn die getroffenen Flächen eindeutig nicht die selbe räumliche Tiefe haben. 😕
    Und sollte der Wert nach der Skalierung nicht zwischen 0.0 und 1.0 liegen? 😕



  • Ich würde dir empfehlen auf den Selection Mode der seit OpenGL 3.0 deprecated ist zu verzichten und stattdessen einfach selbst ordentliches Picking zu implementieren so wie man es heute normalerweise macht...



  • Habe ich auch schon drüber nachgedacht, aber keine wirklich vernünftige Alternative gefunden. Ich könnte in einem separaten Pass jede Fläche mit einer eindeutigen Farbe rendern und dann den Farbwert des Pixels auslesen - Aber was, wenn der Treiber irgendwelche Optimierungs-Spielchen macht und die Farbe ändert?
    Ich könnte auch einen Strahl berechnen und eine Kollision mit der Fläche prüfen. Aber das ist erstens aufwändig und zweitens habe ich texturierte Flächen mit Alpha-Key, so das oft nur ein bestimmer Teil eines Polys sichtbar ist.
    Der Selection Mode würde diese Probleme erschlagen, wenn er denn funktionieren würde. Die (seit neuestem) miese Performance wäre mir noch egal, da das Ding eh nur auf Benutzereingabe im Editor aufgerufen werden würde.
    Gibts eigentlich unter OpenGL so eine Art "User-Buffer" für wo ich anhand irgendwelcher Kriterien Werte pro Frame reinknallen kann, ähnlich dem Selection Buffer? Das wäre ja mal was



  • Cpp_Junky schrieb:

    Ich könnte auch einen Strahl berechnen und eine Kollision mit der Fläche prüfen.

    Genau so macht man das normal...

    Cpp_Junky schrieb:

    Die (seit neuestem) miese Performance wäre mir noch egal, da das Ding eh nur auf Benutzereingabe im Editor aufgerufen werden würde.

    Wenn ich dich schon nicht zum Umdenken bewegen kann dann vielleicht die Tatsache dass das Verwenden des selection buffer sogar im Wiki auf opengl.org als "Common Mistake" geführt wird: http://www.opengl.org/wiki/Common_Mistakes#Selection_and_Picking_and_Feedback_Mode

    Cpp_Junky schrieb:

    Gibts eigentlich unter OpenGL so eine Art "User-Buffer" für wo ich anhand irgendwelcher Kriterien Werte pro Frame reinknallen kann, ähnlich dem Selection Buffer? Das wäre ja mal was

    Was genau meinst du damit?



  • Na so in der Art wie der Name Stack unter OpenGL. Ich pushe z.B vorm Zeichnen einer Fläche einen Wert und dieser wird für jedes korrespondierende Pixel in einen Buffer geschrieben (optimalerweise so gross wie der Framebuffer).



  • Naja, es gibt eben den Name Stack den man aber eben nicht benutzen sollte. Wenn du sowas wirklich brauchst kannst du dir das ja, wie du schon bemerkt hast, selbst bauen indem du einfach die entsprechenden Dreiecke in entsprechenden Farben renderst...



  • Ich könnte in einem separaten Pass jede Fläche mit einer eindeutigen Farbe rendern und dann den Farbwert des Pixels auslesen

    Es gibt (insbesondere Notebook-)Chipsaetze die nur in 16Bit rendern (weil zB das Display eh nicht mehr hergibt).
    Und ganz bloede ist, wenn die dann auch noch anfangen zu dithern...



  • hellihjb schrieb:

    Es gibt (insbesondere Notebook-)Chipsaetze die nur in 16Bit rendern (weil zB das Display eh nicht mehr hergibt).
    Und ganz bloede ist, wenn die dann auch noch anfangen zu dithern...

    Meiner Erfahrung nach ist sowas im Jahre 2010 wirklich nichtmehr relevant. Aber natürlich ein Grund mehr sich für die ordentliche Lösung (Ray Picking) zu entscheiden...



  • Wie gesagt, leider ist das bei Alpha maskierten Texturen ungenau. Ok, evtl könnte man bei der Ray-Variante auch irgendwie das betroffene Texel rauskriegen und damit den Alpha-Wert. Naja ist halt recht kompliziert so, aber es wird dann wohl darauf hinauslaufen 🙄



  • Cpp_Junky schrieb:

    Ok, evtl könnte man bei der Ray-Variante auch irgendwie das betroffene Texel rauskriegen und damit den Alpha-Wert.

    Ja das kann man definitiv...Was genau machst du denn dass du durch eine Alphamaske picken musst?



  • Ist so eine Art 3D Ingame Editor, wo ich Billboard Sprites platzieren und möglichst pixelgenau auswählen können muss -> Da die Objekte dicht nebeneinander stehen können und oft Alpha maskiert sind.

    Hab das Selection Mode Problem übrigens inzwischen gelöst: Setze ich in meinem Pixelformat Descriptor den Depth Buffer auf 16bit, darf ich im zurückgelieferten MinZ/MaxZ auch nur das Loword auswerten da vorne anscheinend Schrott drinsteht. Setze ich den Depthbuffer auf 32bit kann ich natürlich den kompletten Gluint nehmen. Dieses Verhalten habe ich hier allerdings nur auf einer Arbeitsstation. Auf zwei anderen Maschinen bekomme ich immer einen sauberen 32bit GLuint, auch wenn mein Depthbuffer nur 16bit gross ist.
    Naja, werde mir die Raylösung aber trotzdem noch offenhalten.


Anmelden zum Antworten