Приветствую тебя, читатель. Это вторая часть серии переводов работы "Ray-Casting Tutorial For Game Development And Other Purposes". Второй части предшествует первая, которую так же можно просмотреть.
Начнем! Продолжим!
Ограничения ray-casting
Технология ray casting быстрая потому, что она использует некоторые геометрические ограничения. В большинстве случаев стены всегда перпендикулярны полу (заметьте, что это не касается углов между самими стенами).
Отсюда мы получаем еще одно ограничение: точка обзора не может вращаться вдоль оси Z (которую мы все знаем, как ось аппликата - прим. пер.). Почему? Представим обратное: вращение разрешено. В таком случае стены могут наклоняться, и соответственно теряется преимущество отрисовки вертикальных срезов этих самых стен. Ограничение во вращении является одной из причин, почему технологию ray casting нельзя считать полноценным 3D.
Технология ray-casting позволяет игроку двигаться вперед/назад и поворачиваться вправо/влево, но не вращаться вокруг оси Z (такой тип вращения называется креном (если ось Y вертикальная, то вращение по ней - тангаж, а по оси X - рыскание, - прим. пер.)).
Шаг 1: Создание окружения
Для то, чтобы отобразить работу ray casting, мы создадим сцену в виде лабиринта, которая будет основываться на следующих геометрических ограничениях:
Стены всегда перпендикулярны полу
Стены представляют собой одинакового размера кубы
Пол всегда
лаваплоский
Каждый куб будет иметь размер 64x64x64 (Выбор произвольный, но полезно иметь такое число, которое будет являться степенью 2. В таком случае мы сможем использовать операцию битового сдвига, которая работает быстрее умножения и деления). Стоит отметить, что чем больше размер блоков, тем более кубическим будет казаться наш мир, с другой стороны, слишком маленькие блоки ввиду их большого количества замедлят процесс рендера.
Перед тем как продолжить, мы должны определить систему координат (далее - СК), чтобы далее не было каких-либо недопониманий. Наша СК изображена на следующем рисунке.
Любая картезианская СК также будет работать. Тем не менее, будьте последовательны и не используйте разные СК. Иначе вы можете запутать себя - проверено мною лично.
Шаг 2. Определение атрибутов проекции
Перед тем, как начать проецировать и ренедрить созданную сцену, нужно определить некоторые атрибуты. Вот они:
Высота игрока, поле зрения игрока (FOV - Field Of View), и координаты игрока
Размеры плоскости проекции
Как соотносятся игрок и плоскость проекции
Игрок должен иметь возможность видеть то, что находится напротив него. Для этого мы объявим FOV, который определит, насколько широкая область сцены доступна для наблюдения игроком. Люди имеют FOV в 90° и больше. Тем не менее, такой угол не совсем подходит для экранов ПК. Мы выберем 60°, которые были получены путем экспериментов и проб (насколько хорошо выглядит картинка с таким-то углом FOV). Высоту игрока определим, как 32 единицы. Это вдвое меньше, чем стены, что является разумным допущением. (если взять реальное соотношение средней высоты помещения к среднему росту человека-самца, то получим: 2.4 / 1.7 = 1.41 - прим. пер.).
Длинная стрелка показывает угол поворота игрока, остальные - это те самые воображаемые лучи, исходящие из точки обзора. Все вместе, лучи и образуют область видимости игрока, то есть FOV - прим. пер.
Чтобы поместить игрока в наш мир, нужно для этого игрока определить X-координату, Y-координату и угол поворота. Эти 3 атрибута формируют POV (point of view) игрока.
Если предположить, что игрок где-то по центру координатной сетки (1, 2), и его угол поворота равен 45 относительно начала оси, то FOV будет выглядеть примерно, как на картинке ниже. (Каждый элемент сетки имеет размеры 64x64 единиц).
На картинке слева мы видим POV, которая представляет собой координаты игрока и его угол поворота. На картинке справа - FOV - область видимости игрока. - прим. пер.
Нам нужно определить плоскость, на которую мы будем проецировать то, что видит игрок. Плоскость шириной в 320 единиц и высотой в 200 - это хороший выбор, т.к. это разрешение большинства VGА видеокарт.
Когда POV игрока спроецирован на плоскость, сцена будет выглядеть, как на картинке ниже.
Как только нам стали известны FOV и размеры плоскости проекции мы можем посчитать угол между последующими лучами и расстояние между игроком и плоскостью проекции.
Что мы имеем:
На картинке слева мы видим плоскость проекции того, что видит игрок (это же экран нашего монитора): она имеет размеры 320х200 пикселей и центр в точке (160, 100). На картинке справа представлен вид "из глаз игрока". - прим. пер.
Теперь перейдем к расчетам (большая часть вычислений относится к программе старших классов, я советую повторить тригонометрию, теорему Пифагора, если вы не понимаете, как получены такие результаты).
FOV равен 60. При этом мы видим плоскость проекции шириной в 320 пикселей, то есть 60° соответствуют 320 столбцам и, следовательно, 1 столбец равен 60 / 320 градусам. - прим. пер.
FOV и плоскость проекции образуют равнобедренный треугольник. Если к плоскости проекции провести высоту, то мы получим два прямоугольных треугольника с одной стороной в 320 / 2 = 160 единиц и углами: 90°, 60° / 2 = 30° и 90° - 30° = 60° соответственно. Используя формулы тригонометрии мы находим длину высоты (277), которая и является расстоянием между игроком и плоскостью проекции. - прим. пер.
По итогу нам известно:
Размеры плоскости проекции (экрана) = 320х200 единиц
Центр плоскости проекции (160, 100)
Расстояние до плоскости проекции = 277 единиц
Угол между последующими лучами = 60 / 320 градусов
(Мы будем иногда ссылаться на угол между последующими лучами, как на угол между соседними столбцами. Позже этот угол будет использоваться для итераций внутри цикла от одного столбца к другому. Расстояние до плоскости проекции будет необходимо для масштабирования.)