2009-11-19 96 views
3

我正尝试创建一个3D机器人,它应该在点击某些身体部位时执行某些操作。我已经成功(有点)实施选择,如果你点击任何X平面部分,它会注册一个命中,但不是其他任何地方。也就是说,它没有记录深度,如果你点击它的方头,你只能通过点击头部(面对你)来注册一个命中。显然,我并不完全理解挑选和选择问题,而是懒洋洋地尝试将我所了解的2D选择转化为3D(我的老师和岩石一样有帮助),但我已经放弃了某些东西,或者没有改变与深度有关的东西。谁能帮我吗?这里是相关的功能。OpenGL 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); 
    } 
} 
+0

你是什么意思,你只能在面对你的机器人头上注册点击?你如何点击一些没有面对你的东西(即不会被遮挡)。 – Jherico 2009-11-19 23:02:02

+2

+1在早上1时好笑:“我的老师和岩石一样有帮助” – Ricket 2009-12-07 05:59:49

回答

1

这不是完全清楚你问什么。如果你的意思是你只能得到最前面的对象的记录,那么这是预期的。被剔除的多边形不会生成任何命中记录。如果要打击通常会被剔除的多边形记录,则在选择模式下执行绘图时,您需要使用glDisable(GL_CULL_FACE);。这可以防止多边形被剔除,因此可以产生重要记录。

0

阅读关于使用回缓冲区选择对象here。我曾经实施过一次,效果很好。