Jump to content
Site Stability Read more... ×
  • Advertisement
Sign in to follow this  
jorgechp

OpenGL Picking and selecting objects

This topic is 2083 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi.

I'm learning how to make OpenGL to interact with the user through the mouse. I've followed this guide:

http://www.glprogramming.com/red/chapter13.html#name1

But I can't get my code to work. This is my pick() function:
 

void pick(int x, int y)

{

       GLuint selectBuf[BUFSIZE];

   GLint hits;

   GLint viewport[4];





   glGetIntegerv (GL_VIEWPORT, viewport);



   glSelectBuffer (BUFSIZE, selectBuf);

   (void) glRenderMode (GL_SELECT);



   glInitNames();

   glPushName(0);



   glMatrixMode (GL_PROJECTION);

   glPushMatrix ();

   glLoadIdentity ();

/*  create 5x5 pixel picking region near cursor location      */

   gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y),

                  5.0, 5.0, viewport);

   gluOrtho2D (0.0, 1.0, 0.0, 1.0);



[B]   draw_malla(GL_SELECT);[/B]



   glMatrixMode (GL_PROJECTION);

   glPopMatrix ();

   glFlush ();



   hits = glRenderMode (GL_RENDER);

   cout << hits << endl;

  // processHits (hits, selectBuf);

   glutPostRedisplay();



}

Which calls to "draw_malla()"
 

draw_malla(GLenum mode){

   if (mode == GL_SELECT)

      glLoadName(1);

   glBegin(GL_QUADS);

   glColor3f(1.0, 1.0, 0.0);

   glVertex3f(0.2, 0, 0);

   glVertex3f(0.2, 0.6, 0);

   glVertex3f(0.6, 0.6, 0);

   glVertex3f(0.6, 0.0, 0);

   glEnd();

}

When I execute, a square is drawn on the windows but when I click on it, no hits are register.

This is my complete code:




#include "stdlib.h"

#include "stdio.h"

#include <GL/glut.h>

#include <ctype.h>

#include "user_code.h"

#include "file_ply_stl.h"

#include "vertex.h"

#include <iostream>



using namespace std;



// taman?o de los ejes

const int AXIS_SIZE=5000;



int modo = 0;

bool estadoRaton;

int xc,yc;



// variables que definen la posicion de la camara en coordenadas polares

GLfloat Observer_distance;

GLfloat Observer_angle_x;

GLfloat Observer_angle_y;



Draw *d;



// variables que controlan la ventana y la transformacion de perspectiva

GLfloat Window_width,Window_height,Front_plane,Back_plane;



// variables que determninan la posicion y taman?o de la ventana X

int UI_window_pos_x=50,UI_window_pos_y=50,UI_window_width=500,UI_window_height=500;

vector<Punto> vectorFinalE;

vector<Cara> vectorCarasE;









// Process hit buffer to find record with smallest min-z value.

void findClosestHit(int hits, unsigned int buffer[])

{

    int highlightFrames;

   unsigned int closestName;

   unsigned int *ptr, minZ;

   

   minZ= 0xffffffff; // 2^32 - 1

   ptr = buffer;

   closestName = 0;

   for (int i = 0; i < hits; i++)                    

   {

      ptr++;

      if (*ptr < minZ)

      {

         minZ = *ptr;

         ptr += 2;

         closestName = *ptr;

         ptr++;

      }

      else ptr += 3;

   }

   if (closestName != 0) highlightFrames = 10;

}





void draw_malla(GLenum mode){



    if(mode == GL_SELECT)

        glLoadName(1);

   glBegin(GL_QUADS);

   glColor3f(1.0, 1.0, 0.0);

   glVertex3f(0.2, 0, 0);

   glVertex3f(0.2, 0.6, 0);

   glVertex3f(0.6, 0.6, 0);

   glVertex3f(0.6, 0, 0);

   glEnd();

    



    





}



#define BUFSIZE 5120







