воскресенье, 24 января 2016 г.

С плавностью движения по карте высот разобрался.

    На видео результата можно полюбоваться:


Есть небольшие косяки, типа ошибки из-за выхода за пределы карты высот, но в целом я доволен.

moveHiMap.blend.7z (~150 kB)

Управление: WSAD - движение, 7,3,1, - выбор вида камеры. Но надо подождать пару минут, пока карта высот построится. Стартовая сцена так и называется - "start".

Опишу, как оно работает ниже.




    Для начала опишу карту высот. Она представляет из себя двухмерный массив координат с шагом между точками равным одному метру. Почему один метр - все просто, если взять, к примеру, Х-координату объекта, и сконвертировать из float в int, то можно получить первый индекс интересующей токи, а отцелочисленная Y - координата дает второй индекс. Если конечно, координаты не выходят за пределы списка. И в этом массиве записаны координаты точек, ху - координата, понятно совпадает с индексами, но z используется весьма активно. Можно было бы писать только Z-координату, просто я сделал генератор карты через посещение всех координат, мало ли, вдруг вам приспичит террейн малость отредактировать...
Понятно, что поскольку я получаю высоту отбрасывая дробную часть значения координат, то карта высот по идее, должна косплеить ландшафт в майнкрафте, как можно было увидеть на видео с "подергунчиком".  Для наглядности добавлю картинку:


    Видно, что сплошные плоские грани. Извините за темноту, там ночь была. Казалось бы, что сложного сделать ландшафт плавным - просто использовать высоты ячеек для описания вершин поверхностей, а уж из поверхностей, как из полигонов, доставать точку касания. А вот фиг. Беда в том, что четыре точки несколько занадто для описания плоскости, поэтому есть такое понятие как "вырожденные полигоны". Вот картинка, поди разберись, к какой плоскости должна  эта самая точка касания относиться.

Картинка получилась более-менее наглядной, потому что я разбил четырехугольник на четыре треугольника. можно любоваться - сплошные плоскости и ни одного вырожденного полигона. Однако, ничто не мешает сделать это же и в отношении карты высот, нужно только в середине разместить дополнительную точку, причем её даже в карту высот добавлять не надо - всегда можно высчитать. Вот как выглядит полигон выше с дополнительной точкой. Я сделал её высоту равной среднему высот всех точек, как сделаете вы - дело ваше.


И как же теперь вычислить высоту точки касания? Нужно найти треугольник, внутри которого находится точка касания. Для этого, во-первых, нужно перенести координату точки касания в систему координат с центром в средней точке текущей карты высот. Во-вторых, поскольку ребра, делящие квадрат на треугольник, расположены по диагонали, то повернуть полученный вектор положения на 45 градусов, получив таким образом новый вектор положения. Дальше нужно смотреть на знак соответствующей оси, что бы выбрать точки, образующие искомый треугольник. Затем использовать функцию из библиотеки Блендера, которая найдет точку пересечения луча и плоскости, заданной по трем точкам. По идее, никто вам не помешает построить уравнения прямой и плоскости и самостоятельно найти точку пересечения, я только пожелаю удачи.

    С определением высоты касания вроде разобрались. Теперь осталось понять, каким Макаром сделать так, что бы юнит изменял свою ориентацию  соответственно текущему положению относительно карты высот. Идеальным с этой точки зрения является такой юнит, как трайк:


Три колеса, три точки опоры, соответственно все три точки для описания плоскости налицо. Всё что надо - собрать две оси ориентации и вычислить перпендикулярную им ось, как зет.  От центра (желтая), а лучше от средней точки между задними колесами к переднему колесу - ось Y, колеса лиловые, а от левого колеса к правому -ось Х:


 
    А вот что делать с четырехколесным транспортом? Да почти то же самое, нужно только вычислить среднюю высоту между парными колесами, то есть, между передними, между задними, между левыми и между правыми. На рисунке эти точки обозначены синим цветом и соответствующей буквой.  На основе этих точек создаем вектора направления осей юнита, нормализуем их, вычисляем перпендикулярный вектор, который будет осью Z, и собираем все в матрицу ориентации.



   Однако есть проблема - если юнит большой, то скорее всего некоторая возвышенность, типа гребня дюны, находящаяся между колесами, обрабатываться не будет. Это не беда для колесной техники, но проблема для гусеничной. Я добавил определение высоты центра юнита от карты высот и от среднего между токами оси Y, с выбором подходящей. Если юнит скребет брюхом, то поднимаю высоту центра, а если между гребнями провис, то центр берет высоту от средней точки. Посмотрите, увидите. Можно добавить еще точек касания, и расписать взаимное влияние "катков" на друг друга и на корпус, но мне лень. Охота - делайте.


Комментариев нет:

Отправить комментарий