选择模式下的 OpenGL 拾取
Posted
技术标签:
【中文标题】选择模式下的 OpenGL 拾取【英文标题】:OpenGL Picking on Selection Mode 【发布时间】:2013-05-24 13:08:35 【问题描述】:我知道 OpenGL 选择模式已被弃用,并且从未被硬件加速,除了在一些 SGI 盒子和 3DLabs GPU 上。但我无法摆脱它(不是我的代码)。下面是 C++ 代码:
void GLWidget::Selection(int x,int y) // This Is Where Selection Is Done
GLint viewport[4];
glSelectBuffer(BUFSIZE,selectBuf);
glRenderMode(GL_SELECT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glGetIntegerv(GL_VIEWPORT,viewport);
gluPickMatrix(x,viewport[3]-y,5,5,viewport); //defining the picking matrix
gluPerspective(fov,ratio,0.1f,1000);
glMatrixMode(GL_MODELVIEW);
glInitNames();
glPushName(1); //Pushing names on the stack
glutSolidTorus(1, 2, 55, 55); //Some draw in GL_SELECT mode
glTranslatef(5.0f,1,5.0f);
glPopName();
glPushName(2);
glutSolidTorus(1, 2, 55, 55);
glTranslatef(5.0f,1,5.0f);
glPopName();
glPushName(3);
glutSolidTorus(RADIUS1, RADIUS2, complex1, complex2); //public members
glTranslatef(5.0f,1,5.0f);
glPopName();
int hits;
// restoring the original projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
// returning to normal rendering mode
hits = glRenderMode(GL_RENDER);
// if there are hits process them
if (hits != 0)
qDebug() << "Found " << hits << " hit(s)";
processHits(hits,selectBuf);
这是 processHits 方法
void GLWidget::processHits (GLint hits, GLuint buffer[]) //Some prints
unsigned int i, j;
GLuint names, *ptr, minZ,*ptrNames, numberOfNames;
ptr = (GLuint *) buffer;
minZ = 0xffffffff;
for (i = 0; i < hits; i++)
names = *ptr;
ptr++;
if (*ptr < minZ)
numberOfNames = names;
minZ = *ptr;
ptrNames = ptr+2;
ptr += names+2;
qDebug() << "Nearest: ";
ptr = ptrNames;
for (j = 0; j < numberOfNames; j++,ptr++)
qDebug() << *ptr ;
Selection() 是通过使用 *event 调用的(GLWidget 派生自 QGLWidget (QT 4.8))。 因此,只有当我单击鼠标右键时,我才会在缓冲区中“绘制”对象并将它们的名称压入堆栈。
void GLWidget::mousePressEvent(QMouseEvent *event)
lastPos = event->pos();
if (event->buttons() & GLUT_RIGHT_BUTTON)
Selection(event->x(),event->y());
而paintGL()方法是
void GLWidget::paintGL()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glViewport (0, 0, w_screen, h_screen);
gluLookAt(objCamera->mPos.x, objCamera->mPos.y, objCamera->mPos.z,
0, objCamera->mView.y, 0,
objCamera->mUp.x, objCamera->mUp.y, objCamera->mUp.z);
glutSolidTorus(1, 2, 55, 55); //draw some objects
glTranslatef(5.0f,1,5.0f);
glutSolidTorus(1, 2, 55, 55);
glTranslatef(5.0f,1,5.0f);
glutSolidTorus(RADIUS1, RADIUS2, complex1, complex2);
glTranslatef(5.0f,1,5.0f);
glTranslatef(-15.0f,-3,-15.0f);
此时,使用此代码,我可以选择一个对象并检索其 ID,如果在相同的 xy 坐标上有更多对象,我可以检索最近的一个(按 ID)。 所以,现在我有 3 个具有 3 个不同 ID (1-2-3) 的对象。
ID=3 的大小不固定。我的问题是:如何使用缓冲区检索第三个圆环并更改其大小修改 RADIUS1、RADIUS2、complex1、complex2?
有人能写一个小例子吗?
我有没有,当有命中时,只需使用堆栈上命中的名称(使用 glPushName 给出),它必须以某种方式引用一个对象(可能使用包含名称的字符串公共成员),所以我可以改变它的属性?
【问题讨论】:
【参考方案1】:您将不得不自己存储每个对象的属性。当您将名称推送到名称堆栈时,您所做的就是向每个片段添加额外的数据,以便您以后可以有效地识别它的来源。
您可能想要创建一个像 float rad1, rad2, complex1, complex2; 这样的结构。 来存储每个圆环的值。一旦您知道所选对象的 ID,请进入您的所述结构数组,并修改相应对象的值。每次绘制场景时,只需遍历这个结构数组即可。
【讨论】:
以上是关于选择模式下的 OpenGL 拾取的主要内容,如果未能解决你的问题,请参考以下文章