преобразование 3d-положения в 2D-положение экрана - PullRequest
4 голосов
/ 13 октября 2011

Я хотел бы преобразовать 3D-позицию в 2D-позицию на экране.Я взглянул на похожий вопрос: Проецирование 3D-точки на 2D-координату экрана , но я не совсем понимаю ее.Я думал, что для вычисления 2-й позиции мне понадобится матрица проекции, но я не вижу, как она используется, кроме преобразования точки в координатное пространство местоположения.Кроме того, cam.FieldOfView равен farZ в OpenGL?

Может кто-нибудь помочь мне выполнить эту функцию.Достаточно ли параметров для расчета 2-й позиции?Pos уже является вектором относительно положения камеры.

       Vector2* convert(Vector3& pos, Matrix4& projectionMatrix, int screenWidth, int screenHeight)
       {
            float ratio = screenWidth / screenHeight; 

            ...

            screenX = screenWidth * ( 1.0f - screenX); 
            screenY = screenHeight * ( 1.0f - screenY);    

            return new Vector2(screenX, screenY); 
       }

Ответы [ 3 ]

10 голосов
/ 13 октября 2011

Мне кажется, это было бы что-то вроде этого:

    Vector2 Convert(Vector3 pos, const Matrix& viewMatrix, const Matrix& projectionMatrix, int screenWidth, int screenHeight)
    {
        pos = Vector3::Transform(pos, viewMatrix);
        pos = Vector3::Transform(pos, projectionMatrix);

        pos.X = screenWidth*(pos.X + 1.0)/2.0;
        pos.Y = screenHeight * (1.0 - ((pos.Y + 1.0) / 2.0));

        return Vector2(pos.X, pos.Y);
    }

Что мы здесь делаем, это просто передаем вектор через две матрицы преобразования: вид, затем проекция.После проекции вы получаете вектор с Y и X между -1 и 1. Мы делаем соответствующее преобразование, чтобы получить координаты реального пикселя и вернуть новый вектор Vector2.Обратите внимание, что компонент Z в 'pos' также хранит глубину точки в пространстве экрана в конце функции.

Вам нужна матрица 'view', потому что она определяет, где расположена камераи вращается.Проекция определяет только то, как 3D-пространство «сплющено» в 2D-пространстве.

Поле зрения не является farZ.Матрица проекции имеет несколько параметров, среди которых:

  • поле зрения, FOV, то есть горизонтальный угол обзора, в радианах;
  • дальняя плоскость или farZ:это определяет максимальное расстояние, на которое точка может быть от камеры;
  • ближняя плоскость, nearZ: минимальное расстояние, на которое точка может быть от камеры.

Помимо математической задачи,вы можете использовать Vector2 вместо выделения кучи (возвращая указатель).Vector2 - это легкая структура, и в этом контексте очень вероятно, что указатели вызовут головные боли (где вы собираетесь ее удалить и так далее).Также обратите внимание, что я использовал ссылки 'const', поскольку мы не изменяем их, кроме вектора.Для этого нам нужна локальная копия, поэтому она вообще не является ссылкой.

5 голосов
/ 03 октября 2012

Предыдущий код работает, только если вы не делаете никаких вращений (например, GL.Rotate(rotation_x, 1.0, 0.0, 0.0)).Но если вы делаете здесь код:

private Vector2 Convert(Vector3 pos, Matrix4 viewMatrix, Matrix4 projectionMatrix, int screenWidth, int screenHeight)
{
    pos = Vector3.Transform(pos, viewMatrix);
    pos = Vector3.Transform(pos, projectionMatrix);
    pos.X /= pos.Z;
    pos.Y /= pos.Z;
    pos.X = (pos.X + 1) * screenWidth / 2;
    pos.Y = (pos.Y + 1) * screenHeight / 2;

    return new Vector2(pos.X, pos.Y);
}
0 голосов
/ 13 октября 2011

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

Получив матрицу проекции, вы просто применяете ее к своим векторам (умножаете векторы вашей сцены на матрицу проекции), а затем просто отбрасываете компонент Z результирующего вектора ... то есть просто используйте X и Компоненты Y результирующих векторов.

...