Получение ModelView и проекционных матриц в Opengl 2.x [C++]

Я знаю, что Stackru полон похожих вопросов ( вроде того или другого), но приведенные решения, похоже, не работают для меня. Моя цель - использовать gluProject получить координаты экрана некоторой точки из 3D-пространства. До этого я должен получить матрицы, выполнив следующие действия:

GLint view[4]={0};
GLdouble proj[16]={0};
GLdouble model[16]={0};

glGetDoublev(GL_PROJECTION_MATRIX,proj);
glGetDoublev(GL_MODELVIEW_MATRIX,model);
glGetIntegerv(GL_VIEWPORT,view);

Знание этих трех позволяет вычислить экранные координаты точки. Однако, когда я вызываю эти функции, я получаю странные результаты:

VIEWPORT
       0                0                1366               768

PROJECTION
-536 870 912     1 073 460 858           0                  0
      0                0           -536 870 912       1 073 460 858
      0                0                 0                  0
      0                0                 0                  0

MODELVIEW
    1 073 741 824     1 073 741 824       -1 073 741 824         1 071 119 123
          0                0               1 073 741 824         1 072 511 075
   -1 073 741 824     1 072 523 682              0              -1 077 637 615
   -2 147 483 648    -1 069 923 613              0              -1 071 413 844

Матрицы создаются с использованием gluPerspective а также gluLookAt, Окно просмотра, очевидно, является правильным, но матрицы ошибочны не только из-за их значений, которые не кажутся мне нормальными, но и из-за распределения значений по элементам матриц (см., Что элемент [1,2] Матрица проекции должна быть нулевой, но это не так, тогда как элемент [3,3] равен нулю, и не должен).

Эти странные значения указывают на некоторую проблему в вызове glGet() функции, но я не могу понять это. Я проверил, что я не звоню glGet() между glBegin() а также glEnd(), На самом деле, я звоню glGet() только после правильного рисования некоторых точек и перед правильным рисованием некоторых сфер с использованием тех же матриц ModelView и Projection. Вот большой фрагмент моего кода (вызывающая последовательность main->CheckForPlanetPosition->Planet::GetScreenLocation):

typedef struct position {
  int x,y,z;
};

int main()
{
    glEnable(GL_DEPTH_TEST);
    glViewport(0,0,1366,768);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60,16.0f/9.0f,1,1000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(Camera.x,Camera.y,Camera.z,Camera.cx,Camera.cy,Camera.cz,0,1,0);

    //calls to glEnable

    //some drawing
    glBegin(GL_LINES);
    for(float i=1;i<15;i++)
    {
        glColor4f(0,120.0f/255.0f,210.0f/255.0f,1.0f);

        glVertex3f(0,0.5f,i*100.0f/15.0f);
        glVertex3f(100,0.5f,i*100.0f/15.0f);
        glVertex3f(i*100.0f/15.0f,0.5f,0);
        glVertex3f(i*100.0f/15.0f,0,100);
    }
    glEnd();

    CheckForPlanetsLocation();
    //other stuff...
   return 0;
  }

bool CheckForPlanetsLocation()
{
    position pos;
    pos=SomePlanet.GetScreenLocation();
    //check that the mouse is over the returned region...
}

position Planet::GetScreenLocation()
{
        GLint view[4]={0};
        GLdouble proj[16]={0};
        GLdouble model[16]={0};
        GLdouble x,y,z;

        glGetDoublev(GL_PROJECTION_MATRIX,proj);
        glGetDoublev(GL_MODELVIEW_MATRIX,model);
        glGetIntegerv(GL_VIEWPORT,view);

        gluProject(pos.x,pos.y,pos.z,model,proj,view,&x,&y,&z);
        position res;

        res.x=(int)x;
        res.y=(int)y;
        res.z=(int)z;
        return res;
}

Надеюсь, вы можете помочь мне в этот раз! Заранее спасибо за ваши ответы:)

1 ответ

Решение

Проблема в том, что gluProject ожидает массив типа double пока вы передаете float, Когда он будет повторяться, он будет повторяться, используя размер double, который в два раза больше поплавка! Поэтому он пропустит некоторые элементы и даст вам мусор для других. Поменяйте эти поплавковые массивы с помощью double и используйте glGetDoublev чтобы получить значения, которые вы хотите.

Кроме того, ваш gluPerspective В коде есть небольшая ошибка - 16/9 будет целочисленным до 1 перед передачей в функцию. Это не является причиной ваших проблем проецирования, но хорошо помнить, что целочисленное усечение - это то, что испортит ваши вычисления с плавающей запятой.

Наконец, я стану тем парнем и скажу, что в наши дни обучение OldenGL(как я это называю) приносит больше вреда, чем пользы. Есть много отличных онлайн-уроков для современного OpenGL, таких как эти:

Open.GL

LearnOpenGL

Все, что упоминает OpenGL 2 и выше, это то, что вы хотите.

Другие вопросы по тегам