Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 4 of 4

Thread: Picking an Object not working

  1. #1
    Junior Member Newbie
    Join Date
    Feb 2014
    Posts
    6

    Picking an Object not working

    Hello everyone,

    I'm in a bit of a bind for a while now concerning object picking. Here's the situation:
    Our company has recently been implementing OpenGL into our Delphi 2010 programs and our current assignment is to display voyages of several trains in a 3D-esque environment.
    Everything works and is data-aware (connected to a database); our client/customer now wants the ability to open the voyage-information when you click on a train.

    I went looking for a tutorial and came across this: http://www.sulaco.co.za/opengl_project_GL_picking.htm
    Studied the code, dissected the code, applied the code to our own project but it doesn't function.
    One thing I've noticed is this:
    The 'tutorial' uses a Viewport whereas I use a Context; the latter is because we have to use several Delphi Tools like a date-time selection bar on our Form.

    Here is an image of the ContextView:


    And here is the code I'm using for the Object Picking:
    Code :
    function TGL_Form.RetrieveObjectID(x, y: integer): integer;
    var
       objectsFound: integer;
       viewportCoords: array [0..3] of integer;
       selectBuffer: array[0..31] of cardinal;
       lowestDepth: cardinal;
       selectedObject: cardinal;
       i: integer;
    begin
      objectsFound := 0;
      ZeroMemory(@viewportCoords, sizeof(viewportCoords));
      ZeroMemory(@selectBuffer, sizeof(selectBuffer));
     
      glSelectBuffer(32, @selectBuffer);
     
      viewportCoords[0] := 0;
      viewportCoords[1] := 0;
      viewportCoords[2] := GL_Form.ClientWidth;
      viewportCoords[3] := GL_Form.ClientHeight;
     
      glMatrixMode(GL_PROJECTION);
    	glPushMatrix();
     
      glRenderMode(GL_SELECT);
      glLoadIdentity();
     
      gluPickMatrix(x, viewportCoords[3]-y-Integer(not g_Fullscreen)*(GetSystemMetrics(SM_CYCAPTION)+ GetSystemMetrics(SM_CYSIZEFRAME) shl 1), 15, 15, @viewportCoords);
     
      gluPerspective(45.0, viewportCoords[2]/viewportCoords[3], 0.5, 150.0);
      glMatrixMode(GL_MODELVIEW);
     
      objectsFound := glRenderMode(GL_RENDER);
     
      glMatrixMode(GL_PROJECTION);
    	glPopMatrix();
     
    	glMatrixMode(GL_MODELVIEW);
     
      if (objectsFound > 0) then
    	begin
        lowestDepth := selectBuffer[1];
        selectedObject := selectBuffer[3];
     
        for i := 1 to objectsFound - 1 do
    		begin
          if (selectBuffer[(i * 4) + 1] < lowestDepth) then
    			begin
    				lowestDepth := selectBuffer[(i * 4) + 1];
    				selectedObject := selectBuffer[(i * 4) + 3];
          end;
        end;
     
        result := selectedObject;
                    exit;
      end;
     
      result := 0;
    end;
    Pushing names into the list:
    Code :
    //Draw the trains
      glInitNames();
      glPushName(0);
     
      for T1 := 0 to Length(trackNames)-1 do
        for T2 := 0 to Length(trackTrack)-1 do
          if(trackNames[T1] = trackTrack[T2]) then
          begin
            glLoadName(T2);
     
            Y := -((T1 * trackWidth) + (T1 * trackSpace))+0.5;
            glCube(trackFrom[T2]*(trackLength/58),
                   Y,
                   0,
                   ((trackTo[T2]-trackFrom[T2])*(trackLength/58)),  //Length
                   trackWidth,  //Height
                   0.09,         //Depth
                   trackColorR[T2],
                   trackColorG[T2],
                   trackColorB[T2]
                   );
     
            glPrint(trackVoyage[T2],
                    trackFrom[T2]*(trackLength/58)+1,
                    Y+2,
                    0.1,
                    textColorR[T2],
                    textColorG[T2],
                    textColorB[T2],
                    false
                    );
            glEnd();
     
          end;

    Using breakpoints I've adjusted the code accordingly and tested to see where it goes awry:
    Code :
    glRenderMode(GL_SELECT);
      glLoadIdentity();
     
      gluPickMatrix(x, viewportCoords[3]-y-Integer(not g_Fullscreen)*(GetSystemMetrics(SM_CYCAPTION)+ GetSystemMetrics(SM_CYSIZEFRAME) shl 1), 15, 15, @viewportCoords);
     
      gluPerspective(45.0, viewportCoords[2]/viewportCoords[3], 0.5, 150.0);
      glMatrixMode(GL_MODELVIEW);
     
      objectsFound := glRenderMode(GL_RENDER);
    This part ALWAYS returns 0
    The 'x' and 'y' have the correct mouse positions stored,
    data in 'viewportCoords' is correct; [0, 0, 1024, 768],
    'g_FullScreen' is always 'false',

    I have no idea what 'GetSystemMetrics(SM_CYCAPTION)', 'GetSystemMetrics(SM_CYSIZEFRAME)' or '(GetSystemMetrics(SM_CYCAPTION)+ GetSystemMetrics(SM_CYSIZEFRAME) shl 1)' have for values because they're untracable for some reason; neither a breakpoint nor storing the data (Integers) shows any result, though I have a few more methods that might work, will update on this..
    ##UPDATE##
    'GetSystemMetrics(SM_CYCAPTION)' = 23
    'GetSystemMetrics(SM_CYSIZEFRAME)' = 8
    '(GetSystemMetrics(SM_CYCAPTION)+ GetSystemMetrics(SM_CYSIZEFRAME) shl 1)' = 39
    'viewportCoords[3]-y-Integer(not g_Fullscreen)*(GetSystemMetrics(SM_CYCAPTION)+ GetSystemMetrics(SM_CYSIZEFRAME) shl 1)' = returns a value based on the mouseposition (changes)


    I hope someone can help me with fixing this, because I'm at a loss at the moment.

    Thanks in advance and kind regards.
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	GleisGleisGleis_zpsf385d686.jpg 
Views:	39 
Size:	22.9 KB 
ID:	1259  
    Last edited by Zubaja; 04-01-2014 at 06:43 AM.

  2. #2
    Junior Member Newbie
    Join Date
    Sep 2008
    Posts
    21
    Hi,
    Nothing unusual is apparent yet except:
    It seems immeadiately obvious that there is the lack of evidence that you are actually rendering anything to the "offscreen selection buffer".
    i.e. the // Draw the trains// code you show needs to be executed for the second separate time offscreen (in between the lines glMatrixMode(GL_MODELVIEW);
    and objectsFound := glRenderMode(GL_RENDER);.
    I was expecting to see in between these lines something like this:
    glLoadIdentity();
    ApplyCameraTransformations(): //if you have and use the concept
    DrawTrainsHitTestMode (); //or something like it to render with the names/ids

    try it and then see what happens.

    Then an easier way of initially testing this is visually is to comment out the Selection mode line:
    glRenderMode(GL_SELECT);
    Then the zoomed up 15X15 viewport of the glPickmatrix will be magnifyed up and fill up on top of your current viewport (bit like the effect of telescopic
    sights on a rifle, and that zoomed up view will move as you move the "camera with the mouse" (Note: this is possible because of the way i have it set up, thus I am aware it may just not be possible with your set up). It is very conveniently visual. You can also widen the 15X15 view with much higher values if all you see is flashes of color (produced by being zoomed up very close).
    Last edited by Steven Katic; 04-01-2014 at 02:19 PM.

  3. #3
    Intern Contributor
    Join Date
    Mar 2014
    Location
    San Jose, CA
    Posts
    58
    Since the layout of your rendered geometry looks fairly straightforward, could you just figure out in your own code what was drawn at the position the user clicked? That might be simpler in this case, and most likely less error prone.

    Selection mode is also a deprecated feature.

  4. #4
    Junior Member Newbie
    Join Date
    Feb 2014
    Posts
    6
    @Steven Katic
    I've placed the '//draw trains' code in-between the lines you suggested, but nothing comes out of it; I'm not even 100% sure I've done it completely right.
    Code :
    //glRenderMode(GL_SELECT);
     
      gluPickMatrix(x, viewportCoords[3]-y-Integer(not g_Fullscreen)*(GetSystemMetrics(SM_CYCAPTION)+ GetSystemMetrics(SM_CYSIZEFRAME) shl 1), 55, 55, @viewportCoords);
     
      gluPerspective(45.0, viewportCoords[2]/viewportCoords[3], 0.5, 150.0);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      //Draw trains here too
      for T1 := 0 to Length(trackNames)-1 do
        for T2 := 0 to Length(trackTrack)-1 do
          if(trackNames[T1] = trackTrack[T2]) then
          begin
     
            _Y := -((T1 * trackWidth) + (T1 * trackSpace))+0.5;
            glCube(trackFrom[T2]*(trackLength/58),
                   _Y,
                   0,
                   ((trackTo[T2]-trackFrom[T2])*(trackLength/58)),  //Length
                   trackWidth,  //Height
                   0.09,         //Depth
                   trackColorR[T2],
                   trackColorG[T2],
                   trackColorB[T2]
                   );
     
            glPrint(trackVoyage[T2],
                    trackFrom[T2]*(trackLength/58)+1,
                    _Y+2,
                    0.1,
                    textColorR[T2],
                    textColorG[T2],
                    textColorB[T2],
                    false
                    );
          end;
     
      objectsFound := glRenderMode(GL_RENDER);

    As you can also see, I turned off 'GL_SELECT' but that doesn't amount to any change either.
    I've also looked at 'ApplyCameraTransformations();' but Delphi 2010 doesn't have that function.

    @reto.koradi
    If you happen to have a function that (magically) translates pixels into units (2D-3D), that'd be grand and a lot of help (No sarcasm intended). Otherwise I'm still stuck.

    One thing I forgot to mention was that I also looked into RayCasting, a thing I picked up at college when I was studying Game Development, but I had to give up on that because the tutorials I found were not Delphi 2010 compatible.
    And Delphi has some 'glu' functions too, for some reason.

    In any case:
    I'm still stuck (sadly) with narry a solution in sight. If anyone has a different tutorial for me to follow or possibly a completely different solution, that'd be grand.

    ##UPDATE##
    I've looked up a different method, namely this one.
    This time, when I try to get a Vector3 (The result from the function), I get 3x -NAN, which is more (or less, depends on how you look at it since NAN = Not A Number) than the other function I had.

    ##UPDATE_02##
    After editing the code from here, I am finally getting sound digits thrown back at me. They all range from -1 to 1, so I'm guessing that good? Now all I need is to make sure I receive a hit. Any takers on how to do this?
    Last edited by Zubaja; 04-02-2014 at 08:32 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •