Как преобразовать 3D точку в 2D перспективную проекцию?

Я установил Telerik.UI.for.AspNet.Core Nuget Package. Если у кого-то есть другие ответы, не стесняйтесь добавлять ответы. Вероятно, есть несколько решений.

51
задан Bill the Lizard 17 September 2012 в 02:24
поделиться

5 ответов

Я вижу, что этот вопрос немного устарел, но я все равно решил дать ответ тем, кто найдет этот вопрос с помощью поиска.
Стандартный способ представления 2D / 3D преобразований в настоящее время - использование однородных координат . [x, y, w] для 2D и [x, y, z, w] для 3D. Поскольку у вас есть три оси в 3D, а также трансляция, эта информация идеально вписывается в матрицу преобразования 4x4. В этом объяснении я буду использовать матричную нотацию по основным столбцам. Все матрицы имеют размер 4x4, если не указано иное.
Этапы от трехмерных точек до растеризованной точки, линии или многоугольника выглядят следующим образом:

  1. Преобразуйте свои трехмерные точки с помощью обратной матрицы камеры, а затем выполните любые необходимые преобразования. Если у вас есть нормали к поверхности, трансформируйте их тоже, но с параметром w, равным нулю, поскольку вы не хотите переводить нормали. Матрица, с помощью которой вы преобразовываете нормали, должна быть изотропной ; масштабирование и сдвиг делают нормали искаженными.
  2. Преобразуйте точку с помощью матрицы пространства отсечения. Эта матрица масштабирует x и y в соответствии с полем зрения и соотношением сторон, масштабирует z по ближней и дальней плоскостям отсечения и вставляет «старый» z в w. После преобразования вы должны разделить x, y и z на w. Это называется разделением перспективы .
  3. Теперь ваши вершины находятся в пространстве отсечения, и вы хотите выполнить отсечение, поэтому вы этого не сделаете. t визуализировать любые пиксели за пределами области просмотра. Отсечение Сазерленда-Ходжмана является наиболее распространенным используемым алгоритмом отсечения.
  4. Преобразуйте x и y относительно w и полуширины и полувысоты. Ваши координаты x и y теперь находятся в координатах области просмотра. w отбрасывается, но 1 / w и z обычно сохраняются, потому что 1 / w требуется для выполнения интерполяции с коррекцией перспективы по поверхности многоугольника, а z сохраняется в z-буфере и используется для проверки глубины.

Этот этап - это фактическая проекция, поскольку z больше не используется в качестве компонента позиции.

Алгоритмы:

Расчет поля зрения

Вычисляет поле обзора. Не имеет значения, принимает ли тангенты радианы или градусы, но угол должен совпадать. Обратите внимание, что результат достигает бесконечности, когда угол приближается к 180 градусам. Это особенность, поскольку невозможно иметь такой широкий фокус. Если вы хотите числовую стабильность, оставьте угол меньше или равным 179 градусам.

fov = 1.0 / tan(angle/2.0)

Также обратите внимание, что 1.0 / tan (45) = 1. Кто-то здесь предложил просто разделить на z. Результат здесь очевиден. Вы получите угол обзора 90 градусов и соотношение сторон 1: 1. Использование таких однородных координат также имеет ряд других преимуществ; мы можем, например, выполнить отсечение по ближней и дальней плоскостям, не рассматривая его как особый случай.

Расчет матрицы отсечения

Это структура матрицы отсечения. Соотношение сторон - ширина / высота. Таким образом, FOV для компонента x масштабируется на основе FOV для y. Far и near - коэффициенты, которые представляют собой расстояния для ближней и дальней плоскостей отсечения.

[fov * aspectRatio][        0        ][        0              ][        0       ]
[        0        ][       fov       ][        0              ][        0       ]
[        0        ][        0        ][(far+near)/(far-near)  ][        1       ]
[        0        ][        0        ][(2*near*far)/(near-far)][        0       ]

Экранная проекция

После обрезки, На форумах DevMaster по адресу http://www.devmaster.net/ также есть много хороших статей, связанных с программными растеризаторами.

88
ответ дан 7 November 2019 в 09:59
поделиться

Я думаю, что это, вероятно, ответит на Ваш вопрос. Вот то, что я записал там:

Вот очень общий ответ. Скажите камеру в (Xc, Yc, Zc) и точка, которую Вы хотите спроектировать, P = (X, Y, Z). Расстояние от камеры до 2D плоскости, на которую Вы проектируете, является F (таким образом, уравнение плоскости Z-Zc=F). 2D координаты P, спроектированного на плоскость, (X', Y').

Затем очень просто:

X' = ((X - Xc) * (F/Z)) + Xc

Y' = ((Y - Yc) * (F/Z)) + Yc

Если Ваша камера является источником, то это упрощает до:

X' = X * (F/Z)

Y' = Y * (F/Z)

13
ответ дан Community 7 November 2019 в 09:59
поделиться

Для получения исправленных перспективой координат просто разделитесь на z координата:

xc = x / z
yc = y / z

Вышеупомянутые работы, предполагающие, что камера в (0, 0, 0) и Вы проектируете на плоскость в z = 1 - необходимо перевести co-порядки относительно камеры иначе.

Существуют некоторые сложности для кривых, поскольку проектирование точек 3D Кривой Безье в целом не даст Вам те же точки как рисование 2D Кривой Безье через спроектированные точки.

5
ответ дан j_random_hacker 7 November 2019 в 09:59
поделиться

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

  • Вообразите луч от средства просмотра (в точке V) непосредственно к центру плоскости проекции (назовите это C).
  • Вообразите второй луч от средства просмотра до точки в изображении (P), который также пересекает плоскость проекции в какой-то момент (Q)
  • Средство просмотра и эти две точки пересечения на плоскости представления формируют треугольник (VCQ); стороны являются двумя лучами и строкой между точками в плоскости.
  • Формулы используют этот треугольник для нахождения координат Q, который является, куда спроектированный пиксель пойдет
1
ответ дан MarkusQ 7 November 2019 в 09:59
поделиться

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

[fov * aspectRatio][        0        ][        0              ][        0       ]
[        0        ][       fov       ][        0              ][        0       ]
[        0        ][        0        ][(far+near)/(far-near)  ][(2*near*far)/(near-far)]
[        0        ][        0        ][        1              ][        0       ]

некоторые дополнения к вашим вещам:

Эта матрица клипов работает только при проецировании на статическую 2D-плоскость, если вы хотите добавить движение и поворот камеры:

viewMatrix = clipMatrix * cameraTranslationMatrix4x4 * cameraRotationMatrix4x4;

это позволяет вам вращать 2D-плоскость и перемещать ее. .-

0
ответ дан 7 November 2019 в 09:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: