Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 18, 2025 20:12

Foren-Übersicht » Programmierung » OpenGL
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 19 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: Selection theoretische Vorarbeit
BeitragVerfasst: Do Nov 09, 2006 07:53 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Hi Leute,
Also keine Angst es hat nichts mit der Realisation der Selection zu tun, das ist ja ausreichend um Tutorial beschrieben.
Meine Frage aber nun:

Sicher jeder, der von Euch 3d Programme irgendwelcher Art schreibt, hat x-verschiedene Anwendungen für Selectionen. Meine Frage jetzt: Wie verwaltet ihr diese Sinnvoll?
Habt ihr eine Art SelectionManager, in dem ihr die Selectionen überprüfen lasst, in dem neue hinzugefügt werden usw?

Könnte mir vorstellen, dass das funktioniert. Mein Problem ist leider, dass ich im Rahmen der Selection meine ganze Szene rendern muss. Wenn ich nun die Selectiion in eine andere externe Datei zb die Selectionmanager.pas, dann kann ich ja kaum meinen Rendervorgang innerhalb der Funktion ausführen. Das ist ein bisschen umständlich. Hat wer ne Idee, was ich da Stattdessen machen kann?

Danke


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Nov 10, 2006 11:59 
Offline
DGL Member

Registriert: Fr Okt 06, 2006 13:55
Beiträge: 12
Mir wurde von nem Kollegen, der das ganze beruflich macht folgendes geraten:

Versuch nie, oder so wenig wie nur geht, von der Grafikkarte zu lesen.
Da ich eh Ray->Triangle und Ray-Box collision brauchte hab ich diese benutzt um mein eigenes Picking zu bauen. Zusätzlich zu der reinen Prüfung ob eine Boundingbox oder ein Triangle getroffen wurde brauchte ich noch die Möglichkeit meine Mausposition in ein Ray umzubauen. Anhand der Kameraposition (die ja meine Cameraklasse weiss, ohne GL zu fragen) und den Informationen über die Near und Farplane kann man recht simpel den Screen auf die Beiden Planes mappen. Damit hat man dann den start und den endpunkt des Mausrays.
Nun muss ich nurnoch alle für mich interessanten Objekte überprüfen ob sie getroffen wurden.
Dafür hab ich nen Collisionmanager, bei dem ich meine Objekte für verschiedene Arten von Kollisionen registriere. Der rennt nun durch alle sichtbaren (das noch bissel dreckig, weil basiert nur auf entfernung, hier fehlt bei mir noch die anbindung ans FCulling) Objekte und testet zuerst die Boundingbox. Für das meiste reicht das schon. Will ichs genau wissen, überprüf ich dann nochmal von allen Objekten deren Boundingbox ich getroffen hab die einzelnen Dreicke um mehr zu wissen.

Auf diesem Weg spar ich das doppelte Rendern der Welt und vorallem das lesen von OpenGL.

Hab das ganze dann mal im testcase nebeneinander probiert und hab festgestellt, daß es so wirklich schneller ist (obwohl ich für meine Objekte ne extra drawfunktion fürs picking hatte, die alles weggelassen hat, was zeit kostete (reine vertexdaten)).


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Nov 10, 2006 12:48 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Man kann bei glLoadName auch Zeiger und Objekte übergeben indem man sie nach Cardinal oder Integer konvertiert. Dann braucht man keine Liste anzulegen.

Bei vielen Dreiecken macht es aber mehr Sinn, die Nummer die man bei glLoadName übergeben würde als Farbe zu kodieren und dann die Farbe zurückzulesen. Wenn man ein Auswahlrechteck benötigt, muß man eben mehr Pixel lesen. Dann braucht man auch keinen Baum oder ähnliches zur Beschleunigung. Das Rendern über Selection ist zusätzlich auch noch wesentlich langsamer, als wenn man nur die Farbe zeichnet, besonders wenn man VBO's benutzt.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Nov 11, 2006 07:40 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Also erstma kurz zur Selection an sich. Ich habe zwar schon eine funktionierende Selection, aber diese will einfach nich..

Code:
  1. procedure TEngine.SetSelection(X,Y: Integer);
  2. var
  3.   Viewport     : TGLVectori4;
  4. begin
  5.   glGetIntegerv(GL_VIEWPORT, @viewport);
  6.   glSelectBuffer(512, @SelectBuffer);
  7.   glRenderMode(GL_SELECT);
  8.   glInitNames;
  9.   glPushName(0);
  10.   glMatrixMode(GL_PROJECTION);
  11.   glPushMatrix;
  12.     glLoadIdentity;
  13.     gluPickMatrix(X, viewport[3]-Y, 1.0, 1.0, viewport);
  14.     gluPerspective(45.0, UseForm.ClientHeight/UseForm.ClientHeight, 1, 1000);
  15. end;
  16.  


