Selektion: Unterschied zwischen den Versionen
Flash (Diskussion | Beiträge) K (→Was ist das?) |
Flash (Diskussion | Beiträge) K () |
||
Zeile 18: | Zeile 18: | ||
[[glRenderMode]], [[glSelectBuffer]], [[glLoadName]], [[gluPickMatrix]], [[Picking]] | [[glRenderMode]], [[glSelectBuffer]], [[glLoadName]], [[gluPickMatrix]], [[Picking]] | ||
+ | |||
+ | |||
+ | ==Beispiele== | ||
+ | |||
+ | ===Selektion in 2D (glOrtho)=== | ||
+ | Im OnShow meines Formulares erstelle ich den Kontext. Zum Initialisieren der Ansicht rufe ich die untere Methode auf: | ||
+ | <pascal>procedure TForm1.FormResize(Sender: TObject); | ||
+ | var | ||
+ | VP: array[0..1] of Integer; | ||
+ | newWidth, newHeight: Integer; | ||
+ | begin | ||
+ | if (FInitialised) then begin | ||
+ | // Set the viewport for the OpenGL window | ||
+ | glGetIntegerv(GL_MAX_VIEWPORT_DIMS, @VP); | ||
+ | |||
+ | // Dont make the Window to large | ||
+ | newWidth := Min(VP[0], ClientWidth); | ||
+ | newHeight := Min(VP[1], Max(1, ClientHeight)); | ||
+ | |||
+ | // Viewport von OpenGL setzen | ||
+ | glViewport( | ||
+ | (ClientWidth div 2) - (newWidth div 2), | ||
+ | (ClientHeight div 2) - (newHeight div 2), | ||
+ | newWidth, | ||
+ | newHeight); | ||
+ | |||
+ | // Projection matrix | ||
+ | glMatrixMode(GL_PROJECTION); | ||
+ | glLoadIdentity(); | ||
+ | |||
+ | // Perspektive setzen | ||
+ | glOrtho(0, newWidth, newHeight, 0, -1, 1); | ||
+ | |||
+ | // Modelview Matrix | ||
+ | glMatrixMode(GL_MODELVIEW); | ||
+ | glLoadIdentity(); | ||
+ | end; | ||
+ | end;</pascal> | ||
+ | |||
+ | Beim Zeichnen mache ich dann nichts weiter als: | ||
+ | <pascal>var | ||
+ | Error: Cardinal; | ||
+ | RenderMode: Cardinal; | ||
+ | begin | ||
+ | // Go to the model view matrix mode | ||
+ | glMatrixMode(GL_MODELVIEW); | ||
+ | |||
+ | // Replaces the current matrix with the identity matrix | ||
+ | glLoadIdentity(); | ||
+ | |||
+ | // Clear the color and depth buffers | ||
+ | glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); | ||
+ | |||
+ | glGetIntegerv(GL_RENDER_MODE, @RenderMode); | ||
+ | |||
+ | glPushName(0); | ||
+ | glLoadName(10); | ||
+ | // Zeichnen | ||
+ | glPopName; | ||
+ | |||
+ | Error := glGetError; | ||
+ | if Error <> 0 then | ||
+ | Caption := gluErrorString(Error); | ||
+ | |||
+ | if (RenderMode = GL_RENDER) | ||
+ | then SwapBuffers (FDC); | ||
+ | end;</pascal> | ||
+ | |||
+ | Die Selection sieht so aus: | ||
+ | <pascal>var | ||
+ | Puffer : array[0..256] of GLUInt; | ||
+ | Viewport : TGLVectori4; | ||
+ | Treffer,i : Integer; | ||
+ | Z_Wert : GLUInt; | ||
+ | Getroffen : GLUInt; | ||
+ | begin | ||
+ | glGetIntegerv(GL_VIEWPORT, @viewport); | ||
+ | glSelectBuffer(256, @Puffer); | ||
+ | glRenderMode(GL_SELECT); | ||
+ | |||
+ | glMatrixMode(GL_PROJECTION); | ||
+ | glLoadIdentity; | ||
+ | |||
+ | gluPickMatrix(X, Viewport[3] - Y, 1.0, 1.0, Viewport); | ||
+ | glOrtho(0, ClientWidth, ClientHeight, 0, -1, 1); | ||
+ | |||
+ | FormPaint(Self); | ||
+ | |||
+ | glMatrixMode(GL_PROJECTION); | ||
+ | |||
+ | treffer := glRenderMode(GL_RENDER); | ||
+ | |||
+ | if treffer > 0 then begin | ||
+ | Getroffen := High(GLUInt); | ||
+ | Z_Wert := High(GLUInt); | ||
+ | for i := 0 to Treffer-1 do | ||
+ | if Puffer[(i*4)+1] < Z_Wert then begin | ||
+ | getroffen := Puffer[(i*4)+3]; | ||
+ | Z_Wert := Puffer[(i*4)+1]; | ||
+ | end; | ||
+ | |||
+ | ShowMessage(IntToStr(Getroffen)); | ||
+ | end; | ||
+ | |||
+ | FormResize(Self); | ||
+ | end;</pascal> | ||
==Links== | ==Links== | ||
− | [ | + | [[Tutorial_Selection| Selektionstutorial von DelphiGL.com]] |
Version vom 20. Oktober 2005, 18:31 Uhr
Inhaltsverzeichnis
Was ist das?
Die Selektion ist ein bestimmter Rendermodus von OpenGL. Im Selektionsmodus (der durch glRenderMode gesetzt wird) werden keine Fragmente erzeugt und auch keine Änderungen am Framebuffer durchgeführt. Anstelle dessen werden 4 Werte pro sichtbaren Primitiven in einen Selektions Puffer geschrieben. Dieser Puffer muss schon vor dem Aufruf dieser Funktion erstellt worden sein.
Die vier Werte die man pro Primitiven erhält sind:
- Anzahl der Namen auf dem Stack
- Kleinster Z-Wert des getroffenen Objektes
- Größter Z-Wert des getroffenen Objektes
- Name des Objektes
Wozu brauch ich das?
Für die Interaktion des Nutzers mit der Szene.
Wie geht das?
Durch den Selektionspuffer bekommt man die OpenGL Namen der Szenen Elemente zurückgeliefert die im Rendermodus GL_RENDER gerendert worden wären. Dies ermöglicht es unter zuhilfenahme von gluPickMatrix den Bereich um einen Mausklick auszuwerten. Wie das genau funktioniert könnt ihr im Selektionstutorial (siehe Links) nachlesen.
OpenGL Funktionen
Folgende Funktionen haben mit der Selektion zu tun:
glRenderMode, glSelectBuffer, glLoadName, gluPickMatrix, Picking
Beispiele
Selektion in 2D (glOrtho)
Im OnShow meines Formulares erstelle ich den Kontext. Zum Initialisieren der Ansicht rufe ich die untere Methode auf:
procedure TForm1.FormResize(Sender: TObject); var VP: array[0..1] of Integer; newWidth, newHeight: Integer; begin if (FInitialised) then begin // Set the viewport for the OpenGL window glGetIntegerv(GL_MAX_VIEWPORT_DIMS, @VP); // Dont make the Window to large newWidth := Min(VP[0], ClientWidth); newHeight := Min(VP[1], Max(1, ClientHeight)); // Viewport von OpenGL setzen glViewport( (ClientWidth div 2) - (newWidth div 2), (ClientHeight div 2) - (newHeight div 2), newWidth, newHeight); // Projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Perspektive setzen glOrtho(0, newWidth, newHeight, 0, -1, 1); // Modelview Matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); end; end;
Beim Zeichnen mache ich dann nichts weiter als:
var Error: Cardinal; RenderMode: Cardinal; begin // Go to the model view matrix mode glMatrixMode(GL_MODELVIEW); // Replaces the current matrix with the identity matrix glLoadIdentity(); // Clear the color and depth buffers glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glGetIntegerv(GL_RENDER_MODE, @RenderMode); glPushName(0); glLoadName(10); // Zeichnen glPopName; Error := glGetError; if Error <> 0 then Caption := gluErrorString(Error); if (RenderMode = GL_RENDER) then SwapBuffers (FDC); end;
Die Selection sieht so aus:
var Puffer : array[0..256] of GLUInt; Viewport : TGLVectori4; Treffer,i : Integer; Z_Wert : GLUInt; Getroffen : GLUInt; begin glGetIntegerv(GL_VIEWPORT, @viewport); glSelectBuffer(256, @Puffer); glRenderMode(GL_SELECT); glMatrixMode(GL_PROJECTION); glLoadIdentity; gluPickMatrix(X, Viewport[3] - Y, 1.0, 1.0, Viewport); glOrtho(0, ClientWidth, ClientHeight, 0, -1, 1); FormPaint(Self); glMatrixMode(GL_PROJECTION); treffer := glRenderMode(GL_RENDER); if treffer > 0 then begin Getroffen := High(GLUInt); Z_Wert := High(GLUInt); for i := 0 to Treffer-1 do if Puffer[(i*4)+1] < Z_Wert then begin getroffen := Puffer[(i*4)+3]; Z_Wert := Puffer[(i*4)+1]; end; ShowMessage(IntToStr(Getroffen)); end; FormResize(Self); end;