void ratonMovido(int x, int y){

    int x0 = Observer_angle_x*0.2;

    int y0 = Observer_angle_y *0.2;

    if ( estadoRaton )

        {

            //getCamara( &x0, &y0 );

            int yn = y0+(y-yc) ;

            int xn = x0-(x-xc) ;



            //setCamara( xn, yn );

            Observer_angle_x = yn ; Observer_angle_y = xn ;

            glutPostRedisplay();

        }

}









void clear_window()

{



glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

}



void change_projection()

{



glMatrixMode(GL_PROJECTION);

glLoadIdentity();



// formato(x_minimo,x_maximo, y_minimo, y_maximo,Front_plane, plano_traser)

//  Front_plane>0  Back_plane>PlanoDelantero)

glFrustum(-Window_width,Window_width,-Window_height,Window_height,Front_plane,Back_plane);

}



void change_observer()

{



// posicion del observador

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glTranslatef(0,0,-Observer_distance);

glRotatef(Observer_angle_x,1,0,0);

glRotatef(Observer_angle_y,0,1,0);

}



void draw_axis()

{

glBegin(GL_LINES);

// eje X, color rojo

glColor3f(1,0,0);

glVertex3f(-AXIS_SIZE,0,0);

glVertex3f(AXIS_SIZE,0,0);

// eje Y, color verde

glColor3f(0,1,0);

glVertex3f(0,-AXIS_SIZE,0);

glVertex3f(0,AXIS_SIZE,0);

// eje Z, color azul

glColor3f(0,0,1);

glVertex3f(0,0,-AXIS_SIZE);

glVertex3f(0,0,AXIS_SIZE);

glEnd();

}











void draw_objects()

{    

        draw_malla(GL_RENDER);

       



    

}







void draw_scene(void)

{



clear_window();

change_observer();

draw_axis();

draw_objects();

glutSwapBuffers();

}











void change_window_size(int Ancho1,int Alto1)

{

change_projection();

glViewport(0,0,Ancho1,Alto1);

glutPostRedisplay();

}









void normal_keys(unsigned char Tecla1,int x,int y)

{



    if (toupper(Tecla1)=='Q') exit(0);

    if (toupper(Tecla1)=='C'){    

        modo = 0;

    }

    if (toupper(Tecla1)=='S'){

        modo = 1;

    }

    if (toupper(Tecla1)=='A'){

        modo = 2;

    }

    glutPostRedisplay();

}







void special_keys(int Tecla1,int x,int y)

{



switch (Tecla1){

    case GLUT_KEY_LEFT:Observer_angle_y--;break;

    case GLUT_KEY_RIGHT:Observer_angle_y++;break;

    case GLUT_KEY_UP:Observer_angle_x--;break;

    case GLUT_KEY_DOWN:Observer_angle_x++;break;

    case GLUT_KEY_PAGE_UP:Observer_distance*=1.2;break;

    case GLUT_KEY_PAGE_DOWN:Observer_distance/=1.2;break;

    }



glutPostRedisplay();

}







void initialize(void)

{

// se inicalizan la ventana y los planos de corte

Window_width=.5;

Window_height=.5;

Front_plane=1;

Back_plane=1000;



// se inicia la posicion del observador, en el eje z

Observer_distance=3*Front_plane;

Observer_angle_x=0;

Observer_angle_y=0;



// se indica cual sera el color para limpiar la ventana    (r,v,a,al)

// blanco=(1,1,1,1) rojo=(1,0,0,1), ...

glClearColor(1,1,1,1);



// se habilita el z-bufer

glEnable(GL_DEPTH_TEST);

change_projection();

glViewport(0,0,UI_window_width,UI_window_height);

}



void pick(int x, int y)

