Чтобы правильно отобразить каждый пиксель изображения карты высот на местности, мы получим ландшафт как по ширине, так и по длине на 1 единицу меньше, чем фактическая ширина и длина карты высот. Например, если у нас есть изображение шириной всего 2 пикселя, каждый пиксель будет отображаться в каждой вершине четырехугольника. У нас есть 2 пикселя, но только 1 единица местности.
Я пытаюсь «исправить» эту проблему, масштабируя местность, чтобы заполнить пустой квад в конце местности. Однако это проблематично, когда я пытаюсь получить высоту ландшафта в некоторой точке (x, z). Проблема не совсем в масштабировании, как вы увидите.
Сначала давайте посмотрим на код, который работает. Тот, где масштабирование не учитывает отсутствующий квад. У меня есть карта высот 1024x1024, которая создаст ландшафт с квадратами 1023x1023 (я на самом деле использую треугольники, но это легко объяснить с помощью квадраторов) без какого-либо масштабирования.
Теперь давайте масштабируем ландшафт примерно до 2000x2000, передав соответствующие аргументы следующей функции:
void Terrain::ScaleDimension(float dimWidth, float dimLength) {
if(dimWidth <= 0.0f || dimLength <= 0.0f) return;
stepWidth = dimWidth / width; // 1.953125 = 2000 / 1024
stepLength = dimLength / length; // 1.953125 = 2000 / 1024
}
Когда я рисую ландшафт, я использую stepWidth
и stepLength
, чтобы соответствующим образом масштабировать ландшафт соответственно. Ландшафт будет масштабироваться, но будет использоваться только 1023 квадра, всегда 1023, не более (что нормально). Теперь предположим, что я перемещаю своего игрового персонажа и мне нужно получить высоту ландшафта в текущей позиции игрока. У меня есть функция, которая будет принимать x
и z
координаты положения игрока и возвращать высоту в этой точке. Но поскольку размер местности измерен, я не могу просто использовать x
и z
, переданные в функцию, мне нужно вычислить правильные, например:
x = x / stepWidth;
z = z / stepLength;
После этого мне просто нужно найти 4 смежные вершины новых x
и z
и выполнить билинейную интерполяцию по высоте всех вершин, чтобы вычислить правильную высоту на позиции игрока.
Все это работает просто отлично. Ландшафт правильно прорисован, и все высоты правильно рассчитаны. Моя проблема в том, что я пытаюсь обойти «ограничение», описанное в начале этого вопроса.
Чтобы обойти проблему, я изменяю свою функцию масштаба следующим образом:
void Terrain::ScaleDimension(float dimWidth, float dimLength) {
if(dimWidth <= 0.0f || dimLength <= 0.0f) return;
stepWidth = dimWidth / (width - 1.0f);
stepLength = dimLength / (length - 1.0f);
}
Допустим, мой размер рельефа (значения, которые я передаю вышеупомянутой функции масштабирования) - это точно такой же размер карты высот, как 1024x1204. Это даст мне шаг 1.000977517106549364613880742913
, при котором 1023 квадра будут точно соответствовать от 0 до 1024 (размер местности). Пока все хорошо, местность прорисована точно так, как я ожидал.
Настоящая проблема - вычисление высоты. Я пробовал много вещей, но я просто не могу понять это уравнение для вычисления правильных x
и z
, которые будут использоваться в функции, которая возвращает высоту, , учитывая новый шаг вычисления выше . Дайвинг x
и z
с размером шага, как я делал раньше, просто не поможет. Шаг теперь вычисляется немного по-другому и не так просто, как раньше.