Как я делаю Unreal штуки. Бассейн. Часть первая.

Водичка с физикой

В одной игре мне надо было сделать бассейн, в который можно бросать предметы. Ну, тема тёртая, но захотелось не копипастить и сделать физику в воде. И вот как это было:

Суть.

Бассейн состоит из двух базовых вещей - поверхность воды и физика воды. Понятно, что есть еще подповерхность, но в нашей игре камера тудой не ныряла, так что в сути не участвовала.

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

Идея.

Если с поверхностью всё более-менее понятно - берешь любой простой алгоритм расчета волн и двигаешь точки (о нём – чуть пизже), А вот с физикой было не очень понятно. Ведь физика в анриле и так есть, но она не водная. Если физику отключить и двигать объект туда-сюда самому, то на физику это не будет похоже.

Так что идея была такая - сымитировать выталкивание предмета из воды (то есть в каждом тике толкать его импульсом вверх) взяв за основу вершины меша, находящиеся под водой, и учитывая объем, который под водой оказался.

В этой части расскажу про поверхность, а во второй про физику.

Итак, поверхность воды это простой прямоугольный меш с достаточным количеством вершин для сглаживания. Сам меш я генерирую процедурно, используя для этого UProceduralMeshComponent. Грубо говоря в цикле создаю X * Y точек и соединяю их в треугольники.

Сетка с разбивкой на треугольники
Сетка с разбивкой на треугольники

Дальше, в таймере или тике я вызываю обновление всех вершин, которое заключается в выполнении алгоритма моделирования поверхности воды. Я взял самый простой, который нашел на просторах рунета, а именно этот:

Я взял его, потому, что, когда-то давно прочитал его в книжке, и реализовал шейдер воды на его основе. Тогда он показался мне очень красивым и натуральным. У него достаточно настроек, чтобы сымитировать разные жидкости. Книжки давно нет, так что оставалось только нагуглить его где-нибудь.
Тут идея простая: есть два массива вершин - текущий кадр и предыдущий кадр. Расчёт текущего кадра происходит на основе предыдущего, затем массивы меняются местами. Таким образом происходит эволюция поверхности. Затухание и распространение волн по ней.

Сгенерировано ИИ, по этому сетка на картинке не ровная. Но она ровная еси шо.
Сгенерировано ИИ, по этому сетка на картинке не ровная. Но она ровная еси шо.

Кроме расчета распространения волн, рассчитываются нормали для каждой вершины. Довольно грубым способом, но он дает хороший результат: разница высот между соседними точками по Х и по У отдельно.

Работа алгоритма распространения волн.

Ну и осталось последнее - сделать возможность тыкать в воду. По сути тычок в воду это запись в массив вершин значения высоты в нужном месте. Для капли подойдет запись в один элемент, для тычка я закладывал в функцию еще размер тычка. То есть циклом проходился по вершинам и опускал их. Когда объект достаётся из воды, то он тыкает капельки под собой в таймере.

Поверх этого всего полернул материалом для симуляции ветра на поверхности (нормалками).

В следующей части распишу про поведение объектов в воде, про физику выталкивания и про возникшие проблемы.

41
18
8
2