{

       GLuint selectBuf[BUFSIZE];

   GLint hits;

   GLint viewport[4];





   glGetIntegerv (GL_VIEWPORT, viewport);



   glSelectBuffer (BUFSIZE, selectBuf);

   (void) glRenderMode (GL_SELECT);



   glInitNames();

   glPushName(0);



   glMatrixMode (GL_PROJECTION);

   glPushMatrix ();

   glLoadIdentity ();

/*  create 5x5 pixel picking region near cursor location      */

   gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y),

                  5.0, 5.0, viewport);

   gluOrtho2D (0.0, 1.0, 0.0, 1.0);

   draw_malla(GL_SELECT);



   glMatrixMode (GL_PROJECTION);

   glPopMatrix ();

   glFlush ();



   hits = glRenderMode (GL_RENDER);

   cout << hits << endl;

  // processHits (hits, selectBuf);

   glutPostRedisplay();



}





void clickRaton(int button, int state, int x, int y){

    if ( button == GLUT_RIGHT_BUTTON )

        { if ( state == GLUT_DOWN )

            {

                estadoRaton = true ;

                xc = x ; yc = y ;

            }

        }

    else{

        estadoRaton = false ;

                if(button == GLUT_LEFT_BUTTON ){

                    if(state == GLUT_DOWN)                    

                    {

                        GLuint *i = new GLuint[80];

                        pick(x,y);

                    }

                }

    }



}





int main(int argc, char **argv)

{



    // se llama a la inicializacio?n de glut

    glutInit(&argc, argv);



    // se indica las caracteristicas que se desean para la visualizacio?n con OpenGL

    // Las posibilidades son:

    // GLUT_SIMPLE -> memoria de imagen simple

    // GLUT_DOUBLE -> memoria de imagen doble

    // GLUT_INDEX -> memoria de imagen con color indizado

    // GLUT_RGB -> memoria de imagen con componentes rojo, verde y azul para cada pixel

    // GLUT_RGBA -> memoria de imagen con componentes rojo, verde, azul y alfa para cada pixel

    // GLUT_DEPTH -> memoria de profundidad o z-bufer

    // GLUT_STENCIL -> memoria de estarcido

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);



    // posicion de la esquina inferior izquierdad de la ventana

    glutInitWindowPosition(UI_window_pos_x,UI_window_pos_y);



    // taman?o de la ventana (ancho y alto)

    glutInitWindowSize(UI_window_width,UI_window_height);



    // llamada para crear la ventana, indicando el titulo (no se visualiza hasta que se llama

    // al bucle de eventos)

    glutCreateWindow("Pra?ctica 1");



    // asignacio?n de la funcion llamada "dibujar" al evento de dibujo

    glutDisplayFunc(draw_scene);

    // asignacio?n de la funcion llamada "cambiar_tamanio_ventana" al evento correspondiente

    glutReshapeFunc(change_window_size);

    // asignacio?n de la funcion llamada "tecla_normal" al evento correspondiente

    glutKeyboardFunc(normal_keys);

    // asignacio?n de la funcion llamada "tecla_Especial" al evento correspondiente

    glutSpecialFunc(special_keys);



    // funcion de inicializacio?n

    initialize();

    glutMouseFunc( clickRaton );

    glutMotionFunc( ratonMovido );



    // inicio del bucle de eventos

    glutMainLoop();

    delete d;

    return 0;

}





I think that this is the part which is wrong
 

   glPushMatrix ();

   glLoadIdentity ();

/*  create 5x5 pixel picking region near cursor location      */

   gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y),

                  5.0, 5.0, viewport);

   gluOrtho2D (0.0, 1.0, 0.0, 1.0);



[B]   draw_malla(GL_SELECT);[/B]



   glMatrixMode (GL_PROJECTION);

   glPopMatrix ();

But I don't have any idea about what's happening.

Thanks!

 

Share this post


Link to post
Share on other sites
Advertisement

While I can't help with your code (I only ever learned modern OpenGL), I can offer different tutorials on picking. The first tutorial linked is the method I think makes the most sense (using collision objects). It should also have full source. If the idea appeals to you, you can even learn it from non-OpenGL tutorials since it's tied to your physics library instead of OpenGL. The other tutorials I linked might be more tightly tied to OpenGL.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!