С++/OpenGL конвертировать мировые коорды в экранные (2D) координаты

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

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

Matrix projectionMatrix;
Matrix viewMatrix;
Vector3 point3D;

Ответ 1

Чтобы сделать это преобразование, вы должны сначала взять свои позиции в пространстве модели и преобразовать их в пространство клипа. Это делается с умножением матрицы. Я буду использовать код в стиле GLSL, чтобы было очевидно, что я делаю:

vec4 clipSpacePos = projectionMatrix * (viewMatrix * vec4(point3D, 1.0));

Обратите внимание, как я преобразую ваш 3D-вектор в вектор 4D перед умножением. Это необходимо, потому что матрицы 4x4, и вы не можете умножить матрицу 4x4 с 3D-вектором. Вам нужен четвертый компонент.

Следующим шагом будет преобразование этой позиции из пространства кликов в нормализованное координатное пространство устройства (пространство NDC). Пространство NDC находится на расстоянии [-1, 1] во всех трех осях. Это делается путем деления первых трех координат на четвертое:

vec3 ndcSpacePos = clipSpacePos.xyz / clipSpacePos.w;

Очевидно, что если clipSpacePos.w равно нулю, у вас есть проблема, поэтому вы должны это проверить заранее. Если оно равно нулю, это означает, что объект находится в плоскости проекции; глубина его просмотра равна нулю. И такие вершины автоматически обрезаются OpenGL.

Следующим шагом будет преобразование из этого пространства [-1, 1] в координаты окна. Для этого необходимо использовать значения, которые вы передали в glViewport. Первыми двумя параметрами являются смещение от нижнего левого угла окна (vec2 viewOffset), а во втором - ширина/высота области области просмотра (vec2 viewSize). Учитывая это, позиция окна-пространства:

vec2 windowSpacePos = ((ndcSpacePos.xy + 1.0) / 2.0) * viewSize + viewOffset;

И что ты хочешь. Помните: оконное пространство OpenGL относится к нижнему левому краю окна, а не к левому верхнему краю.