如何使用 OpenGL 选择对象






4.61/5 (17投票s)
本文档解释了如何使用 OpenGL 选择对象。
引言
我来自越南,英语不太好。但我希望您能理解我的文章。我尝试编写一个游戏作为我的学校项目。我决定使用 3D 技术编写它,并为此使用了 OpenGL。我一直在寻找一种在 3D 中选择大量对象的方法,并且找到了它。 在本文中,我想向您介绍如何操作。
使用代码
在这个例子中,我使用 MFC 向导。 我的所有代码都写在 CView
上。
添加变量
private: GLdouble gldAspect; GLsizei glnWidth, glnHeight; HGLRC hRC; Cube cube[4]; double r;
Cube
在 MyOpenGL.h 中定义。
使用“类向导”进行消息映射:WM_CREATE
、WM_DESTROY
、WM_EARSEBKGND
、WM_LBUTTONDOWN
、WM_PAINT
、WM_SIZE
、WM_TIMER
。
在 CodeProject 上关于 OpenGL 的另一篇文章中,你可以看到 WM_SIZE
和 WM_PAINT
、WM_CREATE
的代码(我再次使用了代码! 感谢作者的代码!)。
此外,在 WM_CREATE
中,初始化一些变量并启动动画计时器。
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; }
当然,在 OnDestroy()
中停止计时器。
定时器
void CTry_OpenGLView::OnTimer(UINT nIDEvent) { r+=5; if(r>=360) r=0; RedrawWindow(); CView::OnTimer(nIDEvent); }
在 OnEraseBkgnd
中:删除所有内容(否则屏幕会“闪烁”)。
现在,选择对象的代码
void CTry_OpenGLView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default GLuint selectBuf[BUFSIZE]; 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); }
关注点
很简单,不是吗? 我的源代码有一些冗余,我想。 如果您能帮助我删除它,非常感谢! ^_^
历史
- 这是第一个!