Autor Beitrag
P-A-L
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: Mo 21.01.13 21:05 
Hallo zusammen,

seit über einem Jahr liegt mein Projekt auf Eis, weil ich die Selektion von Objekten nicht hinbekomme. Jetzt wende ich mich demütig an die wahren Gurus - Euch! :-)

Ich verwende im Prinzip die Code-Basis aus dem DGL Wiki Tutorial zu Selektion, nur eben erweitert um ein paar Objekte.
Was ich machen möchte: Eine Karte aus 5x5 Hex-Feldern zeichnen (funktioniert) und bei Klick auf eines der Felder den jeweiligen Namen (glLoadName) ausgeben (funktioniert nicht!).

Wenn man jetzt klickt, wird immer derselbe Name ausgegeben, egal ob man ein Objekt getroffen haben sollte oder nicht.
Ich verzweifle da echt dran... Hilfe!!!

EDIT: Ich habe zu Testzwecken die Namensvergabe geändert - also Bitte keine Hinweise á la "Du hast die Namensvergabe auskommentiert" oder so was ;-)

Meine Render-Routine:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
procedure TF_Game.Render;
var i:integer;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(45.0, ClientWidth/ClientHeight, NearClipping, FarClipping);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
  glInitNames;
  glPushName(0);

  theCamera.Apply;
  glLoadName(15);     //test; result: EVERY SelectBufferHit is "15"
  gamemap.draw;
  glLoadName(1);

  glEnd;

  SwapBuffers(DC);
  L_StatusBar.Caption:=text_coords + ' - ' + text_fps + ' - ' + text_info + ' - ' + text_error;
end;


