OpenGL "Picking" error specific to Mac

Discussion in 'Mac Programming' started by urchinsub, Dec 17, 2009.

  1. urchinsub macrumors newbie

    Joined:
    Nov 23, 2009
    #1
    Hi all, thanks for reading. I have a C++ program that uses OpenGL and GLUT. No matter how many times I click the screen in completely different places I will always get the same numbers in my buffer even though it is initialized to all zero's each time.
    Some background may help. This was originally written on an XP laptop and worked fine, porting to Vista with a poor graphics card resulted in clipping and picking errors. Porting to Mac I discovered the same clipping errors were present if I didn't have the graphics set for high performance but the picking error doesn't go away either way.
    Now here's some code:

    GLuint selectBuf[buffsize]; for(int p=0;p<buffsize;p++){selectBuf[p]=0;}
    GLint hits=0;
    GLint viewport[4]; // The Size Of The Viewport. [0] Is <x>, [1] Is <y>, [2] Is <length>, [3] Is <width>

    glSelectBuffer (buffsize, selectBuf);
    glRenderMode(GL_SELECT);
    glInitNames();
    glPushName(0);

    ///////////////////////////////////////////////////////Problem exists between here and....!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    glMatrixMode (GL_PROJECTION);
    glPushMatrix ();
    glLoadIdentity ();
    glGetIntegerv(GL_VIEWPORT, viewport);

    /* create 5x5 pixel picking region near cursor location */
    gluPickMatrix((GLdouble) xmouse, (GLdouble) (viewport[3] - ymouse), 3.0, 3.0, viewport);//(viewport[3] - ymouse) for Windows
    ///////////////////////////////////////////////////////////////////////////////////...here ????? !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    gluPerspective(videocam.xwinmin, videocam.ywinmin, videocam.camnear, videocam.camfar);
    glMatrixMode(GL_MODELVIEW);

    cout<<"Buffer contents before picking: ";
    for(int i=0;i<buffsize;i++){cout<<selectBuf<<", ";}

    draw();

    glPopMatrix ();
    glFlush();
    picking=false;

    hits = glRenderMode(GL_RENDER);

    cout<<"\nValue of 'hits' immediately after glRendermode() is "<<hits<<endl;
    proces*****(hits, selectBuf);
    cout<<"DONE processing picks!!!!!!!!!!!!!!!!!!!!!!!\n"<<endl;

    And sample data from the buffer looks like this:

    Hits = 2
    buffer holds: 1 4294766591 4294767615 0 0 4294739967 4294849023 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

    The program isn;t graphics intensive so I figure it is a porting issue. I played with argument values to see if I had the coordinate system wrong but that didn't seem to work.

    Thanks for your help :)
     
  2. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #2
    Can't tell anything from these, hopefully out of order, code fragments.
     
  3. urchinsub thread starter macrumors newbie

    Joined:
    Nov 23, 2009
    #3
    Thank you

    Thank you for your response.
    If the code fragments were out of order, wouldn't it display wrong in XP as well?
    Does anyone know of any GLUT or OGL versioning issues that might be relevant?
     
  4. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #4
    To be honest I've very little experience writing picking code but after looking at some of my experiments from long ago, which do work, try the following -

    Code:
        GLuint selectBuf[buffsize]; for(int p=0;p<buffsize;p++){selectBuf[p]=0;}
        GLint hits=0;
        GLint viewport[4]; // The Size Of The Viewport. [0] Is <x>, [1] Is <y>, [2] Is <length>, [3] Is <width>
        
        glSelectBuffer (buffsize, selectBuf); 
        glRenderMode(GL_SELECT); 
        glInitNames();
        
        ///////////////////////////////////////////////////////Problem exists between here and....!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        glMatrixMode (GL_PROJECTION);
        glPushMatrix ();
        glLoadIdentity ();
        glGetIntegerv(GL_VIEWPORT, viewport);
        
        /* create 5x5 pixel picking region near cursor location */
        gluPickMatrix((GLdouble) xmouse, (GLdouble) (viewport[3] - ymouse), 3.0, 3.0, viewport);//(viewport[3] - ymouse) for Windows
        ///////////////////////////////////////////////////////////////////////////////////...here ????? !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        gluPerspective(videocam.xwinmin, videocam.ywinmin, videocam.camnear, videocam.camfar);
        glMatrixMode(GL_MODELVIEW);
        
        cout<<"Buffer contents before picking: ";
        for(int i=0;i<buffsize;i++){cout<<selectBuf[i]<<", ";}
    
    // moved from above
    glPushName(0);
        
        draw();
    
    // added to balance above
    glPopName();
        
    // match pushed above
    glMatrixMode(GL_PROJECTION);
    
        glPopMatrix ();
    
    glMatrixMode(GL_MODELVIEW);
    
        glFlush();
        picking=false;
        
        hits = glRenderMode(GL_RENDER);
        
        cout<<"\nValue of 'hits' immediately after glRendermode() is "<<hits<<endl;
        proces*****(hits, selectBuf);
        cout<<"DONE processing picks!!!!!!!!!!!!!!!!!!!!!!!\n"<<endl;
    
     
  5. urchinsub thread starter macrumors newbie

    Joined:
    Nov 23, 2009
    #5
    Thank you

    Thanks. I'll let you know how it goes.
     
  6. urchinsub thread starter macrumors newbie

    Joined:
    Nov 23, 2009
    #6
    Thank you and Merry Xmas

    Dear sir,
    I thank you for taking the time to help me. I have finally had a chance to make the changes you suggested but regretfully the same problem persists. I will not give up on it and hopefully can shed some light on the problem in the future. Merry Xmas.
     
  7. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #7
    Is it possible for you to post the problematic project. If not the whole thing perhaps a reduced version with the same symptoms?
     
  8. urchinsub thread starter macrumors newbie

    Joined:
    Nov 23, 2009
    #8
    Can do

    I have started pearing down the project so I can send it to you. It's a fraction of it's original size but at the moment it is still 2.1 MB and 84 items including the stuff the compiler generates. How do I deliver it to you?
    Thanks :):)
     
  9. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #9
    Remove the "build" folder (next to the Xcode project) that Xcode constructed before you archive the project. It'll be much smaller that way.

    EDIT:

    As to getting it to me I'd suggest attaching it here in your next post.
     
  10. urchinsub thread starter macrumors newbie

    Joined:
    Nov 23, 2009
    #10
    Here's the picking code

    Alright, here's the simplified program without the build file. Thanks for looking at it. I'm sure to be embarrassed soon by learning it was something simple.
    Assuming I didn't remove too much code, you can click one of the yellow chess pieces and then an adjacent square and it will teleport to that square.


    ....don't use attached file. I can edit the post but I can't seem to remove the attachment. I'll post a new one tomorrow after I check for more editing errors :(
     
  11. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #11
    Click "User CP" near the top of the page. In the resulting page click "Attachments" at the bottom of the left most column.

    Should be obvious from there ...
     
  12. urchinsub thread starter macrumors newbie

    Joined:
    Nov 23, 2009
    #12
    New attachment ready

    Ok. Thanks lloyddean. Clearly I don't use forums much.
    Here is the revised attachment. If you click the "board" several times it will eventually move the "King" to a corner square for no apparent reason. After that I don't seem to get any response.
    buttons(...) in inputfuncs.h and processSelection(...) in selectproc.h are the first 2 places you may want to check.
    Actual code for drawing to screen can be found in:
    draw.h / face.h / squares.cpp / and king.cpp

    If you have questions or want me to edit more out to help narrow things down just let me know. Thank you for your time.
     
  13. allegrocm macrumors member

    Joined:
    Mar 13, 2005
    Location:
    Ames, IA
    #13
    I couldn't find your problem, but since you're using a simple overhead view, it might be easier to implement selection just by mapping the pointer position to a square onscreen. As for your code, make sure you pay attention to indentation, as it can make your code much easier to read. With OpenGL, for example, it's good to indent after calls such as glPushMatrix(), glBegin(), etc, to show the hierarchy of the stuff that's going on. Another thing I noticed is you're using some complex code to draw your faces on your board. Since you're trying to be object-oriented with this (a good thing!) try putting more of the draw overhead into the Face class. So rather than

    glTranslatef(toThePositionOfTheFace)
    glLoadName(IDOftheFace)
    face.draw(color)

    You might consider having each face know its position, ID, and color, and just calling face.draw();

    If you thin of object-oriented code as a try, I try to push the messy, icky code as far to the leaves as possible, and the code that actually controls things and makes important decisions should be on the trunk and branches. I hope this helps. Sorry I couldn't figure out the error. I've never used glPicking before, but I thought I'd give it a shot anyway.

    Oh, one other thing, display lists aren't really necessary for the kind of drawing you're doing. It doesn't make a huge difference, but using display lists for fairly small things actually slows things down slightly. Moreso, it just makes your code one step more complex.

    From code your and comments, I can tell you're relatively new at this, and I'm excited to see a new coder trying OpenGL. Keep chugging along and don't let little issues like this slow you down. I suppose my best advice at this point is KEEP IT SIMPLE. Focus on keeping your code clear and easy to read, and later when you come back to it, it'll make a lot more sense. Good luck!

    Ken
     
  14. urchinsub thread starter macrumors newbie

    Joined:
    Nov 23, 2009
    #14
    Thank you Ken.

    Thanks Ken,
    I'm sorry to dissappoint you but I'm not new to OpenGL. I have been working on the full version of this program for 3 years. It looks like a mess with excessively complicated commands because you are only seeing the minimal part of the code necessary to see the problem and try to diagnose it, the rest of the code has been edited along with the removal of most of the files.
    The picking part of the code worked on a laptop running XP 2 years ago. That computer died and I bought a new one that ran Vista, Vista and OpenGL are not good friends and I didn't realize I needed a better graphics card before buying it and running away to Nanjing, China for a year. This laptop could not display the graphics correctly or do picking so I concentrated on the AI for most of a year (after giving up on converting to DirectX).
    I bought my MacBook Pro in October to resume the graphical work, the display lists will eventually be completely replaced with properly modeled graphics. The graphics display well on my MacBook Pro as long as it isn't in power save mode (the alternate GPU) but picking still isn't working.
    At this point I don't know if it is a porting error, a compiler setting issue or did I alter the code adversely some how since I first had problems with it on Vista.
    I welcome your feedback. Thanks for having a look.;)
     
  15. urchinsub thread starter macrumors newbie

    Joined:
    Nov 23, 2009
    #15
    Update

    Alright, I found another problem that made it hard for people to help me, so much for editing the code before submitting it. I have fixed the problem and replaced the 2 main functions for detecting and sorting hits with the earliest version I can still find (it ran successfully on XP). This change includes messages to the console to show you what is in the selection Buffer as well as what is in the 2 dynamically allocated arrays I use to sort the buffer's contents. I have also added 2 pieces of a 2nd color and fixed the error thaty would have prevented them from getting a turn. I'm sorry to see 8 people have apparently downloaded the last file, here is the updated one for those I haven't scared away yet...
     
  16. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #16
    Please no offence implied as any code reformatting was done to aide in MY understanding the code.

    Uncommented 'glLoadName', 'glPushName' and added a few additonal points for imformation gathering:

    Code:
    void Face::drawface(float color[4])
    {
        int x = 2000;
        int y = x;
    
        if ( swapx == true ) { x *= (-1); }
        if ( swapy == true ) { y *= (-1); }
    
        for ( int j = -3+swapy; j < 3+swapy; j++ )
        {
            for ( int i = -3+swapx; i < 3+swapx; i++ )
            {
                glPushMatrix();
    
                    glMaterialfv(GL_FRONT, GL_EMISSION, color);
                    glTranslatef(i*(x), j*(y), 0.0f);///////proper 'z' value assigned in tiles.display(...); see squares.cpp
        
                    // NOTE: Uncommented and added condtional output of namestack value
                    glLoadName(tiles[(3+i-swapx)*6+(3+j-swapy)].getID());
                    if ( picking ) std::cout << "glLoadName - " << tiles[(3+i-swapx)*6+(3+j-swapy)].getID() << std::endl;
        
                    // NOTE: Uncommented and added condtional output of namestack value
                    glPushName(tiles[(3+i-swapx)*6+(3+j-swapy)].getID());
                    if ( picking ) std::cout << "glPushName - " << tiles[(3+i-swapx)*6+(3+j-swapy)].getID() << std::endl;
        
                        tiles[(3+i)*6+(3+j)].display((i+j+dark)%2);
        
                    glPopName();
    
                glPopMatrix();
            }
        }
    }
    
    Code:
    void buttons(GLint button, GLint action, GLint xmouse, GLint ymouse)
    {   
        if ( (button==GLUT_LEFT_BUTTON)&&(action==GLUT_DOWN)&&leftbutton==false )
        {
            videocam.setXmouse(xmouse);
            videocam.setYmouse(ymouse);
            
            leftbutton=true;
    
            GLuint selectBuf[buffsize];
            glSelectBuffer (buffsize, selectBuf);   
    
            glRenderMode(GL_SELECT); 
            
            glMatrixMode (GL_PROJECTION);
            glPushMatrix ();
            glLoadIdentity ();
    
            GLint viewport[4];
            glGetIntegerv(GL_VIEWPORT, viewport);
            
            /* create 3x3 pixel picking region near cursor location */
            gluPickMatrix((GLdouble) xmouse, (GLdouble)(viewport[3] - ymouse), 3.0, 3.0, viewport);
            
            gluPerspective(videocam.xwinmin, videocam.ywinmin, videocam.camnear, videocam.camfar);
            glMatrixMode(GL_MODELVIEW);
    
            glInitNames();
    
            // NOTE:
            // make sure something is on the namestack or 'glLoadName' call in 'Face::drawface'
            // will generate an namestack underflow error
    
            glPushName(0);
                    
            picking=true;
            draw();
            
            glMatrixMode (GL_PROJECTION);
            glPopMatrix ();
            picking=false;
    
            // NOTE:  'hits' is being return as -1
            
            GLint hits;
            hits = glRenderMode(GL_RENDER);
            if ( hits < 0 )
            {
                // NOTE:
                // If the overflow bit was set when glRenderMode was called, a negative hit record count is returned.
                // You'll need to increase the size of 'buffsize'
                // For me this went away between 256 and 512
                cout << "\nValue of 'hits' was negative!!!" << endl;
            }
            else if ( 0 == hits )
            {
                cout << "\nThere were no hits!!!" << endl;
            }
            else if ( hits > 0 )
            {
                cout << "\nValue of 'hits'  immediately after glRendermode() is " << hits << endl;
    
                    proces*****(hits, selectBuf);
    
                cout << "DONE processing picks!!!!!!!!!!!!!!!!!!!!!!!\n"<<endl;
            }
        }
        
        if ( action == GLUT_UP && leftbutton == true )
        {
            leftbutton = false;
        }
    }
    
    In 'proces*****' remember to release the memory allocated to both hitsets[0] and hitsets[1]

    Code:
        delete [] hitsets[1];
        delete [] hitsets[0];
    
    EDIT: Very, very odd - In posting proces***** keep getting changed to what is seen.
    So, so sad. It appears to be an attempt to keep for posting 'offensive' words.
     
  17. urchinsub thread starter macrumors newbie

    Joined:
    Nov 23, 2009
    #17
    Thanks again

    Thanks again lloyddean,
    especially for mention of Pushing the first name (I recently changed that to Load by mistake) and for finding the lack of deallocation (an oversight made in Winter 2007 according to the file's header comments).
    About the changes to Face.h. Only one of the 2 name stack manipulators should be used, not both. Unfortunately one causes an overflow even though it should only register 2 hits at most. The other one always says I have one hit even if it should register two (maybe because load replaces the previous value before it can be processed?). The fact that it moves the piece to the wrong location might be due to recent playing with the glLoad and Push Name calls, I'm not sure. My feeling is that it should use glPushName() but why does it then select all objects on screen rather than just those clicked? Is it a viewport error? Is it a coordinate error from porting to Mac?
    Thanks again and thanks to all others taking an interest :)
     
  18. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #18
    Did you say you had a version (you really believe) that worked correctly under some version of Windows?

    Is that what you posted?

    If it isn't how about posting that version instead?

    Are the values being passed to "process?Hits" in your ranges of expectation?

    Again no offense but - you would not believe the number of Windows oriented programmers I've worked with over the years that think they've written correct code simply because it worked under Windows. Running code on multiple platforms quickly exposes "hidden" problems.
     
  19. urchinsub thread starter macrumors newbie

    Joined:
    Nov 23, 2009
    #19
    I know

    Yeah, I know code written for one platform might work on just that one platform despite errors. The newest file uploaded to the forum has the earliest versions of the process?hits() and buttons I could find. Yes I believe these functions did work at that time but the rest of the code in the file I've uploaded is edited. I don;t want to give away too much of my work so freely, it took a long time to write ;)
    I am taking the full version of the earliest code I could find and am converting to run on Mac to see if I can solve things that way.
    Thanks for your help.
     

Share This Page