Поведение перспективной проекции для преобразования 3D-точки на экран

Я перекодирую конвейер рендеринга в c ++ и у меня возникли некоторые проблемы, чтобы заставить его работать.
Я имею в виду, это работает, но не так, как я ожидал.
Для простоты я преобразую свою 3D-точку в 2D-точку с помощью построения матрицы перспективной проекции следующим образом:

Моя функция draw_edge просто берет 2 точки в мировом пространстве и выполняет вызовы для преобразования этих точек в экранные координаты:

void Scene::draw_edge(const geometry::Point<float,4>& p1, const geometry::Point<float,4>& p2, gui::Color c) const
{

geometry::LineSegment ls(p1.ReduceToPoint3DAsPoint(), p2.ReduceToPoint3DAsPoint());
std::optional<geometry::LineSegment> cls = camera.VisiblePart(ls);

if(cls != std::nullopt)
{
auto p1Persp = Perspective((*cls).GetBegin().ExtendedPoint4DAsPoint());
auto p2Persp = Perspective((*cls).GetEnd().ExtendedPoint4DAsPoint());

om::Vector<2,float> p1Projection2D;
om::Vector<2,float> p2Projection2D;

p1Projection2D[0] = p1Persp.At(0);
p1Projection2D[1] = p1Persp.At(1);
p2Projection2D[0] = p2Persp.At(0);
p2Projection2D[1] = p2Persp.At(1);

gui->render_line(p1Projection2D,p2Projection2D,c);
}
}

Эта функция используется для фактического преобразования моих точек путем применения матрицы перспективы, а затем делить мои координаты на «w».

geometry::Point<float,3> Scene::Perspective(const geometry::Point<float,4>& point) const
{
geometry::Transform perspectiveTransform = camera.GetPerspectiveProjection();
geometry::Point<float,4> pointHomogenous = perspectiveTransform.TransformTo(point);
om::Vector<3,float> normalized;
for(int i = 0; i < 3; i++)
{
normalized[i] = pointHomogenous.At(i) / pointHomogenous.At(3);
}

return geometry::Point<float,3>(normalized);
}

Эта функция используется для построения моей матрицы проекции перспективы

geometry::Transform Camera::GetPerspectiveProjection() const
{
float nearValue = position.Dist(frustum.nearPlane);
float farValue = position.Dist(frustum.farPlane);
float rightValue = nearValue / focaleDistance;
float leftValue = -nearValue / focaleDistance;
float topValue = (aspectRatio * nearValue) / focaleDistance;
float bottomValue = -(aspectRatio * nearValue) / focaleDistance;

auto perspective = geometry::Transform(nearValue, farValue, rightValue, leftValue, topValue, bottomValue);
//auto perspectiveInverse = perspective.GetMatrix().Reverse();
//perspective = geometry::Transform(perspectiveInverse);

return perspective;
}

Как вы можете видеть, я прокомментировал инверсию, и в этом смысл этого поста, я вернусь к нему позже.

Итак, наконец, функция, которая строит мою матрицу перспективы:

Transform(float near, float far, float right, float left, float top, float bottom)
{
transform[0][0] = (2*near)/(right - left);
transform[0][1] = 0.0f;
transform[0][2] = (right + left)/(right - left);
transform[0][3] = 0.0f;

transform[1][0] = 0.0f;
transform[1][1] = (2*near)/(top - bottom);
transform[1][2] = (top + bottom)/(top - bottom);
transform[1][3] = 0.0f;

transform[2][0] = 0.0f;
transform[2][1] = 0.0f;
transform[2][2] = -((far + near)/(far - near));
transform[2][3] = -((2*near*far)/(far - near));

transform[3][0] = 0.0f;
transform[3][1] = 0.0f;
transform[3][2] = -1.0f;
transform[3][3] = 0.0f;
}

Итак, теперь, когда весь необходимый код доступен, вот моя проблема.
Когда я использую инверсию перспективной проекции (раскомментируя 2 строки), результат выглядит следующим образом:

обратная матрица

Но если я прокомментирую свою инверсию, результат будет следующим:

нет обратной матрицы

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

Спасибо за чтение и не стесняйтесь спрашивать больше информации

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]