Code:
  1. function TEngine.GetSelection: Integer;
  2. var
  3.   Treffer,i    : Integer;
  4.   Z_Wert       : GLUInt;
  5.   Getroffen    : GLUInt;
  6. begin
  7.     glmatrixmode(gl_projection);              //Wieder in den Projektionsmodus
  8.   glPopMatrix;                                //um unsere alte Matrix wiederherzustellen
  9.  
  10.   treffer := glRenderMode(GL_RENDER);         //Anzahl der Treffer auslesen
  11.  
  12.   Getroffen := High(GLUInt);                  //Höchsten möglichen Wert annehmen
  13.   Z_Wert := High(GLUInt);                     //Höchsten Z - Wert
  14.   for i := 0 to Treffer-1 do
  15.   begin
  16.     if SelectBuffer[(i*4)+1] < Z_Wert then
  17.     begin
  18.      getroffen       := SelectBuffer[(i*4)+3];
  19.      Z_Wert := SelectBuffer[(i*4)+1];
  20.     end;
  21.   end;
  22.   if getroffen = High(GLUInt) then Result := -1
  23.   else Result := getroffen;
  24. end;


Code:
  1. procedure TForm1.Render;
  2. begin
  3.   glInitNames;
  4.   glPushName(0);
  5.  
  6.   Engine.DoStart;
  7.  
  8.   glLoadName(1);
  9.   glBegin(GL_QUADS);
  10.   glVertex3f(3,3,0);
  11.   glVertex3f(6,3,0);
  12.   glVertex3f(6,6,0);
  13.   glVertex3f(3,6,0);
  14.   glEnd;
  15.  
  16.   glLoadName(2);
  17.   glBegin(GL_QUADS);
  18.   glVertex3f(-3,-3,0);
  19.   glVertex3f(-3,-6,0);
  20.   glVertex3f(-6,-6,0);
  21.   glVertex3f(-6,-3,0);
  22.   glEnd;
  23.  
  24.   Engine.DoEnd;
  25. end;


Code:
  1. procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  2.   Shift: TShiftState; X, Y: Integer);
  3. begin
  4.   Engine.SetSelection(X,Y);
  5.   Render;
  6. ShowMessage(inttostr(Engine.GetSelection));
  7. end;


Zur erklärung. Aus der Datei Form1 rufe ich die TEngine auf und da innerhalb der selection ja einmal gerendert werden muss, habe ich die Selection zweigeteilt. Einmal SetSelection (alles vor dem Rendern) und einmal Getselection (alles nach dem Rendern). Das sollte von der Theorie her auch so funktionieren. Mein Problem ist nur, wenn ich nun irgendwo in meine Szene klicke, egal wo, dann bekomme ich immer 2. Generell bekomme ich immer die Zahl, die ich als letzte auf den Namestack gelegt habe. Warum, das frage ich Euch ;)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Nov 11, 2006 18:45 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Habes jetz nochma aus der anderen Datei rausgenommen und in die Hauptdatei gelegt:
Code:
  1. procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  2.   Shift: TShiftState; X, Y: Integer);
  3. var
  4.   Treffer,i    : Integer;
  5.   Z_Wert       : GLUInt;
  6.   Getroffen    : GLUInt;
  7.   Viewport     : TGLVectori4;
  8.     SelectBuffer       : array[0..512] of GLUInt;
  9. begin
  10.   glGetIntegerv(GL_VIEWPORT, @viewport);
  11.   glSelectBuffer(512, @SelectBuffer);
  12.   glMatrixMode(GL_PROJECTION);
  13.   glRenderMode(GL_SELECT);
  14.   glPushMatrix;
  15.     glLoadIdentity;
  16.     gluPickMatrix(X, viewport[3]-Y, 1.0, 1.0, viewport);
  17.     gluPerspective(45.0, ClientHeight/ClientHeight, 1, 1000);
  18.  
  19.     Render;
  20.  
  21.     glmatrixmode(gl_projection);              //Wieder in den Projektionsmodus
  22.   glPopMatrix;                                //um unsere alte Matrix wiederherzustellen
  23.  
  24.   treffer := glRenderMode(GL_RENDER);         //Anzahl der Treffer auslesen
  25.  
  26.   Getroffen := High(GLUInt);                  //Höchsten möglichen Wert annehmen
  27.   Z_Wert := High(GLUInt);                     //Höchsten Z - Wert
  28.   for i := 0 to Treffer-1 do
  29.   begin
  30.     if SelectBuffer[(i*4)+1] < Z_Wert then
  31.     begin
  32.      getroffen       := SelectBuffer[(i*4)+3];
  33.      Z_Wert := SelectBuffer[(i*4)+1];
  34.     end;
  35.   end;
  36.   ShowMessage(inttostr(getroffen));
  37. end;


