选择模式下的OpenGL拾取 [英] OpenGL Picking on Selection Mode

查看:238
本文介绍了选择模式下的OpenGL拾取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道OpenGL选择模式已被弃用,并且从来没有被硬件加速过,除了一些SGI盒子和3DLabs GPU之外,但是我无法摆脱它(不是我的代码),下面是C ++代码:

I know that OpenGL selection mode is deprecated and never was HW accelerated, except on a few SGI boxes and 3DLabs GPUs.But i can't get rid of it (not my code).Below its the C++ code:

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方法

This is the processHits method

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()通过使用*事件(GLWidget派生自QGLWidget(QT 4.8))来调用. 因此,只有当我单击鼠标右键时,我才会在缓冲区中绘制"对象并将它们的名称压入堆栈.

Selection() is invoked by using an *event (GLWidget derives from QGLWidget (QT 4.8)). So,only when i click the right mousebutton I ""draw"" objects in the buffer and push their names on the stack.

void GLWidget::mousePressEvent(QMouseEvent *event)
{
lastPos = event->pos();
if (event->buttons() & GLUT_RIGHT_BUTTON){
    Selection(event->x(),event->y());
    }
}

paintGL()方法是

While the paintGL() method is

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)的对象.

At this time,with this code, I can select an object and retrieve its ID,and if there are more of them on the same xy coordinates i can retrieve the nearest one (by ID). So,now I've got 3 objects with 3 different IDs (1-2-3).

ID = 3的对象的大小不固定.我的问题是:如何使用缓冲区来检索第三个圆环并更改其大小以修改RADIUS1,RADIUS2,complex1,complex2?

The one with ID=3 has non fixed size.My question is:how to use the buffer to retrieve the third torus and change its size modifying RADIUS1, RADIUS2, complex1, complex2?

你们中的一个人可以写一个小例子吗?

Could someone of you write a small example?

有一次,当我被命中时,只需使用堆栈上命中的名称(使用glPushName给定),该名称必须以某种方式引用一个对象(也许带有一个包含该名称的字符串public member),这样我可以更改其属性?

Have I,when there is a hit,simply use the name of the hit on the stack (given with glPushName),that must refers in some way to an object (maybe with a string public member wich contains the name),so i can change its properties?

推荐答案

您将必须自己存储每个对象的属性.将名称推入名称堆栈时,您要做的就是向每个片段添加额外的数据,以便以后可以有效地识别其来源.

You are going to have to store the properties of each object yourself. When you push a name onto the name stack, all you're doing is adding extra data to each fragment so you can effectively identify where it came from later.

您可能想要创建一个结构,例如{float rad1,rad2,complex1,complex2; }存储每个圆环的值.一旦知道所选对象的ID,就进入所述结构的数组,并修改适当对象的值.每次绘制场景时,只需遍历此结构数组即可.

You'll probably want to create a structure like { float rad1, rad2, complex1, complex2; } to store the values for each torus. Once you know the ID of the object selected, go into your array of said struct, and modify the values for the appropriate object. Each time you draw your scene, just run through this array of structs.

这篇关于选择模式下的OpenGL拾取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