Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to select an object using OpenGL

0.00/5 (No votes)
29 Oct 2003 1  
This article explains how to select an object using OpenGL.

Sample Image

Introduction

I am Vietnamese and my English is not good. But I hope you will understand my article. I tried to write a game as my project in school. I decided to write it using 3D technique, and I used OpenGL for this. I looked for a way to select an object on a lot object overunder on 3D and I have found it. In this article I want to introduce you to how to do it.

Using the code

In this example I use MFC wizard. All my code was written on CView.

Add variables:

private:
    GLdouble gldAspect;
    GLsizei glnWidth, glnHeight;
    HGLRC hRC;
    Cube cube[4];
    double r;

Cube is defined in MyOpenGL.h.

Use "class wizard" for message map: WM_CREATE, WM_DESTROY, WM_EARSEBKGND, WM_LBUTTONDOWN, WM_PAINT, WM_SIZE, WM_TIMER.

On another article in CodeProject about OpenGL you can see the code for WM_SIZE and WM_PAINT, WM_CREATE (I use the code again! Thanks to the owner's code!).

Additionally, on WM_CREATE, init for some variables and start the timer for animation.

int CTry_OpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
     if (CView::OnCreate(lpCreateStruct) == -1)
          return -1;
     
     // TODO: Add your specialized creation code here

     hRC=SetUpOpenGL(m_hWnd);
     for(int i=0;i<4;i++) cube[i].x=i*2-3;
     r=0;
     SetTimer(1000,100,NULL);

     return 0;
}

Of course, kill timer in OnDestroy().

Timer:

void CTry_OpenGLView::OnTimer(UINT nIDEvent) 
{
     r+=5;
     if(r>=360) r=0;
     RedrawWindow();

     CView::OnTimer(nIDEvent);
}

In OnEraseBkgnd: delete all (if not, the screen will "flick").

And now, the code to pick an object:

void CTry_OpenGLView::OnLButtonDown(UINT nFlags, CPoint point) 
{
     // TODO: Add your message handler code here and/or call default

    GLuint selectBuf;
    GLint hits;
    GLint viewport[4];

     HDC hDC = ::GetDC(this->m_hWnd);
     wglMakeCurrent(hDC,hRC);

    glGetIntegerv (GL_VIEWPORT, viewport);
    glSelectBuffer (BUFSIZE, selectBuf);

    glRenderMode(GL_SELECT); // Enter the SELECT render mode

    glInitNames();
    glPushName(-1);

    glMatrixMode (GL_PROJECTION);
    glPushMatrix ();
    glLoadIdentity ();
    gluPickMatrix((GLdouble) point.x, 
          (GLdouble) (viewport[3] - point.y), 
          5.0, 5.0, viewport);
    gluPerspective(30.0,gldAspect,1.0,20.0);
    glMatrixMode(GL_MODELVIEW);
    PaintScreen(GL_SELECT);//function paint the objects.

    glPopMatrix ();
    glFlush ();

    hits = glRenderMode (GL_RENDER);

     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     glViewport(0,0,glnWidth,glnHeight);
     gluPerspective(30.0,gldAspect,1.0,20.0);
    
     /*for(int i=0;i<hits;i++)
     {
          cube[selectBuf[3+i*4]].selected= 
             !cube[selectBuf[3+i*4]].selected;
     }//select all (include the hide object)!
     */
     if (hits)
     {
          int n=0;double minz=selectBuf[1];
          for(int i=1;i<hits;i++)
          {
               if (selectBuf[1+i*4]<minz) 
                 {n=i;minz=selectBuf[1+i*4];}
          }
          cube[selectBuf[3+n*4]].selected=
              !cube[selectBuf[3+n*4]].selected;
     }//only select the object we see (nearest object)!


     wglMakeCurrent( NULL, NULL );
    ::ReleaseDC( this->m_hWnd, hDC );

     CView::OnLButtonDown(nFlags, point);
}

Points of interest

Is it easy, isn't it? My source has some wastes, I think. Thanks a lot if you can help me to remove it! ^_^

History

  • This is the first!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here