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);
    }
} 
4

2 回答 2

1

It's not entirely clear what you're asking for. If you mean you're only getting a hit record for the object that's front-most, then that's kind of expected. Polygon(s) that are culled won't generate any hit record(s). If you want hit records for polygons that would normally be culled, you'll want to use glDisable(GL_CULL_FACE); while you do the drawing in selection mode. This prevents polygons from being culled, so they can produce hit records.

于 2009-11-19T23:48:12.930 回答
0

在此处阅读有关使用后台缓冲区进行对象选择的内容。我实施过一次,效果很好。

于 2009-11-21T01:01:26.003 回答