OpenGL: Glut实现选取

来源:互联网 发布:java 泛型方法 调用 编辑:程序博客网 时间:2024/06/03 10:59

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 intBUFSIZE = 512;intg_iWidth = 800;intg_iHeight = 600;floatg_fAngle = 0;const GLfloatred[]    = { 231.0 / 255.0, 36.0 / 255.0, 46.0 / 255.0, 1.0};const GLfloatyellow[] = { 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();}};Cubecube[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 modeglInitNames();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

 

0 0