Das wird bei Mausklick aufgerufen (soll selektieren):
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
function TF_Game.getSelectBufferHit():integer;
var
   SelectBuffer : array[0..512of TGLUInt;
   Viewport     : TGLArrayi4;
   Hits,i       : Integer;
   HitZValue    : TGLUInt;
   Hit          : TGLUInt;
begin
  glGetIntegerv(GL_VIEWPORT, @viewport);
  glSelectBuffer(512, @SelectBuffer);
  glRenderMode(GL_SELECT);
  //glInitNames;
  //glPushName(0);
  glMatrixMode(GL_PROJECTION);
  glPushMatrix;
  glLoadIdentity;
  gluPickMatrix(mx, viewport[3]-my, 1.01.0, dglOpenGL.TVector4i(viewport));
  gluPerspective(45.0, ClientWidth/ClientHeight, 0.11000);
  Render;
  glMatrixMode(GL_PROJECTION);
  glPopMatrix;
  Hits := glRenderMode(GL_RENDER);
  Hit       := High(TGLUInt);
  HitZValue := High(TGLUInt);
  for i := 0 to Hits-1 do
    if SelectBuffer[(i*4)+1] < HitZValue then
    begin
      Hit       := SelectBuffer[(i*4)+3];
      HitZValue := SelectBuffer[(i*4)+1];
    end;
  Result := Hit;
end;


Und das sind die HexTile und HexMap Objekte:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
    type TCoord = record
  Col : integer;
  Row : integer;
end;

type THexTile = class
  private
    _ID : integer;
  public
    constructor create(col,row:integer);
    function getID():integer;
    function getxy():TCoord;
    procedure draw(); // draws hex
end;

type TMap = class
  _tiles : array of array of THexTile;
  _sizeRows : cardinal;
  _sizeCols : cardinal;
  procedure draw(); // draws all hexes
  procedure load(); // loads map from file
end;
constructor THexTile.Create(col,row: integer);
  begin
    inherited Create();
    _ID := row*1000+col;
  end;

  function THexTile.getID() : integer;
  begin
    result:=_ID;
  end;

  function THexTile.getxy():TCoord;
  begin
    // ID=14008 means row=14 col=8
    result.Col := _ID mod 1000;
    result.Row := _ID div 1000;
  end;

  procedure THexTile.draw;
  begin
    glLoadName(88);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    //glLoadName(_ID);
    glBegin(GL_POLYGON);
      glTexCoord2f(0.75,0); glVertex3f(0.5,sqrt(0.75),0);
      glTexCoord2f(0.25,0); glVertex3f(-0.5,sqrt(0.75),0);
      glTexCoord2f(0,0.5); glVertex3f(-1,0,0);
      glTexCoord2f(0.25,1); glVertex3f(-0.5,-sqrt(0.75),0);
      glTexCoord2f(0.75,1); glVertex3f(0.5,-sqrt(0.75),0);
      glTexCoord2f(1,0.5); glVertex3f(1,0,0);
    glEnd;
  end;

  procedure TMap.load;
  var
    r,c: integer;
  begin
    setlength(_tiles, _mapsize_x, _mapsize_y);
    // determine columns and rows
    for r:=0 to _mapsize_y-1 do
      for c:=0 to _mapsize_x-1 do
      Begin
        _tiles[c,r]:=THexTile.Create(c,r);
      end;
  end;

  procedure TMap.draw;
  var
    r,c : integer; //row and column of the hextile on the map
    x,y : double;  //coordinates of tile position on render matrix
  begin
    glMatrixMode(GL_MODELVIEW);
    glloadidentity;

    For r:= 0 To _mapsize_y-1 do
      For c:=0 to _mapsize_x-1 do
      Begin
        theCamera.Apply;
        // move pen to mid point of hex
        x:=1+(c*1.5);
        y:=(-1)*((2*r+((c+1mod 2)+1)*sqrt(0.75));
        gltranslatef(x,y,0);
        _tiles[c,r].draw;
    End;
  end;


Moderiert von user profile iconMartok: Code- durch Delphi-Tags ersetzt
Einloggen, um Attachments anzusehen!
Jens01
Hält's aus hier
Beiträge: 9
Erhaltene Danke: 3



BeitragVerfasst: Mo 21.01.13 21:58 
Wenn ich richtig gesehen habe, dann setzt Du mit "glLoadName" den Namen/Nummer auf 15 und renderst alle Objekte. Du mußt aber mit "glLoadName" den Namen/Nummer setzen und das Objekt rendern, das diesen Namen zurückgeben soll, dann wieder neuen Namen setzen und nächstes Objekt rendern usw.
P-A-L Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: Di 22.01.13 16:56 
user profile iconJens01 hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich richtig gesehen habe, dann setzt Du mit "glLoadName" den Namen/Nummer auf 15 und renderst alle Objekte. Du mußt aber mit "glLoadName" den Namen/Nummer setzen und das Objekt rendern, das diesen Namen zurückgeben soll, dann wieder neuen Namen setzen und nächstes Objekt rendern usw.


Hallo Jens,

danke für die Antwort. Wie gesagt, ich hatte mit dem Naming rumgespielt um den Fehler zu finden, diese Zeile war Teil der Tests. Ich werde versuchen, heute abend mal einen "sauberen" Quelltext hochzuladen.
In der Routine "THexTile.Draw" wird das einzelne HexTile mit seiner ID als Name belegt (hier im Quelltext auskommentiert), funktioniert aber trotzdem nicht - es wird immer 15 als Selektion zurückgegeben. Wenn ich den glLoadName(15) entferne, wird halt alles als "0" ausgegeben.

Der Fehler muss also entweder in der GetSelectBufferHit() oder in THexTile.Draw liegen... Oder ich rufe die Routinen in der falschen Reihenfolge auf...

Ich bin bald so weit, ein Preisgeld für das Finden des Bugs auszuloben :p
Jens01
Hält's aus hier
Beiträge: 9
Erhaltene Danke: 3



BeitragVerfasst: Di 22.01.13 18:02 
Guck Dir mal meine CamerAH www.delphigl.com/for....php?f=13&t=9811 an.
Die ist Deiner genutzten Kamera ähnlich und hat auch schon Teile für diese Selektion. Eine weitere Möglichkeit der Selektion (und wohl auch die besser Option) ist dies Colorpicking.
Eigentlich ganz einfach.
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Di 22.01.13 20:25 
Hey,

das glInitNames und glPushNames(0) muss definitiv rein, das initialisiert die ganzen Sachen. Außerdem initialisierst du in deinem Render-Code die ProjektionsMatrix neu, dann is die PickMatrix wieder weg. Also Zeilen 6-8 aus dem RenderCode raus. Wenn das nich hilft, mach das gluPickMatrix mal größer (100x100) und lass den RenderMode auf GL_RENDER, dann kannst du dir angucken, ob da überhaupt das richtige gerendert wird.

€: Ich seh grad das du InitNames und PushNames(0) im RenderCode hast... Dann kann es eig. nur noch an der Projektion liegen...

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
P-A-L Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: Di 22.01.13 21:26 
user profile iconBergmann89 hat folgendes geschrieben Zum zitierten Posting springen:
Hey,

das glInitNames und glPushNames(0) muss definitiv rein, das initialisiert die ganzen Sachen. Außerdem initialisierst du in deinem Render-Code die ProjektionsMatrix neu, dann is die PickMatrix wieder weg. Also Zeilen 6-8 aus dem RenderCode raus. Wenn das nich hilft, mach das gluPickMatrix mal größer (100x100) und lass den RenderMode auf GL_RENDER, dann kannst du dir angucken, ob da überhaupt das richtige gerendert wird.

€: Ich seh grad das du InitNames und PushNames(0) im RenderCode hast... Dann kann es eig. nur noch an der Projektion liegen...

MfG Bergmann.


Bergmann, TAUSEND DANK, das war's!!! :D Ich kann Dir gar nicht sagen wie dankbar ich Dir dafür bin!!!

*Tief Verbeug*


user profile iconJens01 hat folgendes geschrieben Zum zitierten Posting springen:
Guck Dir mal meine CamerAH www.delphigl.com/for....php?f=13&t=9811 an.
Die ist Deiner genutzten Kamera ähnlich und hat auch schon Teile für diese Selektion. Eine weitere Möglichkeit der Selektion (und wohl auch die besser Option) ist dies Colorpicking.
Eigentlich ganz einfach.


Danke Jens, sieht sehr gut aus. Bin gerade dabei das in meinen Code einzubauen und werd Dir dann Rückmeldung geben ob's passt. :)