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

Aktuelle Zeit: Fr Jul 18, 2025 07:28

Foren-Übersicht » English » English Programming Forum
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 9 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Question on picking...
BeitragVerfasst: So Jan 28, 2007 01:13 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
Hello,

My question is as simple as "Why can't I seem to pick the red rotating squares in my program?" which will become more apparent as I provide more detail. I am setting myself up to do some good things with OpenGL but I need my users to be able to interface with the scene - so I looked into some tutorials on picking and have made good progress, only one thing confuses me. I have several spinning squares stacked on top of each other - I have two columns of these - I can successfully pick any square but the bottom square on each column - try as I might, I can't pick the bottom square (in both cases, the red square) and I haven't got a clue why.

Here's what my OpenGL program window looks like, my annotations are trying to illustrate my problem:

Bild

My code is relatively simple... the picking stuff is more or less lifted from some Internet tutorials - with some slight modications made by me - although I'm not sure how I could have broken it though. Any help would be greatly appreciated... I can provide the .pas, .dfm and .dpr in a .zip if anyone has the heart to see see what's really happening (3K only).

Code:
  1. unit Main;
  2.  
  3. interface
  4.  
  5. uses
  6.   OpenGL, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   StdCtrls, ExtCtrls, ComCtrls;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     Timer1: TTimer;
  12.     procedure FormCreate (Sender : TObject);
  13.     procedure Timer1Timer(Sender : TObject);
  14.     procedure FormMouseDown (Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
  15.   private
  16.     procedure Draw;
  17.     procedure DSquare (Select : Integer; X, Y, Z, Angle : GLFloat);
  18.   public
  19.   end;
  20.  
  21. var
  22.   Form1 : TForm1;
  23.   Flipper1 : GLFloat;
  24.   Selecting : Boolean;
  25.   LastName : Integer;
  26.  
  27.  
  28. implementation
  29.  
  30. procedure glBindTexture ( Target : GLEnum;
  31.                           Texture : GLUInt
  32.                         ); stdcall; external OpenGL32;
  33.  
  34. {$R *.DFM}
  35.  
  36.  
  37. procedure TForm1.DSquare ( Select : Integer;
  38.                            X, Y, Z, Angle : GLFloat
  39.                          );
  40. begin
  41.   glLoadIdentity;
  42.   glTranslatef (X,Y,Z);
  43.   glRotatef (-80,1,0,0);
  44.   glRotatef (Angle,0,0,1);
  45.   glRotatef (Sin (GetTickCount / 900) * 5,0,1,0);
  46.  
  47.   if (Selecting) then
  48.   begin
  49.     Inc (LastName);
  50.     glLoadName (LastName);
  51.   end;
  52.  
  53.   case Select of
  54.     1 : glColor3f (1,0,0);
  55.     2 : glColor3f (0,1,0);
  56.     3 : glColor3f (0,0,1);
  57.     4 : glColor3f (1,1,0);
  58.     5 : glColor3f (0,1,1);
  59.     6 : glColor3f (1,0,1);
  60.   end;
  61.  
  62.   glBegin (GL_QUADS);
  63.     glTexCoord2f (0,0);
  64.     glVertex3f (-1,-1,0);
  65.  
  66.     glTexCoord2f (1,0);
  67.     glVertex3f (1,-1,0);
  68.  
  69.     glTexCoord2f (1,1);
  70.     glVertex3f (1,1,0);
  71.  
  72.     glTexCoord2f (0,1);
  73.     glVertex3f (-1,1,0);
  74.   glEnd;
  75. end;
  76.  
  77.  
  78. procedure setupPixelFormat ( DC :HDC
  79.                            );
  80. const
  81.    pfd : TPIXELFORMATDESCRIPTOR = (nSize : SizeOf (TPIXELFORMATDESCRIPTOR);
  82.          nVersion : 1;
  83.          dwFlags : PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER;
  84.          iPixelType : PFD_TYPE_RGBA;
  85.          cColorBits : 24;
  86.          cRedBits : 0; cRedShift : 0; cGreenBits : 0;  cGreenShift : 0; cBlueBits : 0; cBlueShift : 0;
  87.          cAlphaBits : 0; cAlphaShift : 0; cAccumBits : 0; cAccumRedBits : 0; cAccumGreenBits : 0;
  88.          cAccumBlueBits : 0; cAccumAlphaBits : 0; cDepthBits : 16; cStencilBits : 0; cAuxBuffers : 0;
  89.          iLayerType : PFD_MAIN_PLANE; bReserved : 0; dwLayerMask : 0; dwVisibleMask : 0; dwDamageMask : 0);
  90. var
  91.   PixelFormat : Integer;
  92. begin
  93.   PixelFormat := ChoosePixelFormat (DC,@pfd);
  94.   if (PixelFormat = 0) then
  95.   begin
  96.     Exit;
  97.   end;
  98.  
  99.   if (SetPixelFormat (DC,PixelFormat,@pfd) <> True) then
  100.   begin
  101.     Exit;
  102.   end;
  103. end;
  104.  
  105.  
  106. procedure TForm1.FormCreate ( Sender : TObject
  107.                             );
  108. var
  109.   DC : HDC;
  110.   RC : HGLRC;
  111. begin
  112.   DC := GetDC (Handle);
  113.   SetupPixelFormat (DC);
  114.   RC := wglCreateContext (DC);
  115.   wglMakeCurrent (DC,RC);
  116.  
  117.   glMatrixMode (GL_PROJECTION);
  118.   glFrustum (-0.1,0.1,-0.1,0.1,0.3,25.0);
  119.   glMatrixMode (GL_MODELVIEW);
  120.   glEnable (GL_DEPTH_TEST);
  121.   glDepthFunc (GL_LESS);
  122.   glHint (GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
  123.   glEnable (GL_TEXTURE_2D);
  124.  
  125.   Flipper1 := 0;
  126.   Selecting := False;
  127. end;
  128.  
  129.  
  130. procedure TForm1.Draw;
  131. begin
  132.   { Reset this each time around; in case Draw is called while selecting. }
  133.   LastName := 0;
  134.  
  135.   glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  136.   glClearColor (0,0,0.5,1);
  137.  
  138.   DSquare (1,1.5,-2,-10,-Flipper1);
  139.   DSquare (2,1.5,-1.5,-10,-Flipper1 + 10);
  140.   DSquare (3,1.5,-1,-10,-Flipper1 + 20);
  141.   DSquare (4,1.5,-0.5,-10,-Flipper1 + 30);
  142.  
  143.   DSquare (1,-1.5,-2,-10,-Flipper1);
  144.   DSquare (2,-1.5,-1.5,-10,-Flipper1 + 10);
  145.   DSquare (3,-1.5,-1,-10,-Flipper1 + 20);
  146.   DSquare (4,-1.5,-0.5,-10,-Flipper1 + 30);
  147.   DSquare (5,-1.5,0,-10,-Flipper1 + 40);
  148.   DSquare (6,-1.5,0.5,-10,-Flipper1 + 50);
  149.  
  150.   if (Flipper1 = 360) then
  151.   begin
  152.     Flipper1 := 0;
  153.   end;
  154.  
  155.   SwapBuffers (wglGetCurrentDC);
  156. end;
  157.  
  158.  
  159. procedure TForm1.Timer1Timer ( Sender : TObject
  160.                              );
  161. begin
  162.   Flipper1 := Flipper1 + 0.5;
  163.   Draw;
  164. end;
  165.  
  166.  
  167. procedure TForm1.FormMouseDown ( Sender : TObject;
  168.                                  Button : TMouseButton;
  169.                                  Shift : TShiftState;
  170.                                  X, Y : Integer
  171.                                );
  172. var
  173.   selectBuff : array [0..23] of GLUint;
  174.   viewport : array [0..3] of GLUint;
  175. begin
  176.   { Stop the timer doing any screen updates... }
  177.   Timer1.Enabled := False;
  178.  
  179.   { Select buffer parameters; viewport = 0, 0, width, height... }
  180.   glGetIntegerv (GL_VIEWPORT,@viewport);
  181.   glSelectBuffer (23,@selectBuff);
  182.  
  183.   { Enter selection mode... }
  184.   glMatrixMode (GL_PROJECTION);
  185.   glPushMatrix;
  186.     glRenderMode (GL_SELECT);
  187.     Selecting := True;
  188.  
  189.     { Clear Select Buffer... }
  190.     glInitNames;
  191.     glPushName (0);
  192.     glLoadIdentity;
  193.  
  194.     { Set a viewing volume; (x, y, width, height, viewport); pick matrix... }
  195.     gluPickMatrix (X,viewport[3]-Y-27,1,1,@viewport);
  196.     { Do the perspective calculations... last value = maximum clipping depth... }
  197.     gluPerspective (45.0,viewport[2] / viewport[3],0.0,100.0);
  198.     glMatrixMode (GL_MODELVIEW);
  199.     Draw;
  200.  
  201.     if (glRenderMode (GL_RENDER) > 0) then
  202.     begin
  203.       ShowMessage ('Object picked: ' + IntToStr (SelectBuff[3]));
  204.     end;
  205.  
  206.     glMatrixMode (GL_PROJECTION);
  207.   glPopMatrix;
  208.   glMatrixMode (GL_MODELVIEW);
  209.  
  210.   Selecting := False;
  211.   Timer1.Enabled := True;
  212. end;
  213.  
  214.  
  215. end.
My guess is that this is something someone will be able to point to immediately and it's a lesson I'll never forget. :lol:

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Jan 28, 2007 01:49 
Offline
Ernährungsberater
Benutzeravatar

Registriert: Sa Jan 01, 2005 17:11
Beiträge: 2068
Programmiersprache: C++
At that point, the only "fault" I could find, is that you're not using dglOpenGL.pas ;)
But that is just for comfort and won't resolve that problem.

The only differnce I can see between your program and our selection sample in the wiki is the way you're taking the picked object:
Code:
  1. ShowMessage ('Object picked: ' + IntToStr (SelectBuff[3]));


Code:
  1.   treffer := glRenderMode(GL_RENDER);         //Anzahl der Treffer auslesen
  2.  
  3.   Getroffen := High(GLUInt);                  //Höchsten möglichen Wert annehmen
  4.   Z_Wert := High(GLUInt);                     //Höchsten Z - Wert
  5.   for i := 0 to Treffer-1 do
  6.     if Puffer[(i*4)+1] < Z_Wert then
  7.     begin
  8.       getroffen       := Puffer[(i*4)+3];
  9.       Z_Wert := Puffer[(i*4)+1];
  10.     end;
  11.  
  12.   if getroffen=High(GLUInt)
  13.     then Result := -1
  14.     else Result := getroffen;

but that is not a reason why you're are not able to hit glName(1);

_________________
Steppity,steppity,step,step,step! :twisted:
❆ ❄ ❄ ❄ ❅ ❄ ❆ ❄ ❅ ❄ ❅ ❄ ❅ ❄ ❄
❄ ❄ ❄ ❅ ❄ ❄ ❄ ❅ ❄ ❄ ❆ ❄ ❄


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Been digging a little more...
BeitragVerfasst: So Jan 28, 2007 02:54 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
OK,

Maybe this will help highlight the problem... the issue is not that I can't pick glName(1) - it seems I can - but that it was the green square, as opposed to the red one at the bottom. At first I thought it was like the red squares hadn't been assigned a name at all, but then I started picking all over the place on the screen... and I got the following surprising results:

Bild

...and now I'm starting to think there is something fundamentally wrong with my coordinates somewhere - in fact, it seems pretty obvious that this is true. I'll keep on looking at this, but if anyone can spot it straight away or have a run of the program (which can be found here http://www.hmusiccentre.org.uk/HMCImages/Picking.zip if wanted) and alter the code to fix it it would be really helpful.

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Jan 28, 2007 12:02 
Offline
Ernährungsberater
Benutzeravatar

Registriert: Sa Jan 01, 2005 17:11
Beiträge: 2068
Programmiersprache: C++
Ok, I found the problem at line 197:

But first another fault I found:
Code:
  1. gluPickMatrix (X,viewport[3]-Y-27,1,1,@viewport);

You don't need to subtract 27 from Y, the titlebar has been subtracted before.

So, the real problem:
Code:
  1. gluPerspective (45.0,viewport[2] / viewport[3],0.0,100.0);

You only run this code if you're selecting, if you're just rendering you're using
Code:
  1. glFrustum (-0.1,0.1,-0.1,0.1,0.3,25.0);

instead. If you're replacing gluPerspective with glFrustum it works nearly correct. Now you can select the red square, but you will select it too if the green square is in front of it. To resolve this you have to use the code I postet on post ago.

_________________
Steppity,steppity,step,step,step! :twisted:
❆ ❄ ❄ ❄ ❅ ❄ ❆ ❄ ❅ ❄ ❅ ❄ ❅ ❄ ❄
❄ ❄ ❄ ❅ ❄ ❄ ❄ ❅ ❄ ❄ ❆ ❄ ❄


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Jan 28, 2007 13:03 
Offline
Fels i.d. Brandung
Benutzeravatar

Registriert: Sa Mai 04, 2002 19:48
Beiträge: 3830
Wohnort: Tespe (nahe Hamburg)
Don't want to interrupt, but did you thought about implementing some sort of color picking? After working with different methods, I think it is pretty easy to implement. If the user clicks, you are rendering the scene a second time offscreen. Every object is getting a unique color value and (of course) you have to disable everything that might influenece the color (texture, lighting, dithering etc. disable everything) Now you just need to read one pixel from the color buffer, trying to indentify it from some kind of color list. Because a modern graphic card should not having any troubles with one small offscreen rendering... especially because it's not needed every render pass, but only if the user clicks. If you having a true color envroiment you also have the Alpha channel additionally and should be able to handle lot's of objects, without any mathematic stuff.

_________________
"Light travels faster than sound. This is why some people appear bright, before you can hear them speak..."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Jan 28, 2007 16:14 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
You don't even need offscreen rendering. You can simply render the frame again with colors after SwapBuffers(), so they stay in the backbuffer.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Jan 28, 2007 17:49 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
OK - I've finally arrived at where I want to be and have two ways of identifying my picked objects now - the extremely simple way I started with (which works quite well, unless other objects get in the way of the one you want to pick) and the more complicated way which will cycle through multiple picked objects and ascertain which is closest to you - based on Depth - I got confused here for a while, as all my objects are on the same Z - but Depth must mean something else! The second method appears to work perfectly for my requirements, i.e. it will allow me to 'pick' the bottom square from the tower. Thanks for all of the hints and tips!

1) Simplest...
Code:
  1. procedure TForm1.FormMouseDown ( Sender : TObject;
  2.                                  Button : TMouseButton;
  3.                                  Shift : TShiftState;
  4.                                  X, Y : Integer
  5.                                );
  6. var
  7.   SelectBuffer : array [0..23] of GLUInt;
  8.   Viewport : array [0..3] of GLUInt;
  9. begin
  10.   { Stop the timer doing any screen updates... }
  11.   Timer1.Enabled := False;
  12.   Selecting := True;
  13.  
  14.   { Select buffer parameters; viewport = 0, 0, width, height... }
  15.   glGetIntegerv (GL_VIEWPORT,@Viewport);
  16.   glSelectBuffer (23,@SelectBuffer);
  17.  
  18.   { Enter selection mode... }
  19.   glMatrixMode (GL_PROJECTION);
  20.   glPushMatrix;
  21.     glRenderMode (GL_SELECT);
  22.  
  23.     { Clear Select Buffer... }
  24.     glInitNames;
  25.     glPushName (0);
  26.     glLoadIdentity;
  27.  
  28.     { Set a viewing volume; (x, y, width, height, viewport); pick matrix... }
  29.     gluPickMatrix (X,Viewport[3] - Y,1,1,@Viewport);
  30.     glFrustum (-0.1,0.1,-0.1,0.1,0.3,25);
  31.     glMatrixMode (GL_MODELVIEW);
  32.     Draw;
  33.  
  34.     if (glRenderMode (GL_RENDER) > 0) then
  35.     begin
  36.       ShowMessage ('glName: ' + IntToStr (SelectBuffer[3]));
  37.     end;
  38.  
  39.     glMatrixMode (GL_PROJECTION);
  40.   glPopMatrix;
  41.   glMatrixMode (GL_MODELVIEW);
  42.  
  43.   Selecting := False;
  44.   Timer1.Enabled := True;
  45. end;
2) Discerning between multiple hits...
Code:
  1. procedure TForm1.SecondFormMouseDown ( Sender : TObject;
  2.                                        Button : TMouseButton;
  3.                                        Shift : TShiftState;
  4.                                        X, Y : Integer
  5.                                      );
  6. var
  7.   ViewportCoords : array [0..3] of Integer;
  8.   SelectBuffer : array [0..31] of Cardinal;
  9.   SelectedObject, Loop, NumberOfHits : Integer;
  10.   { It is very important that LowestDepth is a Cardinal, not an Integer. }
  11.   LowestDepth : Cardinal;
  12. begin
  13.   { Stop the timer doing any screen updates... }
  14.   Timer1.Enabled := False;
  15.   Selecting := True;
  16.  
  17.   glSelectBuffer (32,@SelectBuffer);
  18.   glGetIntegerv (GL_VIEWPORT,@ViewportCoords);
  19.   glMatrixMode (GL_PROJECTION);
  20.  
  21.   glPushMatrix;
  22.     glRenderMode (GL_SELECT);
  23.     { Clear Select Buffer... }
  24.     glInitNames;
  25.     glPushName (0);
  26.     glLoadIdentity;
  27.     gluPickMatrix (X,ViewportCoords[3] - Y,1,1,@ViewportCoords);
  28.     glFrustum (-0.1,0.1,-0.1,0.1,0.3,25);
  29.     glMatrixMode (GL_MODELVIEW);
  30.     Draw;
  31.     NumberOfHits := glRenderMode (GL_RENDER);
  32.     glMatrixMode (GL_PROJECTION);
  33.   glPopMatrix;
  34.  
  35.   glMatrixMode (GL_MODELVIEW);
  36.  
  37.   if (NumberOfHits > 0) then
  38.   begin
  39.     LowestDepth := SelectBuffer[1];
  40.     SelectedObject := SelectBuffer[3];
  41.  
  42.     if (NumberOfHits > 1) then
  43.     begin
  44.       for Loop := 0 to NumberOfHits - 1 do
  45.       begin
  46.         if (SelectBuffer[(Loop * 4) + 1] < LowestDepth) then
  47.         begin
  48.           LowestDepth := SelectBuffer[(Loop * 4) + 1];
  49.           SelectedObject := SelectBuffer[(Loop * 4) + 3];
  50.         end;
  51.       end;
  52.     end;
  53.     ShowMessage ('glName: ' + IntToStr (SelectedObject));
  54.   end;
  55.  
  56.   Selecting := False;
  57.   Timer1.Enabled := True;
  58. end;
To answer the question posed by Phobeus, as best as I can anyway... I believe that I can't use colour picking for my requirements as I intend these spinning squares to have texures and represent Album covers - I limited the program that I posted on this forum to just be coloured squares so that I would not confuse the issue of anyone helping with textures etc.. If I can get everything working as expected, what I am looking for is a new way of HMusicCentre users being able to pick Albums by certain Artists - via some eye-candy selection screen where an Artist has a 'tower' of Albums and users can click on the one they want to play... i.e. just like below...

Bild

As for the comment by LarsMiddendorf, I'm sorry - but I didn't understand it - maybe I will later.

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Jan 28, 2007 21:18 
Offline
Fels i.d. Brandung
Benutzeravatar

Registriert: Sa Mai 04, 2002 19:48
Beiträge: 3830
Wohnort: Tespe (nahe Hamburg)
Have a look at:
http://gpwiki.org/index.php/OpenGL_Selection_Using_Unique_Color_IDs

_________________
"Light travels faster than sound. This is why some people appear bright, before you can hear them speak..."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Very interesting...
BeitragVerfasst: Mo Jan 29, 2007 00:20 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
I have had a good read of that and it was really interesting. There'd be some work for me to do to translate the bits of C++ to Delphi though so, unless there's some incredible performance boost or the way I have implemented it is going to get really difficult when I have hundreds of items on the screen, I think I shall stick with the way that I have working, via Picking, illustrated above.

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 9 Beiträge ] 
Foren-Übersicht » English » English Programming Forum


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 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.011s | 14 Queries | GZIP : On ]