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;
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)
{
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);
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);
glPopMatrix ();
glFlush ();
hits = glRenderMode (GL_RENDER);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0,0,glnWidth,glnHeight);
gluPerspective(30.0,gldAspect,1.0,20.0);
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;
}
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