Дублировать поведение орфографической проекции OpenGL без OpenGL

У меня возникла проблема с попыткой репликации поведения OpenGL в среде без OpenGL.

В основном мне нужно создать SVG файл из списка строк, созданных моей программой. Эти линии создаются с использованием отиграфической проекции.

Я уверен, что эти строки рассчитаны правильно, потому что, если я попытаюсь использовать их с контекстом OpenGL с орфографической проекцией и сохранить результат в изображении, изображение будет правильным.

Проблема возникает, когда я использую точно такие же строки без OpenGL.

Я воспроизвел матрицы проектирования и просмотра OpenGL, и я обрабатываю каждую строку следующим образом:

3D_output_point = projection_matrix * view_matrix * 3D_input_point

а затем я вычисляю его положение (SVG файл) следующим образом:

2D_point_x = (windowWidth / 2) * 3D_point_x + (windowWidth / 2)
2D_point_y = (windowHeight / 2) * 3D_point_y + (windowHeight / 2)

Я вычисляю матрицу отографических проекций следующим образом:

float range = 700.0f;
float l, t, r, b, n, f;

l = -range;
r = range;
b = -range;
t = range;
n = -6000;
f = 8000;

matProj.SetValore(0, 0, 2.0f / (r - l));
matProj.SetValore(0, 1, 0.0f);
matProj.SetValore(0, 2, 0.0f);
matProj.SetValore(0, 3, 0.0f);

matProj.SetValore(1, 0, 0.0f);
matProj.SetValore(1, 1, 2.0f / (t - b));
matProj.SetValore(1, 2, 0.0f);
matProj.SetValore(1, 3, 0.0f);

matProj.SetValore(2, 0, 0.0f);
matProj.SetValore(2, 1, 0.0f);
matProj.SetValore(2, 2, (-1.0f) / (f - n));
matProj.SetValore(2, 3, 0.0f);

matProj.SetValore(3, 0, -(r + l) / (r - l));
matProj.SetValore(3, 1, -(t + b) / (t - b));
matProj.SetValore(3, 2, -n / (f - n));
matProj.SetValore(3, 3, 1.0f);

и матрицу вида следующим образом:

CVettore position, lookAt, up;

position.AssegnaCoordinate(rtRay->m_pCam->Vp.x, rtRay->m_pCam->Vp.y, rtRay->m_pCam->Vp.z);
lookAt.AssegnaCoordinate(rtRay->m_pCam->Lp.x, rtRay->m_pCam->Lp.y, rtRay->m_pCam->Lp.z);
up.AssegnaCoordinate(rtRay->m_pCam->Up.x, rtRay->m_pCam->Up.y, rtRay->m_pCam->Up.z);

up[0] = -up[0];
up[1] = -up[1];
up[2] = -up[2];

CVettore zAxis, xAxis, yAxis;
float length, result1, result2, result3;

// zAxis = normal(lookAt - position)
zAxis[0] = lookAt[0] - position[0];
zAxis[1] = lookAt[1] - position[1];
zAxis[2] = lookAt[2] - position[2];
length = sqrt((zAxis[0] * zAxis[0]) + (zAxis[1] * zAxis[1]) + (zAxis[2] * zAxis[2]));
zAxis[0] = zAxis[0] / length;
zAxis[1] = zAxis[1] / length;
zAxis[2] = zAxis[2] / length;

// xAxis = normal(cross(up, zAxis))
xAxis[0] = (up[1] * zAxis[2]) - (up[2] * zAxis[1]);
xAxis[1] = (up[2] * zAxis[0]) - (up[0] * zAxis[2]);
xAxis[2] = (up[0] * zAxis[1]) - (up[1] * zAxis[0]);
length = sqrt((xAxis[0] * xAxis[0]) + (xAxis[1] * xAxis[1]) + (xAxis[2] * xAxis[2]));
xAxis[0] = xAxis[0] / length;
xAxis[1] = xAxis[1] / length;
xAxis[2] = xAxis[2] / length;

// yAxis = cross(zAxis, xAxis)
yAxis[0] = (zAxis[1] * xAxis[2]) - (zAxis[2] * xAxis[1]);
yAxis[1] = (zAxis[2] * xAxis[0]) - (zAxis[0] * xAxis[2]);
yAxis[2] = (zAxis[0] * xAxis[1]) - (zAxis[1] * xAxis[0]);

// -dot(xAxis, position)
result1 = ((xAxis[0] * position[0]) + (xAxis[1] * position[1]) + (xAxis[2] * position[2])) * -1.0f;

