2016-11-11 120 views
0

我在使用选择缓冲区的OpenGL的选择机制中遇到了相当困难的时间。具体来说,我希望能够在选定的对象中进行子选择。我的测试世界上有散落的多个对象,每个对象有四个呈现“面临着”,类似这样的:使用SelectBuffer选择多个名称OpenGL

void drawObject(int i) 
{ 
    renderFace0(i); 
    renderFace1(i); 
    renderFace2(i); 
    renderFace3(i); 
} 

一切都很好,至今。参数i只是说索引是什么,因为我的“对象”只是存储在数组中的数据。每个对象都是基于其索引唯一标识的。然后,我添加了采摘功能,其目标正在指向更新(我用的是屏幕的中心,其采点的对象):

void pickObject() 
{ 
    unsigned int selectBuffer[200]; 
    int viewport[4]; 
    int hits; 

    glGetIntegerv(GL_VIEWPORT, viewport); 
    glSelectBuffer(200, selectBuffer); 

    glRenderMode(GL_SELECT); 

    glInitNames(); 
    glPushName(0); 

    glMatrixMode(GL_PROJECTION); 
    glPushMatrix(); 
    glLoadIdentity(); 

    gluPerspective(45.0f, (double)width/(double)height, 0.05f, 100.0f); 

    double centerX = (double)width/2.0; 
    double centerY = (double)height/2.0; 

    gluPickMatrix(centerX, centerY, 5.0f, 5.0f, viewport); 
    transformWorld(); 
    int i; 
    for(i = 0; i < NUM_OBJECTS; i ++) 
    { 
     glLoadName(i + 1); 
     drawObject(i); 
    } 

    hits = glRenderMode(GL_RENDER); 
    if(hits > 0) 
    { 
     int znear; 
     znear = selectBuffer[2]; 
     selected = selectBuffer[3]; 

     for(i = 1; i < hits; i ++) 
     { 
      if(selectBuffer[4 * i + 2] > znear) 
      { 
       znear = selectBuffer[4 * i + 2]; 
       selected = selectBuffer[4 * i + 3]; 
      } 
     } 

    } else selected = -1; 

    glPopName(); 
    glPopMatrix(); 
    glFlush(); 
} 

我应该在这一点上,我的工作请注意完全在C中。再一次,所有这些工作都很好。最近的对象被选择正确(我知道这是因为我使用selected变量在我的渲染函数中为当前选中的对象着色。但是这些信息并不足够,因为基于此,屏幕中心的指针可能指向任何一个对象的脸部。我希望能够选择对象上的个人脸部,同时也能够识别对象本身被选中。到目前为止,我尝试的两件事是:1)使用glPushNameglPopName而不是glLoadName来绘制pickObject函数中的每个对象,然后对drawObject函数中的每个单独的面具有glPushNameglPopName,但是没有得到结果我想,并且2)制作一个完全独立的函数pickFace,我在pickObject函数后面运行。它做同样的事情,但只渲染当前选定的对象并设置变量selectedFace而不是selected。我的猜测是,这是实现我想要的最低效的方式,但是,尽管它有效,但我想知道是否有更好的选择。

回答

0

嗯,这个答案实际上让我收费相当愚蠢张贴它,因为这是一个简单的修复,我以某种方式保持俯瞰。如果我已经更正了从后面选择缓冲区中检索ID的方式,那么为每个对象使用glPushNameglPopName。所以drawObject功能变成这样:

void drawObject(int i) 
{ 
    glPushName(0); 
    renderFace0(i); 
    glPopName(); 

    glPushName(1); 
    renderFace1(i); 
    glPopName(); 

    glPushName(2); 
    renderFace2(i); 
    glPopName(); 

    glPushName(3); 
    renderFace3(i); 
    glPopName(); 
} 

而对于“pickObject”功能更正为:

int i; 
for(i = 0; i < NUM_OBJECTS; i ++) 
{ 
    glPushName(i); 
    drawObject(i); 
    glPopName(); 
} 

hits = glRenderMode(GL_RENDER); 
if(hits > 0) 
{ 
    int znear; 
    znear = selectBuffer[2]; 
    selected = selectBuffer[3]; 
    selectedFace = selectBuffer[4]; 

    for(i = 1; i < hits; i ++) 
    { 
     if(selectBuffer[5 * i + 2] > znear) 
     { 
      znear = selectBuffer[5 * i + 2]; 
      selected = selectBuffer[5 * i + 3]; 
      selectedFace = selectBuffer[5 * i + 4]; 
     } 
    } 

} else selected = -1; 

最大的变化我错过了在索引发生了变化i * 4i * 5,因为自从我m在每个选择中寻找两个名字,选择缓冲区将被排列如下:{number of names hit, far value, near value, first name, second name, ...}然后重复该模式。所以我的步长必须从4更改为5,因为每次命中时有两个名字,现在每个命中选择缓冲区中有5个数据值,而不是4个。

相关问题