Проблемы точности в алгоритме Raycasting

Я программирую движок Raycasting.

Начальное положение луча определяется положением игрока, стоящего внутри 2D-сетки.

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

(Подробное описание концепции находится здесь: http://www.permadi.com/tutorial/raycast/rayc7.html)

Есть небольшая неточность, которая вызывает некоторые проблемы. Считаю, что проблема связана с неправильным расчетом шагов сетки.

Однако мне не хватает математического понимания, чтобы решить эту проблему.

Описание проблемы:

Когда луч движется влево, размер шага пересечения сетки немного отличается от размера шага, когда он движется вправо.

(Почему меня это вообще волнует? Это вызывает проблему, потому что некоторые горизонтальные пересечения сетки находятся дальше от игрока, чем вертикальные пересечения сетки, когда вертикальные и горизонтальные пересечения расположены близко друг к другу, особенно в углах. Поскольку я использую разные текстуры для вертикальных пересечений вид горизонтальных стен ухудшается, потому что вертикальная текстура используется на небольших участках стены, даже если это горизонтальная стена.)

Эта проблема вызвана ошибкой в ​​моем алгоритме? Вот как я рассчитываю первое горизонтальное пересечение сетки и размер шага сетки:

Найдите первое пересечение сетки:

if (current_angle > 180) {
    first_grid_horizontal_y = ((int)p.pos_y / Field::width) * Field::width + Field::width;
} else {
    first_grid_horizontal_y = ((int)p.pos_y / Field::width) * Field::width - 1;
}
first_grid_horizontal_x = p.pos_x + (p.pos_y - first_grid_horizontal_y) / tan( 180 - current_angle);

Рассчитайте размер шага:

if (current_angle > 180) {
    grid_stepsize_horizontal_y = Field::width;
    grid_stepsize_horizontal_x = Field::width / tan(current_angle - 180);
} else {
    grid_stepsize_horizontal_y = -Field::width;
    grid_stepsize_horizontal_x = Field::width / tan(180 - current_angle);
}

Как видите, я всегда использую «180 - текущий угол» для определения направления значения x. Это вызывает неточность? Нужно ли мне больше различать углы?


person Marius Anderie    schedule 03.09.2014    source источник


Ответы (2)


Тригонометрические функции работают с радианами, а не градусами. Так

tan(180 - current_angle)

должен выглядеть

tan(Math.Pi - current_angle)

Обратите внимание, что он равен

- tan(current_angle)

Если ваш current_angle в градусах, это:

current_angle_radians = current_angle_degrees * Math.Pi / 180
person MBo    schedule 03.09.2014
comment
Да, я сделал свою собственную функцию tan, которая переводит радианы в градусы. Я просто postt tan () для лучшей читаемости. - person Marius Anderie; 03.09.2014

Я думаю, ваша неточность связана с вычитанием 1 при движении вверх.

Идея, лежащая в основе этого, вероятно, заключается в том, что вы хотите получить индекс последнего пикселя блока, но это необязательно: здесь вы выполняете математику с плавающей запятой, и значение y следующего горизонтального пересечения должно представлять линию между сеткой клетки. Если вы пойдете вниз, это будет самая верхняя координата ячейки; если вы идете вверх, это самая нижняя координата.

(Кроме того: (int) y / w будет округляться до нуля и, таким образом, будет работать только для неотрицательных чисел. Вы можете рассмотреть возможность использования floor(x / w).)

person M Oehm    schedule 03.09.2014