arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

Pick.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------
00002 //C++ 
00003 //                   ________    ____   ___ 
00004 //                  |        \  /    | /  /
00005 //                  +---+     \/     |/  /
00006 //                  +--+|  |\    /|     < 
00007 //                  |  ||  | \  / |  |\  \ 
00008 //                  |      |  \/  |  | \  \ 
00009 //                   \_____|      |__|  \__\
00010 //                       Copyright  2003 
00011 //                      Joe Michael Kniss
00012 //               "All Your Base are Belong to Us"
00013 //-------------------------------------------------------------------------
00014 
00015 /// Pick.cpp
00016 
00017 #include <GL/glew.h>
00018 #include "Pick.h"
00019 #include <algorithm>
00020 #include <iostream>
00021 #include <limits>
00022 
00023 using namespace std;
00024 
00025 ////////////////////////////////////////////////////////////////
00026 /// begin a pick, you need to call your draw loop and then
00027 ///   endPick when you are done.  
00028 void Pick::startPickGL(double x, double y, double pickWin)
00029 {
00030    GLint viewport[4];
00031    glGetIntegerv(GL_VIEWPORT,viewport);
00032    GLfloat proj[16];
00033    glGetFloatv(GL_PROJECTION_MATRIX,proj);
00034 
00035    /// set up projection matrix for picking
00036    glMatrixMode(GL_PROJECTION);
00037    {
00038       glPushMatrix();
00039       glLoadIdentity();
00040       gluPickMatrix(x, y, pickWin, pickWin, viewport);
00041       glMultMatrixf(proj);
00042    }
00043    glMatrixMode(GL_MODELVIEW);
00044    
00045    /// set up pick buffer and render mode
00046    glSelectBuffer(_pbSize, _pickBuffer);
00047    glRenderMode(GL_SELECT);
00048 
00049    /// initiallize name buffer
00050    glInitNames();
00051 
00052    _picking = true;
00053 }
00054 
00055 ////////////////////////////////////////////////////////////////
00056 /// for sorting our pick info's
00057 struct PBSortZ1 {
00058    bool operator() (const PickInfo &pi1, const PickInfo &pi2)
00059    {
00060       return pi1.z1 < pi2.z1;
00061    }
00062 };
00063 
00064 ////////////////////////////////////////////////////////////////
00065 /// end a pick, fill the pick information vector
00066 PickInfoVec Pick::endPickGL()
00067 {
00068    /// catch the most obvious user mistake and report it
00069    ///   TODO: an assertion would force the user fix this too
00070    if(!_picking)
00071    {
00072       cerr << "Pick::endPickGL(), you must call startPickGL() before endPickGL()" << endl;
00073       return PickInfoVec();
00074    }
00075    _picking = false;
00076 
00077    /// reset projection matrix
00078    glMatrixMode(GL_PROJECTION);
00079    {  
00080       glPopMatrix();
00081    }
00082    glMatrixMode(GL_MODELVIEW);
00083 
00084    /// setting the render mode back returns hits 
00085    GLint hits = glRenderMode(GL_RENDER);
00086 
00087    /// see if we actually picked ANYTHING
00088    if(!hits) return PickInfoVec();
00089 
00090    /// we did so create the info vector
00091    PickInfoVec piv;
00092 
00093    /// loop over picks
00094    for(int i=0, j=0; i<hits; ++i)
00095    {
00096       ///////////////////
00097       /// make sure we don't overrun the pick buffer,
00098       ///  first check.
00099       if( j >= _pbSize )
00100       {
00101          cerr << "Pick::endPick(), pick-buffer overrun, try increasing the " 
00102             << "size of the pick buffer." << endl;
00103          sort(piv.begin(), piv.end(), PBSortZ1());
00104          return piv; ///< just return what we have
00105       }
00106       ///////////////////
00107 
00108       /// first item on stack is the number of names
00109       unsigned int nnames = _pickBuffer[j++];
00110       
00111       ///////////////////
00112       /// make sure we don't overrun the pick buffer
00113       ///   second check..
00114       if( int(j+nnames+1) >= _pbSize )
00115       {
00116          cerr << "Pick::endPick(), pick-buffer overrun, try increasing the " 
00117             << "size of the pick buffer.." << endl;
00118          sort(piv.begin(), piv.end(), PBSortZ1());
00119          return piv; ///< just return what we have
00120       }
00121       ///////////////////
00122 
00123       /// add the pick info to our vector
00124       piv.push_back(
00125          PickInfo(
00126            _pickBuffer[j  ]/double(std::numeric_limits<unsigned int>::max()), //z1
00127            _pickBuffer[j+1]/double(std::numeric_limits<unsigned int>::max()), //z2
00128            &(_pickBuffer[j+2]), nnames                                        //names
00129          )
00130       );
00131 
00132       /// increment j so we are at the right position in the pick buffer.
00133       j += nnames + 2;
00134 
00135    } /// end loop over picks
00136 
00137    /// sort pickInfo vector based on increasing z1 value
00138    sort(piv.begin(),piv.end(),PBSortZ1());  
00139    return piv;
00140 }

Send questions, comments, and bug reports to:
jmk