Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl 光线拾取的轨迹球问题_Opengl_Picking_Trackball_Ray Picking - Fatal编程技术网

Opengl 光线拾取的轨迹球问题

Opengl 光线拾取的轨迹球问题,opengl,picking,trackball,ray-picking,Opengl,Picking,Trackball,Ray Picking,我正在尝试在OpenGL场景中开发3D光线拾取 我有一个带轨迹球的OBJ装载机 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;

我正在尝试在OpenGL场景中开发3D光线拾取

我有一个带轨迹球的OBJ装载机

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 convert2dto3D(int mouseX, int mouseY){
    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)mouseX; 
    double winY = viewport[3] - (double)mouseY; 

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

    //printf("Coordinata 2D %d %d\nCoordinata camera far: %f %f %f\n", mouseX, mouseY, m_end.x, m_end.y, m_end.z);
    //printf("Coordinate camera near: %f %f %f\n", m_start.x, m_start.y, m_start.z);
    //fflush(stdout);

    mouseClicked = GL_TRUE;

    Vector3d nearPoint(m_start.x, m_start.y, m_start.z);
    Vector3d farPoint(m_end.x, m_end.y, m_end.z);

    Vector3d ray = farPoint - nearPoint;

}

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;
}
以下是轨迹球的功能:

     /*
     *  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();
    }
/*
*从projtex.c改编(撕下)的简单轨迹球般的运动
*(由David Yu和David Blythe撰写)。参见1996年的SIGGRAPH
*高级OpenGL课程笔记。
*/
#包括
#包括
#包括
#包括
#包括“gltb.h”
#定义GLTB\u时间\uε10
静态胶合gltb_上次;
静态GLfloat gltb_lastposition[3];
静态GLfloat gltb_角度=0.0;
静态gltb_轴[3];
静态GLfloat-gltb_变换[4][4];
静态胶合gltb_宽度;
静态胶接高度;
静态闪烁gltb_按钮=-1;
静态gltb\U跟踪=GLU FALSE;
静态gltb\u animate=GL\u TRUE;
静态空隙
_gltbPointToVector(整数x,整数y,整数宽度,整数高度,浮点v[3])
{
浮动d,a;
/*将x、y投影到以宽度、高度为中心的半球上*/
v[0]=(2.0*x-宽度)/宽度;
v[1]=(高度-2.0*y)/高度;
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;
}
静态空隙
_gltbAnimate(无效)
{
再发现();
}
无效的
_gltbStartMotion(整数x、整数y、整数按钮、整数时间)
{
断言(gltb_按钮!=-1);
gltb_跟踪=GL_真;
gltb_lasttime=时间;
_gltbPointToVector(x,y,gltb_宽度,gltb_高度,gltb_最后位置);
}
无效的
_gltbStopMotion(整数按钮,无符号时间)
{
断言(gltb_按钮!=-1);
gltb_跟踪=GL_假;
if(time-gltb\u lasttime
如果我在开始时投射光线(CTRL+左键单击),它将与正确的三维远点和近点一起工作 如果我旋转对象(使用轨迹球),光线不会使用真实的眼睛/远点,我也不知道为什么。
我尝试用GluLookAt代替glRotatef,但我不知道如何像这个轨迹球那样用鼠标移动相机。

解决了:问题是display()中开始/结束处的pushMatrix()/popMatrix()