Есть два способа показать в компьютере, как рушится стена. Первый - аниматор рисует, как кирпичи разлетаются: красиво, быстро, и физики там ноль. Второй - ты честно считаешь силы между каждой парой кирпичей и смотришь, что получится. Второй способ медленный, капризный и иногда выдаёт сюрпризы. Зато когда башня падает - она падает потому, что иначе не могла.
На видео - второй способ. Это модуль «Демонтаж» из моего симулятора физики: четыре постройки, шар-баба и больше ничего. Хочу рассказать, что происходит под капотом, потому что там интереснее, чем кажется.
Каждый кирпич - твёрдое тело: масса, момент инерции, положение, поворот. Каждый контакт между соседями - маленькая задача: найти точку касания, направление, глубину, а потом подобрать такой импульс, чтобы тела не проваливались друг в друга и не проскальзывали сильнее, чем позволяет трение. На крепости это тысячи контактов, и решаются они не разом, а по очереди - каждый следующий учитывает предыдущий, и так десять кругов за один шаг времени. Шагов таких - 120 в секунду.
Хитрость номер один: стена, которую никто не трогает, не считается вообще. Кирпичи «спят» - движок помечает тела, которые давно не двигались, и перестаёт их обсчитывать. Каменщик кладёт стену осевшей, а не дрожащей, и мы кладём так же: все кирпичи рождаются спящими. Просыпаются они только от удара - и дальше волна пробуждения бежит по кладке через контакты, кирпич будит соседа. На видео это видно буквально: кирпичи подсвечиваются цветом по собственной скорости, и цветная волна бежит по стене на кадр раньше, чем стена отвечает движением.
Почему круглая башня - это сложно
Стену выложить просто: ряд, полкирпича сдвига, следующий ряд. Башню - нет.
Первый вариант я написал за пять минут: кирпичи по кругу, каждый повёрнут на свой угол. Прежде чем запускать это в движок, я проверил геометрию отдельным скриптом: он просто раскладывает те же кирпичи и ищет, не влезли ли два кирпича друг в друга. Влезли. На 119 миллиметров. Я перепутал знак поворота, и кирпичи легли не по касательной к кругу, а вдоль радиуса - ёжиком.
Исправил знак - осталось 15 мм. Это уже тоньше: если внутренние грани кирпичей ровно касаются по окружности, то углы кирпича (он же прямой, а окружность - нет) торчат внутрь и цепляют соседний. Реальные каменщики знают это тысячи лет: круглую башню кладут так, чтобы снаружи между кирпичами были клинья раствора. У меня раствора нет, поэтому радиус считается по внутренним граням, а второе кольцо внутрь отступает не на толщину кирпича, а чуть больше - ровно на столько, чтобы углы хорды не задевали.
Почему это важно? Если два тела при рождении пересекаются, движок честно пытается их растолкнуть. С силой, пропорциональной глубине. Башня в этом случае не стоит и не падает - она взрывается. Пятнадцати миллиметров хватает.
Крепость: перевязка углов
У квадратной крепости есть проблема, о которой не думаешь, пока не начнёшь класть: угол. Две стены сходятся, и чей кирпич занимает угловую клетку? Если всегда одной стены - вторая просто прислонена и отваливается при первом же ударе. Каменщики решают это чередованием: чётный ряд - угол за одной стеной, нечётный - за другой. Стены прошивают друг друга, как пальцы сложенных рук.
Побочный эффект, который я не планировал: разница в длине между «стеной с углом» и «стеной без угла» - полтора кирпича. Полтора - значит, швы соседних рядов автоматически сдвигаются на полкирпича. Перевязка получается сама, из геометрии угла. Каменщики это тоже знали.
Шар - чугунный, примерно в восемь раз плотнее кирпича. Он такое же тело в том же мире, как кирпичи, поэтому два шара сталкиваются между собой тем же кодом, что шар с кирпичом. Никаких специальных правил для шаров нет: бросьте три, они разлетятся, как разлетятся.
Крепость тормозит. Когда шар просыпает тысячу кирпичей, движку надо проверить каждый проснувшийся кирпич против его соседей - а в плотной кладке соседей штук двадцать. Двадцать тысяч проверок за один шаг, два шага на кадр. Пришлось переписать эту часть так, чтобы проверки шли параллельно на всех ядрах, но в том же порядке, что раньше - потому что порядок здесь не эстетика: решаешь контакты снизу вверх - башня уползает на 30 см за 12 секунд, сверху вниз - на 8 мм. Это я не выдумал, это измерил.
И ещё честное: тест «спокойная сцена не должна выделять память» после переписывания покраснел, и я до сих пор ищу, кто выделяет 640 байт за шаг. Пять логов, пять срезов. Найду.