opengl中的选择基本思路:
1,获得视口信息,指定返回点击记录的数组。
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (BUFSIZE, selectBuf);
2,glRenderMode(GL_SELECT)进入选择模式,
3,对名字堆栈进行初始化
glInitNames();
glPushName(-1);
4,利用gluPickMatrix构造拾取矩阵进行选择,
glPushMatrix ();
glLoadIdentity ();
gluPickMatrix((GLdouble) mousex, (GLdouble) (viewport[3] - mousey), 5.0, 5.0, viewport);
gluPerspective(30.0, (GLfloat)g_iWidth/(GLfloat)g_iHeight, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
PaintScreen(GL_SELECT);
glPopMatrix ();
鼠标左键拾取cube,为了保证每次只能有一个cube被选中,MouseCB函数中对z值进行比较。保证始终z最小的cube被选择。相应的处理语句:
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];
}
}
//hit记录第四项为ID编号
cube[selectBuf[3 + n * 4]].selected = !(cube[selectBuf[3 + n * 4]].selected);
}
运行效果:
下面是整个cpp:
#include <Windows.h>
#include <GL/glut.h>
#pragma comment(lib,"glut32.lib")
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"opengl32.lib")
const int BUFSIZE = 512;
int g_iWidth = 800;
int g_iHeight = 600;
float g_fAngle = 0;
const GLfloat red[] = { 231.0 / 255.0, 36.0 / 255.0, 46.0 / 255.0, 1.0};
const GLfloat yellow[] = { 253.0 / 255.0, 208.0 / 255.0, 0.0 / 255.0, 1.0};
class Cube
{
public:
double x, y, z;
bool selected;
Cube()
: x(0), y(0), z(0)
, selected(false)
{}
void Draw()
{
glPushMatrix();
{
glTranslated(x, y, z);
if (selected)
{
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, red);
}
else
{
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, yellow);
}
glutSolidCube(1.0);
}
glPopMatrix();
}
};
Cube cube[4];
void PaintScreen(GLenum mode)
{
glPushMatrix();
glRotated( g_fAngle, 0.0, 1.0, 0.0 );
for(int i = 0; i < 4; i++)
{
if (mode==GL_SELECT)
{
glLoadName(i);
}
cube[i].Draw();
}
glPopMatrix();
}
void Init()
{
glClearColor(84.0 / 255.0, 0.0 / 255.0, 125.0 / 255.0, 0.0);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
for(int i = 0; i < 4; i++)
{
cube[i].x = i * 2 - 3;
}
}
void Reshape(int Width, int Height)
{
if (0 == Height)
{
Height = 1;
}
glViewport(0, 0, Width, Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, (GLfloat)Width / (GLfloat)Height, 1.0, 20.0);
}
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(6.0, 4.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
PaintScreen(GL_RENDER);
glDisable(GL_LIGHT0);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glutSwapBuffers();
}
void Idle()
{
g_fAngle += 0.5;
if( g_fAngle >= 360 )
{
g_fAngle = 0;
}
//调用DrawGLScene函数
glutPostRedisplay();
}
void KeyBoardCB(unsigned char key, int x, int y)
{
if(key == 27)
{
exit(0);
}
}
void MouseCB(int button, int state, int mousex, int mousey)
{
if( button != GLUT_LEFT || state != GLUT_DOWN)
{
return;
}
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];
static bool IsFirst = true;
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) mousex, (GLdouble) (viewport[3] - mousey), 5.0, 5.0, viewport);
gluPerspective(30.0, (GLfloat)g_iWidth/(GLfloat)g_iHeight, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
PaintScreen(GL_SELECT);
glPopMatrix ();
glFlush();
hits = glRenderMode (GL_RENDER);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, g_iWidth, g_iHeight);
gluPerspective(30.0, (GLfloat)g_iWidth/(GLfloat)g_iHeight, 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];
}
}
//hit记录第四项为ID编号
cube[selectBuf[3+n*4]].selected = !( cube[selectBuf[3+n*4]].selected );
}
//glutPostRedisplay();
}
int main(int argc, char **argv)
{
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (800, 600);
glutInitWindowPosition (100, 100);
glutCreateWindow ("OpenGL Select Obj");
Init();
glutDisplayFunc ( DrawGLScene );
glutReshapeFunc ( Reshape );
glutMouseFunc( MouseCB );
glutKeyboardFunc( KeyBoardCB );
glutIdleFunc( Idle );
glutMainLoop ();
return 0;
}
http://blog.csdn.net/ryfdizuo/article/details/4012067