und mein Render
Code:
  1.   Engine.DoStart;
  2.  
  3.   glLoadName(1);
  4.   glBegin(GL_QUADS);
  5.   glVertex3f(3,3,0);
  6.   glVertex3f(6,3,0);
  7.   glVertex3f(6,6,0);
  8.   glVertex3f(3,6,0);
  9.   glEnd;
  10.  
  11.   glLoadName(2);
  12.   glBegin(GL_QUADS);
  13.   glVertex3f(-3,-3,0);
  14.   glVertex3f(-3,-6,0);
  15.   glVertex3f(-6,-6,0);
  16.   glVertex3f(-6,-3,0);
  17.   glEnd;    
  18.  
  19.   Engine.DoEnd;


an der DoEnd hat sich nix geändert, die DoStart hat nun nur die InitNames und die PushName(0) reinbekommen:
Code:
  1. procedure TEngine.DoStart();
  2. begin
  3.   StartTick := GetTickCount;
  4.  
  5.   glGetIntegerv(GL_RENDER_MODE,@RenderMode);
  6.  
  7.   glMatrixMode(GL_MODELVIEW);
  8.   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  9.  
  10.   glLoadIdentity;
  11.  
  12.   glRotatef(ViewingDirection[0],1,0,0);
  13.   glRotatef(ViewingDirection[1],0,1,0);
  14.   glRotatef(ViewingDirection[2],0,0,1);
  15.   glTranslatef(1,-1,-5);
  16.   glTranslatef(ViewingPosition[0],ViewingPosition[1],ViewingPosition[2]);
  17.  
  18.   if KoordSysDraw = TRUE then DrawKoordSys();
  19.  
  20.   glInitNames;
  21.   glPushName(0);
  22. end;


Habe jetzt beide Tuts nochma komplett durchgelesen und KEINE Ahnung warums nich geht...


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Nov 12, 2006 20:49 
Offline
DGL Member
Benutzeravatar

Registriert: So Jun 04, 2006 12:54
Beiträge: 263
Von der Graka lesen ist beim Selektieren kein problem, da es ein vergleichsweise seltner Vorgang ist. In vielen Fällen ist eine Selektion über die Farbe am schnellsten. Dazu sollte man ein FBO benutzen welches ein float32 Framebuffer mit einer Größe von einem bis wenigen wenigen Pixel haben. Nun muss man nur noch jeden Vertex in einer anderen Farbe Zeichnen lassen, wobei Float32 23 bit in der Mantisse hat, was bedeutet, dass man bis zu 8 Mio Vertices mit einem Kanal kodieren kann. Besser ist es ein einem Kanal die Vertexnummer in einem Zweiten die Objektnummer zu speichern.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Nov 12, 2006 20:58 
Offline
DGL Member

Registriert: Sa Okt 22, 2005 20:24
Beiträge: 291
Wohnort: Frauenfeld/CH
das problem ist meiner meinung beim selektieren vorallem, dass man die ganze szene nochmal rendern muss.

_________________
bester uo-shard: www.uosigena.de


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Nov 12, 2006 21:16 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Also ich versteh eure antworten nich so ganz. ich wollte eigentlich wissen, warum meine selektion nich geht ^^


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Nov 12, 2006 23:10 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Code:
  1. gluPerspective(45.0, ClientHeight/ClientHeight, 1, 1000);


