《基于MFC的OpenGL编程》Part 15 Selection

本文介绍如何使用OpenGL的选取功能实现对场景中特定物体的选择。通过设置视口、定义视锥体,并利用gluPickMatrix创建小视锥体置于鼠标光标下,可以确定哪些物体位于该区域内。

Selection

Selection is a powerful feature of OpenGL that allows you click at some position of the OpenGL window using the mouse and determine which of your objects lie beneath it. The act of selecting a specific object is called Picking. With OpenGL's selection feature, we can specify a viewing volume and determine which objects fall within that viewing volume. A powerful utility function, gluPickMatrix, produces a matrix which can be used to create a smaller viewing volume placed beneath the mouse cursor. Then we use selection to test this viewing volume to see which objects are contained by it.

Selection is actually a rendering mode, but in this mode no pisels are actually copied onto the frame buffer. Instead, primitives drawn within the viewing volume produce hit records in a selection buffer. We must set up this selection buffer in advance and name the primitives or groups of primitives so that they can be identified in the selection buffer.We can then parse the buffer to determine which objects intersected the viewing volume.

Naming Primitives

We have to name a group of primitives such as one describing a cube or a cylinder etc in order to identify them. These names are nothing but integers such as for display list names. The names list is maintained on the named stack. After we initialize the name stack we can push names on the stack or simply replace the name currently on the top of the stack. When a hit occurs during selection, all the names on the stack are copied onto the selection buffer.

1,CCY457OpenGLView类中加入一个变量,用来表示宽高比

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->GLdoublem_aspectRatio;//width/heightratio

2OnSize函数修改如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->voidCCY457OpenGLView::OnSize(UINTnType,intcx,intcy)
{
CView::OnSize(nType,cx,cy);
if(0>=cx||0>=cy)
{
return;
}
//selectthefullclientarea
::glViewport(0,0,cx,cy);
//computetheaspectratio
//thiswillkeepalldimensionscalesequal
m_aspectRatio=(GLdouble)cx/(GLdouble)cy;
//selecttheprojectionmatrixandclearit
::glMatrixMode(GL_PROJECTION);
::glLoadIdentity();
//selecttheviewingvolume
::gluPerspective(45.0f,m_aspectRatio,.01f,200.0f);
//::gluOrtho2D(-10.0f,10.0f,-10.0f,10.0f);
//switchbacktothemodelviewmatrixandclearit
::glMatrixMode(GL_MODELVIEW);
::glLoadIdentity();
}

3,绘制函数修改如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->voidCCY457OpenGLView::RenderScene()
{
//绘制函数
glTranslatef(0.0f,0.0f,-5.0f);
glRotatef(m_xRot,
1.0f,0.0f,0.0f);
glRotatef(m_yRot,
0.0f,1.0f,0.0f);
glInitNames();
glPushName(
0);
glPushMatrix();
glTranslatef(
-2.0f,0.0f,0.0f);
glLoadName(
1);
glutSolidSphere(
1.0f,20,20);
glPopMatrix();
glPushMatrix();
glLoadName(
2);
glTranslatef(
2.0f,0.0f,0.0f);
glutSolidCube(
1.0f);
glPopMatrix();
}

4,加入对鼠标左键选择物体的处理

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->voidCCY457OpenGLView::ProcessSelection(CPointpoint)
{
intxPos=point.x;
intyPos=point.y;
GLuintselectBuff[
64];
GLinthits,viewport[
4];
glSelectBuffer(
64,selectBuff);
glGetIntegerv(GL_VIEWPORT,viewport);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glRenderMode(GL_SELECT);
glLoadIdentity();
gluPickMatrix(xPos,viewport[
3]-yPos,2,2,viewport);
gluPerspective(
45.0f,m_aspectRatio,.01f,200.0f);
RenderScene();
hits
=glRenderMode(GL_RENDER);
if(hits==1)
ProcessObject(selectBuff);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
voidCCY457OpenGLView::ProcessObject(GLuint*pSelectBuff)
{
intid=pSelectBuff[3];
if(id==1)
MessageBox(
"YouclickedonSphere");
if(id==2)
MessageBox(
"YouclickedonCube");
}
voidCCY457OpenGLView::OnLButtonDown(UINTnFlags,CPointpoint)
{
ProcessSelection(point);
CView::OnLButtonDown(nFlags,point);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值