OpenGL 3D选择

3
我正在尝试创建一个3D机器人,当单击某些身体部位时,应该执行某些动作。我已经成功(有点)实现了拾取功能,即如果您单击任何x平面部分,则会注册命中,但其他地方不行。也就是说,它没有注册深度,并且如果您单击其正方形头部,只能通过单击头部前面(面向您)来注册命中。显然,我并不完全理解选取和选择,并且在试图将我对2D选择的了解转录到3D时很粗心大意(我的老师像一块石头一样有用),但我漏掉了某些内容或者没有改变与深度相关的某些内容。有人可以帮助我吗?以下是相关函数。
void processHits (GLint hits, GLuint buffer[])
{
    unsigned int i, j;
    GLint n, *ptr;

    printf ("hits = %d\n", hits);
    ptr = (GLint *) buffer;

    //For each hit.
    for (i = 0; i < hits; i++)
    {
        n = *ptr;       //Number of names under current hit.
        ptr+=3;         //Bypass three integers: n, z1, z2.
        printf ("hit %d has %d name(s)\n", i, n);

        //For each name.
        for (j = 0; j < n; j++)
        {
            if(*ptr==1) printf ("Body hit.\n");
            else if(*ptr==2) printf ("Right shoulder hit.\n");
            else if(*ptr==3) printf ("Left shoulder hit.\n");
            else if(*ptr==4) printf ("Left arm hit.\n");
            else if(*ptr==5) printf ("Right arm hit.\n");
            else if(*ptr==6) printf ("Left leg hit.\n");
            else if(*ptr==7) printf ("Right leg hit.\n");
            else if(*ptr==8) printf ("Right foot hit.\n");
            else if(*ptr==9) printf ("Left foot hit.\n");
            else if(*ptr==10) printf ("Neck hit.\n");
            else if(*ptr==11) printf ("Head hit.\n");
            else printf ("Nothing hit.\n");

            ptr++;
        }
        printf ("\n");
    }
}

void selection(int mouse_x, int mouse_y)
{
    GLuint buffer[512];                     //Set up a selection buffer.
    GLint hits;                             //The number of objects we selected.
    GLint viewport[4];                      //Viewport size. [0] Is <x>, [1] Is <y>, [2] Is <length>, [3] Is <width>.

    glGetIntegerv(GL_VIEWPORT, viewport);   //Sets the array <viewport> to size and location of screen relative to window.
    glSelectBuffer(512, buffer);            //Tell OpenGL to use our array for selection.

    glRenderMode(GL_SELECT);                //Puts OpenGL in selection mode. Nothing will be drawn. Object IDs and extents stored in buffer.

    glInitNames();                          //Initializes name stack.
    glPushName(0);                          //Push an entry onto the stack.

    glMatrixMode(GL_PROJECTION);            //Selects the projection matrix.
    glPushMatrix();                         //Push the projection matrix.
    glLoadIdentity();                       //Resets matrix.

    //This creates a matrix that will zoom up to a small portion of the screen, where the mouse is.
    gluPickMatrix((GLdouble) mouse_x, (GLdouble) (viewport[3]-mouse_y), 0.01, 0.01, viewport);

    gluPerspective(45.0f, (GLfloat) (viewport[2]-viewport[0])/(GLfloat) (viewport[3]-viewport[1]), 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);                                 //Select the modelview matrix.
    drawObjects(GL_SELECT);                                     //Render the targets to the selection buffer.
    glMatrixMode(GL_PROJECTION);                                //Select the projection matrix.
    glPopMatrix();                                              //Pop the projection matrix.
    glMatrixMode(GL_MODELVIEW);                                 //Select the modelview matrix.
    hits = glRenderMode(GL_RENDER);
    processHits (hits, buffer);

    //printf("%d ", hits);

    //Post redisplay message.
    glutPostRedisplay();
}

void mouse(int button, int state, int x, int y)
{    
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        selection(x, y);
    }
} 

你的意思是说只有在机器人头部朝向你的情况下才能注册点击吗?那么如果某个部位没有朝向你,你该如何进行点击呢(比如说它不会被遮挡)? - Jherico
2
晚上1点开心一笑:「我的老师像块石头一样没什么用」。 - Ricket
2个回答

1

你的问题并不是完全清楚。如果你的意思是只有最前面的对象才会产生命中记录,那么这是可以预料的。被剔除的多边形不会生成任何命中记录。如果你想要得到通常会被剔除的多边形的命中记录,你需要在选择模式下绘制时使用glDisable(GL_CULL_FACE);。这将防止多边形被剔除,因此它们可以产生命中记录。


0

讀取有關使用背景緩衝區進行對象選擇的文檔 這裡。我曾實現過一次,效果非常好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接