Wenn das kein Tippfehler ist, dann liegt dein Problem daran, der Aspektratio wäre dann immer 1.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Nov 13, 2006 16:41 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Das ist natuerlich aeusserst dumm von mir gewesen ;)
Aber funken tut es deshalb immernoch nicht. *seufzt*


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Nov 13, 2006 17:20 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Dann versuch mal die Selektion visuell zu "debuggen", also zu prüfen ob für die Selektion (die man ja nicht sieht) auch alles korrekt gerendert wird. Also ganz einfach die Pickmatrix etwas erweitern (damit man was erkennt), nicht nach GL_SELECT umschalten und dann am Ende Pause machen (Sleep oder besser Tastendruck). Dann sieht man nämlich sehr schnell ob dass was in der Seletkion gerendert wird auch dem entspricht was man dort gerendert haben will.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Nov 13, 2006 18:29 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Also keine Ahnung, ob ich das jetzt richtig verstanden habe ^^ ich habes mal versucht:
Code:
  1.  
  2. procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  3.   Shift: TShiftState; X, Y: Integer);
  4. var
  5.   Treffer,i    : Integer;
  6.   Z_Wert       : GLUInt;
  7.   Getroffen    : GLUInt;
  8.   Viewport     : TGLVectori4;
  9.     SelectBuffer       : array[0..512] of GLUInt;
  10. begin
  11.   glGetIntegerv(GL_VIEWPORT, @viewport);
  12.   glSelectBuffer(512, @SelectBuffer);
  13.   glMatrixMode(GL_PROJECTION);
  14.   glRenderMode(GL_RENDER);
  15.   glPushMatrix;
  16.     glLoadIdentity;
  17.     gluPickMatrix(X, viewport[3]-Y, 1.0, 1.0, viewport);
  18.     gluPerspective(45.0, ClientWidth/ClientHeight, 1, 1000);
  19.  
  20.   test.SetDrawMode(GL_FRONT,GL_FILL);
  21.   test.SetDrawMode(GL_BACK,GL_FILL);
  22.  
  23.   glDisable(GL_TEXTURE_2D);
  24.   glColor4f(0.3,0.4,0.8,0.4);
  25.  
  26.   glLoadName(dreieck);
  27.   test.draw;
  28.  
  29.   test.SetDrawMode(GL_FRONT,GL_LINE);
  30.   test.SetDrawMode(GL_BACK,GL_LINE);
  31.   glColor4f(1,1,1,1);
  32.  
  33.   glLoadName(viereck);
  34.   test.draw;
  35.  
  36.   test.SetDrawMode(GL_FRONT,GL_FILL);
  37.   test.SetDrawMode(GL_BACK,GL_FILL);
  38.  
  39.   glLoadName(stern);
  40.   test.SetMeshMode(TRUE);
  41.   Test.Draw;
  42.   test.SetMeshMode(FALSE);
  43.  
  44.     glmatrixmode(gl_projection);              //Wieder in den Projektionsmodus
  45.   glPopMatrix;                                //um unsere alte Matrix wiederherzustel
  46.  
  47.   Engine.DoEnd;
  48. end;


Also wenn ich jetzt an die Stelle klicke, wo vorher die Kugel war, sehe ich nach dem Klick einen ausschnitt der Kugel, der scheinbar sehr nahe an mir dran ist. Ich sehe entweder nur ein Blaue Fläche, die ein Teilstueck meiner Kugel ist, oder eine blaue Flaeche und weisse Linien, wenn ich in die Naehe des Wireframes klicke.
Klicke ich ausserhalb klicke, sehe ich nur meinen schwarzen raum und mein koordinatensystem.

Weiss nicht genau, ob es so funktioniert. Erhöhe ich die PickMatrix scheint das Ziel weiter weg von mir dargestellt zu werden, da bin ich aber nicht sicher. Zumindest weiss ich nicht, ob es so stimmt ^^


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Nov 13, 2006 18:48 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Jetzt siehst du halt ob das was gerendert werd dem entspricht das selektiert werden sollte wenn jemand an diese Stelle klickt. Wenn sich das Bild nicht ändert, egal wo hin du klickst, und die Kugel dann ne ID von 2 hat (die du ja immer zurückbekommst), dann renderst du während der Selektion evtl. einen falschen Bildausschnitt.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Nov 13, 2006 18:51 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Naja es wird ein sehr kleiner Bildausschnitt dann ueber das gesamte Fenster gerendert. So wie du es erklaerst, macht es sinn, denn wenn ich die Pickmatrix auf 100 100 setze, wird der ausschnitt scheinbar weiter weg angezeigt. In wirklichkeit ist ja aber der gesamte ausschnitt von 1 1 auf 100 100 angewachsen. Stimmt also scheinbar alles

Dennoch kommt immernoch ne 3 bei Selektieren also keine Aenderung


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Nov 15, 2006 21:52 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Hast du sonst noch eine Idee?
Ich habe mal eine Demo angehängt. Szene wird normal gerendert. Clickt man links, wird die Selektion gerendert, klickt man rechts sieht man wieder die ganze Szene und kann neu linksklicken.

Denke mal, das funkt so, wie du es meintest
http://shaddow89.sh.funpic.de/Demo.rar


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 19 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » OpenGL


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 15 Queries | GZIP : On ]