c++ - 选择模式下的 OpenGL 拾取

标签 c++ qt opengl qglwidget

我知道 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 给出),它必须以某种方式引用一个对象(可能有一个包含名称的字符串公共(public)成员),所以我可以改变它的属性?

最佳答案

您将不得不自己存储每个对象的属性。当您将名称压入名称堆栈时,您所做的只是向每个片段添加额外的数据,以便您以后可以有效地识别它的来源。

您可能想要创建一个结构,如 { float rad1, rad2, complex1, complex2; } 来存储每个环面的值。知道所选对象的 ID 后,进入所述结构的数组,并修改相应对象的值。每次绘制场景时,只需遍历这个结构数组。

关于c++ - 选择模式下的 OpenGL 拾取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16735736/

相关文章:

c++ - 返回对 int 的引用与在 C++ 函数中返回 int?

c++ - 避免 Switch 语句中的分支操作

c++ - 使用 C++ 将事件处理程序添加到新创建的窗口

c++ - 在 Qt 虚拟键盘上实现 Backspace 和 Enter 键

c++ - 在另一个类上使用的单例模式

c++ - 使用 QtCreator,如何在我具有 ssh 访问权限的远程服务器上构建我的项目?

c++ - QT 样式注释(智能感知?)

c++ - 在 Linux 中制作程序,OpenGL、Wayland 和 Qt 如何融入画面

c++ - 带有 QOpenGLWidget 的 Qt 5.5,核心配置文件中的隐形三角形

c++ - 在 OpenGL 中绘制多个相关对象