// -dot(yaxis, eye)
result2 = ((yAxis[0] * position[0]) + (yAxis[1] * position[1]) + (yAxis[2] * position[2])) * -1.0f;

// -dot(zaxis, eye)
result3 = ((zAxis[0] * position[0]) + (zAxis[1] * position[1]) + (zAxis[2] * position[2])) * -1.0f;

// Set the computed values in the view matrix.
matView.SetValore(0, 0, xAxis[0]);
matView.SetValore(0, 1, yAxis[0]);
matView.SetValore(0, 2, zAxis[0]);
matView.SetValore(0, 3, 0.0f);

matView.SetValore(1, 0, xAxis[1]);
matView.SetValore(1, 1, yAxis[1]);
matView.SetValore(1, 2, zAxis[1]);
matView.SetValore(1, 3, 0.0f);

matView.SetValore(2, 0, xAxis[2]);
matView.SetValore(2, 1, yAxis[2]);
matView.SetValore(2, 2, zAxis[2]);
matView.SetValore(2, 3, 0.0f);

matView.SetValore(3, 0, result1);
matView.SetValore(3, 1, result2);
matView.SetValore(3, 2, result3);
matView.SetValore(3, 3, 1.0f);

Результаты, полученные из OpenGL и выхода SVG, совершенно разные, но через два дня я не смог найти решение.

Это результат OpenGL enter image description here

И это мой вывод SVG enter image description here

Как вы можете видеть, это вращение не является корневым.

Любая идея, почему? Точки линии одинаковы, и мы надеемся, что и матрицы.


Постановка матриц, которые я создавала, не сработала. Я имею в виду, что матрицы были неправильными, я думаю, потому что OpenGL ничего не показывал. Поэтому я попытался сделать обратное, я создал матрицы в OpenGL и использовал их с моим кодом. Результат лучше, но еще не совершенен.

Теперь я думаю, что я делаю что-то неправильно, отображая 3D-точки в 2D-экранные точки, потому что точки, которые я получаю, инвертированы в Y, и у меня все еще есть некоторые строки, которые не идеально подходят.

Это то, что я получаю от использования OpenGL-матриц и моего предыдущего подхода к отображению 3D-точек в 2D-пространство экрана (это SVG, а не рендеринг OpenGL):

enter image description here


Хорошо, это содержимое матрицы представления, которое я получаю от OpenGL:

enter image description here

Это матрица проекции, которую я получаю от OpenGL:

enter image description here

И это результат, который я получаю с этими матрицами, и, изменив вычисление координат двумерной точки Y, например, bofjas сказал:

enter image description here

Похоже, что некоторые вращения отсутствуют. Моя камера имеет поворот на 30 ° на оси X и Y, и похоже, что они не вычислены правильно.

Теперь я использую те же матрицы, что и OpenGL. Поэтому я думаю, что я делаю неправильные вычисления, когда я сопоставляю 3D-точку в 2D-координатах экрана.

Ответ 1

Вместо отладки собственного кода вы можете использовать преобразовать обратную связь, чтобы вычислить прогнозы ваших линий с использованием конвейера OpenGL. Вместо того, чтобы растрировать их на экране, вы можете захватывать их в буфере памяти и затем сохранять непосредственно в SVG. Настройка этого параметра немного зависит от конкретной настройки вашей кодовой страницы OpenGL, но это может быть более простое решение.

В соответствии с вашим собственным кодом, похоже, что вы либо смешали координаты x и y где-нибудь, либо матрицы строк и столбцов.

Ответ 2

Я решил эту проблему очень простым способом. Поскольку, когда я рисую, используя OpenGL, он работает, я только что создал матрицы в OpenGL, а затем извлек их с помощью glGet(). Используя эти матрицы, все в порядке.

Ответ 3

Вы ищете специализированную версию ортогональных (наклонных) проекций, называемых изометрическими проекциями. Математика действительно проста, если вы хотите знать, что внутри матрицы. Посмотрите Википедию

Ответ 4

OpenGL загружает матрицы в основной колонке (противоположно c++). Например, эта матрица:

[1 ,2 ,3 ,4 ,
 5 ,6 ,7 ,8 ,
 9 ,10,11,12,
 13,14,15,16]

загружает этот путь в память:

|_1 _|
|_5 _|
|_9 _|
|_13_|
|_2 _|
.
.
.

так что я полагаю, вы должны транспонировать эти матрицы из openGL (если вы делаете это по мажорной строке)