Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: Trackball issue with Raypicking

Threaded View

  1. #1
    Junior Member Newbie
    Join Date
    Oct 2013
    Posts
    4

    Trackball issue with Raypicking

    I'm trying to develop a 3D raypicking in my OpenGL scene.

    I have a working OBJ loader with a trackball.

    Code :
    char*      model_file = NULL;       /* name of the obect file */
    GLuint     model_list = 0;      /* display list for object */
    GLMmodel*  model;               /* glm model data structure */
    GLfloat    scale;               /* original scale factor */
    GLfloat    smoothing_angle = 90.0;  /* smoothing angle */
    GLfloat    weld_distance = 0.00001; /* epsilon for welding vertices */
    GLboolean  facet_normal = GL_FALSE; /* draw with facet normal? */
    GLboolean  bounding_box = GL_FALSE; /* bounding box on? */
    GLboolean  spheres = GL_FALSE;
    GLboolean  performance = GL_FALSE;  /* performance counter on? */
    GLboolean  stats = GL_FALSE;        /* statistics on? */
    GLuint     material_mode = 0;       /* 0=none, 1=color, 2=material, 3=texture */
    GLint      entries = 0;         /* entries in model menu */
    GLdouble   pan_x = 0.0;
    GLdouble   pan_y = 0.0;
    GLdouble   pan_z = 0.0;
    char texnames[1][64] = {"foto_rgb.ppm"};
    //char texnames[1][64] = {"grid.ppm"};
    GLint w,h;
    GLubyte* texture;
     
     
     
    void line (void) {
     
        glLineWidth(10);
        //glPointSize(50.2);
        glColor3f(0.0f, 1.0f, 0.0f);      
        glBegin(GL_LINES);
            glVertex3f( m_start.x, m_start.y, m_start.z );
            glVertex3f( m_end.x, m_end.y, m_end.z );
        glEnd();
        glColor3f(1.0f,1.0f,1.0f);
        glLineWidth(1);
     
    }
     
     
    void lists(void){
        GLfloat ambient[] = { 0.2, 0.2, 0.2, 1.0 };
        GLfloat diffuse[] = { 0.8, 0.8, 0.8, 1.0 };
        GLfloat specular[] = { 0.0, 0.0, 0.0, 1.0 };
        GLfloat shininess = 65.0;
     
        glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
        glMaterialf(GL_FRONT, GL_SHININESS, shininess);
     
        if (model_list)
            glDeleteLists(model_list, 1);
     
        glDisable(GL_TEXTURE_2D);
        /* generate a list */
        switch (material_mode)
        {
         case 0:
            if (facet_normal)
                model_list = glmList(model, GLM_FLAT);
            else
                model_list = glmList(model, GLM_SMOOTH);
         break;
         case 1:
            if (facet_normal)
                model_list = glmList(model, GLM_FLAT | GLM_COLOR);
            else
                model_list = glmList(model, GLM_SMOOTH | GLM_COLOR);
         break;
         case 2:
            if (facet_normal)
                model_list = glmList(model, GLM_FLAT | GLM_MATERIAL);
            else
                model_list = glmList(model, GLM_SMOOTH | GLM_MATERIAL);
         break;
         case 3:
            glEnable(GL_TEXTURE_2D);
            model_list = glmList(model, GLM_TEXTURE);
    //        glDisable(GL_TEXTURE_2D);
         break;
        }
    }
     
    void init(void){
        gltbInit(GLUT_LEFT_BUTTON);
     
        /* read in the model */
        model = glmReadOBJ(model_file);
        scale = glmUnitize(model);
        glmFacetNormals(model);
        glmVertexNormals(model, smoothing_angle);
     
        if (model->nummaterials > 0)
            material_mode = 2;
     
        /* create new display lists */
        lists();
     
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
        glEnable(GL_DEPTH_TEST);
    }
     
    void reshape(int width, int height){
        gltbReshape(width, height);
     
        glViewport(0, 0, width, height);
     
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(60.0, (GLfloat)height / (GLfloat)width, 1.0, 128.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0, 0.0, -3.0);
    }
     
    void display(void){
        static char s[256], t[32];
        static char* p;
        static int frames = 0;
        int i=0,j=0;
     
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
        glPushMatrix();
     
        glTranslatef(pan_x, pan_y, 0.0);
     
        gltbMatrix();
     
        if(mouseClicked){
            line();
        }
     
        glCallList(model_list);
     
        glPopMatrix();
     
        glutSwapBuffers();
        glEnable(GL_LIGHTING);
    }
     
    static GLint      mouse_state;
    static GLint      mouse_button;
     
    void mouse(int button, int state, int x, int y){
        GLdouble model_project[4*4];
        GLdouble proj[4*4];
        GLint view[4];
     
        /* fix for two-button mice -- left mouse + shift = middle mouse */
        if (button == GLUT_LEFT_BUTTON && glutGetModifiers() & GLUT_ACTIVE_SHIFT)
            button = GLUT_MIDDLE_BUTTON;
     
        gltbMouse(button, state, x, y);
     
        mouse_state = state;
        mouse_button = button;
     
        if (state == GLUT_DOWN && button == GLUT_MIDDLE_BUTTON) {
            glGetDoublev(GL_MODELVIEW_MATRIX, model_project);
            glGetDoublev(GL_PROJECTION_MATRIX, proj);
            glGetIntegerv(GL_VIEWPORT, view);
     
            gluProject((GLdouble)x, (GLdouble)y, 0.0,
                model_project, proj, view,
                &pan_x, &pan_y, &pan_z);
            gluUnProject((GLdouble)x, (GLdouble)y, pan_z,
                model_project, proj, view,
                &pan_x, &pan_y, &pan_z);
            pan_y = -pan_y;
        }
     
        if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && glutGetModifiers() & GLUT_ACTIVE_CTRL) {
            convert2dto3D(x,y);
        }
        else if(button == GLUT_WHEEL_UP){ // Wheel up
            glmScale(model, 1.25);
            lists();
        }
        else if(button == GLUT_WHEEL_DOWN){ // Wheel down
            glmScale(model, 0.8);
            lists();
        }
     
        glutPostRedisplay();
    }
     
    void motion(int x, int y){
        GLdouble model[4*4];
        GLdouble proj[4*4];
        GLint view[4];
     
        gltbMotion(x, y);
     
     
        glutPostRedisplay();
    }
     
    int main(int argc, char** argv){
        int buffering = GLUT_DOUBLE;
        struct dirent* direntp;
        DIR* dirp;
        int models;
     
        glutInitWindowSize(512, 512);
        glutInit(&argc, argv);
     
        while (--argc) {
            if (strcmp(argv[argc], "-sb") == 0)
                buffering = GLUT_SINGLE;
            else
                model_file = argv[argc];
        }
     
        if (!model_file) {
    //        model_file = "data/dolphins.obj";
            model_file = "data/boeing_2.obj";
        }
     
        glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | buffering);
        glutCreateWindow("Smooth");
     
        glutReshapeFunc(reshape);
        glutDisplayFunc(display);
        glutKeyboardFunc(keyboard);
        glutMouseFunc(mouse);
        glutMotionFunc(motion);
     
    /* Image data packed tightly. */
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     
        textures();
     
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    //    glEnable(GL_TEXTURE_2D);
     
        models = glutCreateMenu(menu);
        dirp = opendir(DATA_DIR);
        if (!dirp) {
            fprintf(stderr, "%s: can't open data directory.\n", argv[0]);
        } else {
            while ((direntp = readdir(dirp)) != NULL) {
                if (strstr(direntp->d_name, ".obj")) {
                    entries++;
                    glutAddMenuEntry(direntp->d_name, -entries);
                }
            }
            closedir(dirp);
        }
     
     
        init();
     
        glutMainLoop();
        return 0;
    }

    Code :
    void convert2dto3D(int xMouse, int YMouse){
        double matModelView[16], matProjection[16]; 
        int viewport[4]; 
     
        glGetDoublev( GL_MODELVIEW_MATRIX, matModelView ); 
        glGetDoublev( GL_PROJECTION_MATRIX, matProjection ); 
        glGetIntegerv( GL_VIEWPORT, viewport );
     
        double winX = (double)xMouse; 
        double winY = viewport[3] - (double)YMouse; 
        gluUnProject(winX, winY, 0.0, matModelView, matProjection, viewport, &m_start.x, &m_start.y, &m_start.z); 
        gluUnProject(winX, winY, 1.0, matModelView, matProjection,  viewport, &m_end.x, &m_end.y, &m_end.z);
        mouseClicked = GL_TRUE;
     
    }

    Here trackball's functions:

    Code :
    /*
         *  Simple trackball-like motion adapted (ripped off) from projtex.c
         *  (written by David Yu and David Blythe).  See the SIGGRAPH '96
         *  Advanced OpenGL course notes.
         */
     
     
        #include <math.h>
        #include <stdio.h>
        #include <assert.h>
        #include <GL/glut.h>
        #include "gltb.h"
     
     
        #define GLTB_TIME_EPSILON  10
     
     
        static GLuint    gltb_lasttime;
        static GLfloat   gltb_lastposition[3];
     
        static GLfloat   gltb_angle = 0.0;
        static GLfloat   gltb_axis[3];
        static GLfloat   gltb_transform[4][4];
     
        static GLuint    gltb_width;
        static GLuint    gltb_height;
     
        static GLint     gltb_button = -1;
        static GLboolean gltb_tracking = GL_FALSE;
        static GLboolean gltb_animate = GL_TRUE;
     
     
        static void
        _gltbPointToVector(int x, int y, int width, int height, float v[3])
        {
          float d, a;
     
          /* project x, y onto a hemi-sphere centered within width, height. */
          v[0] = (2.0 * x - width) / width;
          v[1] = (height - 2.0 * y) / height;
          d = sqrt(v[0] * v[0] + v[1] * v[1]);
          v[2] = cos((3.14159265 / 2.0) * ((d < 1.0) ? d : 1.0));
          a = 1.0 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
          v[0] *= a;
          v[1] *= a;
          v[2] *= a;
        }
     
        static void
        _gltbAnimate(void)
        {
          glutPostRedisplay();
        }
     
        void
        _gltbStartMotion(int x, int y, int button, int time)
        {
          assert(gltb_button != -1);
     
          gltb_tracking = GL_TRUE;
          gltb_lasttime = time;
          _gltbPointToVector(x, y, gltb_width, gltb_height, gltb_lastposition);
        }
     
        void
        _gltbStopMotion(int button, unsigned time)
        {
          assert(gltb_button != -1);
     
          gltb_tracking = GL_FALSE;
     
          if (time - gltb_lasttime < GLTB_TIME_EPSILON && gltb_animate) {
              glutIdleFunc(_gltbAnimate);
          } else {
            gltb_angle = 0;
            if (gltb_animate)
              glutIdleFunc(0);
          }
        }
     
        void
        gltbAnimate(GLboolean animate)
        {
          gltb_animate = animate;
        }
     
        void
        gltbInit(GLuint button)
        {
          gltb_button = button;
          gltb_angle = 0.0;
     
          /* put the identity in the trackball transform */
          glPushMatrix();
          glLoadIdentity();
          glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)gltb_transform);
          glPopMatrix();
        }
     
        void
        gltbMatrix(void)
        {
          assert(gltb_button != -1);
     
          glPushMatrix();
          glLoadIdentity();
          glRotatef(gltb_angle, gltb_axis[0], gltb_axis[1], gltb_axis[2]);
          glMultMatrixf((GLfloat*)gltb_transform);
          glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)gltb_transform);
          glPopMatrix();
     
          glMultMatrixf((GLfloat*)gltb_transform);
        }
     
        void
        gltbReshape(int width, int height)
        {
          assert(gltb_button != -1);
     
          gltb_width  = width;
          gltb_height = height;
        }
     
        void
        gltbMouse(int button, int state, int x, int y)
        {
          assert(gltb_button != -1);
     
          if (state == GLUT_DOWN && button == gltb_button)
            _gltbStartMotion(x, y, button, glutGet(GLUT_ELAPSED_TIME));
          else if (state == GLUT_UP && button == gltb_button)
            _gltbStopMotion(button, glutGet(GLUT_ELAPSED_TIME));
        }
     
        void
        gltbMotion(int x, int y)
        {
          GLfloat current_position[3], dx, dy, dz;
     
          assert(gltb_button != -1);
     
          if (gltb_tracking == GL_FALSE)
            return;
     
          _gltbPointToVector(x, y, gltb_width, gltb_height, current_position);
     
          /* calculate the angle to rotate by (directly proportional to the
             length of the mouse movement) */
          dx = current_position[0] - gltb_lastposition[0];
          dy = current_position[1] - gltb_lastposition[1];
          dz = current_position[2] - gltb_lastposition[2];
          gltb_angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz);
     
          /* calculate the axis of rotation (cross product) */
          gltb_axis[0] = gltb_lastposition[1] * current_position[2] - 
                       gltb_lastposition[2] * current_position[1];
          gltb_axis[1] = gltb_lastposition[2] * current_position[0] - 
                       gltb_lastposition[0] * current_position[2];
          gltb_axis[2] = gltb_lastposition[0] * current_position[1] - 
                       gltb_lastposition[1] * current_position[0];
     
          /* XXX - constrain motion */
          gltb_axis[2] = 0;
     
          /* reset for next time */
          gltb_lasttime = glutGet(GLUT_ELAPSED_TIME);
          gltb_lastposition[0] = current_position[0];
          gltb_lastposition[1] = current_position[1];
          gltb_lastposition[2] = current_position[2];
     
          /* remember to draw new position */
          glutPostRedisplay();
        }

    If I cast a ray (CTRL + Left_click) at the beginning It works with correct 3D far_point and near_point

    Image:

    If I rotate the object (use Trackball), the ray doesn't use real eye/far points and I can't figure out why.

    Image:

    I've tried with GluLookAt instead of glRotatef, but I can't figure out how to move camera with mouse like this trackball does.
    Last edited by Dark Photon; 01-25-2014 at 04:43 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •