Точные задачи в алгоритме лучевого вещания

Я программирую движок радиовещания.

Начальная позиция луча определяется положением игрока, который стоит внутри 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. Это вызывает неточность? Нужно ли больше различать углы?

3

Решение

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

tan(180 - current_angle)

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

tan(Math.Pi - current_angle)

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

- tan(current_angle)

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

current_angle_radians = current_angle_degrees * Math.Pi / 180
1

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

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

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

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

1

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