OpenGL三维面拾取

原理:

    OpenGL中的拾取是对OpenGL图形管线的一个应用,是在图形管线的投影变换阶段利用拾取矩阵来实现的。

    首先介绍一下名字栈,在拾取之后,怎么获得拾取面的标识呢?这里就需要对每个图元设置标识符。拾取完成,后OpenGL会在指定的SelectBuffer缓冲区中保存拾取面的标识符。
    OpenGL一共有三种模型:GL_RENDER渲染模式(默认值),GL_SELECT选择模式,GL_FEEDBACK反馈模式。在OpenGL进入选择模式后,获取鼠标坐标(也可以是其他坐标点)后,生成一个指定大小的选择框。OpenGL会自动裁剪掉在选择框之外的物体,然后进行归一化视体操作:先将选择框归一化为-1到1 的正方体,然后移动的原点,最后放大为窗体的大小。需要注意的是这个视体并不会被绘制,也就是不会被放在缓存区中。OpenGL会把拾取面的标识放在SelectBuffer的缓存区中。
    这还没完,那么SelectBuffer里面数据时怎么存储的呢?
一条拾取信息:
第一项.击中的物件的名字的数目(即:1)
第二项.这个物件中最近的点的深度值
第三项.这个物件中最远的点的深度值
第四项.这个物件的唯一的名字
在一些应用场景下,对一个物体可能会配两个或多个名字。这时,第一项记录就不为1,在第四项后面还会增加相应的名字项。第二项、第三项说明的是视点距离物体的深度值,物件对应Z-BUFFER中的深度值,乘以2^32 -1后取整而得到。

代码实现:

GLuint selectBuff[PICK_BUFFER_SIZE]; 
GLint hits, viewport[4];   

glSelectBuffer(PICK_BUFFER_SIZE, selectBuff); //告诉OpenGL初始化selectbuffer
glRenderMode(GL_SELECT);   

glInitNames();  //初始化名字栈 
glPushName(0);
glMatrixMode(GL_PROJECTION);    //备份当前投影矩阵
glPushMatrix();    
glLoadIdentity();   

glGetIntegerv(GL_VIEWPORT, viewport);
gluPickMatrix( GLdouble(mouse_x),           //  
GLdouble(viewport[3]-mouse_y),    // viewport[3]保存的是窗口的高度,窗口坐标转换为OpenGL坐标  
10,10,              // 选择框
viewport          // 视口信息
);   
double left =  - pDC->m_Camera.m_width/2.0;
double right =  pDC->m_Camera.m_width/2.0;
double bottom =  - pDC->m_Camera.m_height/2.0;
double top =  pDC->m_Camera.m_height/2.0;
glOrtho(left,right,bottom,top,pDC->m_Camera.m_near,pDC->m_Camera.m_far);
for( int i = 0; i < m_Facet.GetSize(); i++ ) //重绘物体
{
glLoadName( i+1 );//添加标识符
for (int j=0;j<m_Facet[i]->triangle.GetSize();j++)
m_Facet[i]->triangle[j]->Draw(pDC,m_Facet[i]->clr);
}
glMatrixMode(GL_PROJECTION);//恢复投影矩阵
glPopMatrix();
hits = glRenderMode(GL_RENDER); // 返回选择到对象的个数  
if(hits > 0)  
{
m_Facet[selectBuff[3]-1]->selected = !m_Facet[selectBuff[3]-1]->selected;  //  选择结果处理
if (m_Facet[selectBuff[3]-1]->selected)
{
m_Facet[selectBuff[3]-1]->clr =RGB(0,255,0);
}
else
m_Facet[selectBuff[3]-1]->clr =RGB(255,255,255);
}

需要说明的是看代码注释,很好理解整个过程,但是要特别注意,glOrtho()设置的视体一定要是窗体的大小,不能随便设置。
看看效果:双击选中,选中为绿色。

OpenGL三维面拾取_第1张图片

OpenGL三维面拾取_第2张图片

OpenGL三维面拾取_第3张图片


你可能感兴趣的:(OpenGL三维面拾取)