Я знаю, что StackOverflow полно подобных вопросов (Как этот или же вон тот) но приведенные решения не работают для меня.
Моя цель — использовать 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;
}
Надеюсь, вы сможете помочь мне в этот раз! Заранее спасибо за ваши ответы 🙂
Проблема в том, что gluProject
ожидает массив типа double
пока вы передаете float
, Когда он будет повторяться, он будет повторяться, используя размер double
, который в два раза больше поплавка! Таким образом, он пропустит некоторые элементы и даст вам мусор для других. Поменяйте эти поплавковые массивы с помощью double и используйте glGetDoublev
чтобы получить значения, которые вы хотите.
Кроме того, ваш gluPerspective
в коде есть небольшая ошибка — 16/9 будет целочисленным до 1 до это передано в функцию. Это не является причиной ваших проблем проецирования, но хорошо помнить, что целочисленное усечение — это то, что испортит ваши вычисления с плавающей запятой.
Наконец, я стану этим парнем и скажу, что в наши дни обучение OldenGL (как я это называю) приносит больше вреда, чем пользы. Существует множество отличных онлайн-учебников по современному OpenGL, таких как:
Все, что упоминает OpenGL 2 и выше, это то, что вы хотите.