opengl中鼠标拾取操作分析
2012-07-25 11:14
381 查看
在进行Opengl编程时,通常会进行一些交互式操作,其中的鼠标拾取技术可以实现对目标物体的选取和判断,为开发者和用户带来便利。下面笔者就对这当中的一些核心代码进行总结和分析。
Opengl中的拾取是对opengl管线的一个应用,所以这个过程并不是想象中利用射线求交来判断是否选中目标物体,而是利用投影变换阶段的拾取矩阵进行的。
由于我的工程是在mfc环境下进行的,所以我只列出核心代码并进行分析,不过只要读者真正理解了这部分代码,相信这个功能也就很好的实现了。
int mouse_x ,mouse_Y;
//鼠标位置
GLuint buffer[512];
//设定一个选择缓冲区
GLint hits;
//被选中的物体的数量
void
Selection(void)
//拾取
{
GLint
viewport[4]; //视口的大小,四个值分别为,x,y,width,height;
glGetIntegerv(GL_VIEWPORT,
viewport);
glSelectBuffer(512,
buffer);
(void)
glRenderMode(GL_SELECT);
//拾取前,要进入进入选择模式
glInitNames();
//初始化名字栈,主要用来存放目标物体的名字
glPushName(0);
//在名字栈里放入一个初始化名字
glMatrixMode(GL_PROJECTION);
//选择投影矩阵,我前面说过,判断是以投影的形式进行的
glPushMatrix();
//压入投影矩阵
glLoadIdentity();
// Resets The Matrix 重置矩阵,为了使构建拾取矩阵
gluPickMatrix((GLdouble)
mouse_x, //建立拾取矩阵
(GLdouble) (viewport[3]-mouse_y),//窗口坐标转化为opengl坐标
1.0f, 1.0f, //选择框的大小
viewport);
//视口的位置和大小
gluPerspective(45.0f, (GLfloat) (viewport[2]-viewport[0])/(GLfloat)
(viewport[3]-viewport[1]), 0.01f, 1200.0f);
//乘以投影矩阵
glMatrixMode(GL_MODELVIEW);
//进入视图变换状态
Draw(GL_SELECT);//该函数是用来渲染物体,也就是你自己要绘制的物体,包括名字
glMatrixMode(GL_PROJECTION);//投影变换状态
glPopMatrix();
// 进入之前的投影状态,因为以上都是绘制时的状态
glMatrixMode(GL_MODELVIEW);
hits=glRenderMode(GL_RENDER);
// 获得选中物体的个数
ProcessHits(hits,buffer);
//对选中的物体进行处理
}
void
ProcessHits(GLint
hits, GLuint
buffer[])
{
if (hits > 0)
// 如果选中物体数目大于0
{
int
choose = buffer[3];
//buffer第一个值为选中物体的的个数,第二个、第三个表示物体的最小深度和最大深度,第四个为选中的名字
int
depth = buffer[1];
for (int
loop = 1; loop <
hits; loop++)
{
if (buffer[loop*4+1] <
GLuint(depth))
//判断当前的物体是否离我们最近
{
choose =
buffer[loop*4+3];
depth =
buffer[loop*4+1];
}
}
//…
添加自己的处理代码
}
}
void
Draw(GLenum
model)
{
if (model ==
GL_SELECT)
{
glLoadName(1);
}
//添加物体1代码
if (model ==
GL_SELECT)
{
glLoadName(2);
}
//添加物体2代码
…
}
希望通过上面的代码大家可以有所收获,不对之处还望更正。
Opengl中的拾取是对opengl管线的一个应用,所以这个过程并不是想象中利用射线求交来判断是否选中目标物体,而是利用投影变换阶段的拾取矩阵进行的。
由于我的工程是在mfc环境下进行的,所以我只列出核心代码并进行分析,不过只要读者真正理解了这部分代码,相信这个功能也就很好的实现了。
int mouse_x ,mouse_Y;
//鼠标位置
GLuint buffer[512];
//设定一个选择缓冲区
GLint hits;
//被选中的物体的数量
void
Selection(void)
//拾取
{
GLint
viewport[4]; //视口的大小,四个值分别为,x,y,width,height;
glGetIntegerv(GL_VIEWPORT,
viewport);
glSelectBuffer(512,
buffer);
(void)
glRenderMode(GL_SELECT);
//拾取前,要进入进入选择模式
glInitNames();
//初始化名字栈,主要用来存放目标物体的名字
glPushName(0);
//在名字栈里放入一个初始化名字
glMatrixMode(GL_PROJECTION);
//选择投影矩阵,我前面说过,判断是以投影的形式进行的
glPushMatrix();
//压入投影矩阵
glLoadIdentity();
// Resets The Matrix 重置矩阵,为了使构建拾取矩阵
gluPickMatrix((GLdouble)
mouse_x, //建立拾取矩阵
(GLdouble) (viewport[3]-mouse_y),//窗口坐标转化为opengl坐标
1.0f, 1.0f, //选择框的大小
viewport);
//视口的位置和大小
gluPerspective(45.0f, (GLfloat) (viewport[2]-viewport[0])/(GLfloat)
(viewport[3]-viewport[1]), 0.01f, 1200.0f);
//乘以投影矩阵
glMatrixMode(GL_MODELVIEW);
//进入视图变换状态
Draw(GL_SELECT);//该函数是用来渲染物体,也就是你自己要绘制的物体,包括名字
glMatrixMode(GL_PROJECTION);//投影变换状态
glPopMatrix();
// 进入之前的投影状态,因为以上都是绘制时的状态
glMatrixMode(GL_MODELVIEW);
hits=glRenderMode(GL_RENDER);
// 获得选中物体的个数
ProcessHits(hits,buffer);
//对选中的物体进行处理
}
void
ProcessHits(GLint
hits, GLuint
buffer[])
{
if (hits > 0)
// 如果选中物体数目大于0
{
int
choose = buffer[3];
//buffer第一个值为选中物体的的个数,第二个、第三个表示物体的最小深度和最大深度,第四个为选中的名字
int
depth = buffer[1];
for (int
loop = 1; loop <
hits; loop++)
{
if (buffer[loop*4+1] <
GLuint(depth))
//判断当前的物体是否离我们最近
{
choose =
buffer[loop*4+3];
depth =
buffer[loop*4+1];
}
}
//…
添加自己的处理代码
}
}
void
Draw(GLenum
model)
{
if (model ==
GL_SELECT)
{
glLoadName(1);
}
//添加物体1代码
if (model ==
GL_SELECT)
{
glLoadName(2);
}
//添加物体2代码
…
}
希望通过上面的代码大家可以有所收获,不对之处还望更正。
相关文章推荐
- OpenGL鼠标拾取
- 轻轻松松做OpenGL鼠标拾取
- 关于unity的轴的移动和openGL的鼠标拾取
- OpenGL中鼠标拾取
- OpenGL鼠标拾取的实现:终于搞定(包括细节问题)
- OpenGL鼠标拾取的实现:终于搞定(包括细节问题)
- opengl 鼠标拾取
- [置顶] OpenGL鼠标拾取的实现:终于搞定(包括细节问题)
- 深入理解OpenGL拾取模式(OpenGL Picking)
- OpenGL中与鼠标的交互——点击鼠标左键,在鼠标处画点
- 使用OpenGL实现三维坐标的鼠标拣选
- 【转】Direct3D中实现图元的鼠标拾取
- OpenGL中的鼠标控制
- 使用OpenGL实现三维坐标的鼠标拣选(转)
- OpenGL鼠标旋转图像
- OpenGL鼠标控制绘制矩形
- CSharpGL(21)用鼠标拾取、拖拽VBO图元内的点、线或本身
- Modern OpenGL用Shader拾取VBO内单一图元的思路和实现
- 乱弹OpenGL选择-拾取机制(下)
- OpenGL学习笔记:拾取与选择