Я написал простой инструмент моделирования физики, который позволяет мне прыгать шары по экрану. Вы можете щелкнуть и перетащить шарик, чтобы запустить шарик, или создать сотни шариков одновременно и наблюдать, как они взаимодействуют друг с другом.
альтернативный текст http://i41.tinypic.com/2zr0oic.png
[Ссылка на увеличенную версию]
Это была забавная маленькая программа, над которой я работал, и я хочу продолжить ее, если смогу. Я знаю, что они говорят, что преждевременная оптимизация - корень всего зла, но я начинаю сталкиваться с фактическими барьерами производительности и хочу знать, может ли мне помочь кто-нибудь, имеющий опыт в разработке игр / симуляторов.
Проблема:
Прямо сейчас моя программа задыхается, если вы добавляете слишком много шаров (на моей машине она не может обрабатывать более 800). Если вы это сделаете, симуляция больше не будет реалистичной, и все шары перекрывают друг друга на дне.
Проблема в обнаружении столкновений. В наиболее наивном случае обнаружение столкновений является проблемой O (N ^ 2). Каждый шар проверяет каждый второй. Это очень быстро снижает производительность (даже после 100 шаров вы будете делать 10 000 проверок столкновений за цикл).
Если вы посмотрите здесь, вы можете увидеть скриншот, где я добавил несколько сотен шаров. Симулятор не может идти в ногу, и они начинают перекрывать друг друга.
альтернативный текст http://i41.tinypic.com/2nsnuqd.png
[Ссылка на увеличенную версию]
В настоящее время я обнаруживаю столкновения, ища перекрывающиеся шары. Если я нахожу два шарика, которые перекрывают друг друга, я разделяю их по минимальному расстоянию перевода (MTD) или раздвигаю их. Затем я использую простое физическое уравнение, чтобы скорректировать их импульсные векторы, и после столкновения они движутся в разных направлениях.
Это прекрасно работает, за исключением случаев, когда слишком много шаров, минимальное расстояние перевода становится заметным. Они начинают перекрывать друг друга в больших количествах и постоянно толкают друг друга на дне. Чем хуже я увеличиваю «гравитацию», тем хуже. Давление на них увеличивается, а количество сжимаемых / перекрывающих друг друга элементов увеличивается.
Опять же, у меня нет проблем, пока я не наберу значительное количество N шаров.
Текущий метод оптимизации :
Обнаружение столкновения -
Очистка и удаление - (иначе. Сортировка и очистка)
Я использую сортировку вставки на своих шарах каждый цикл цикла вдоль их оси x. Из-за характера сортировки вставок я могу использовать временную когерентность моего симулятора. Кадр за кадром, позиции шаров меняются незначительно, так что сортировке не нужно много работать. Это приводит к тому, что время линейной сортировки амортизируется во время O (N) или линейно, а не в среднем времени O (N ^ 2).
Поскольку шары отсортированы, я делаю пару предварительных проверок во втором цикле перед проверкой столкновений. Теперь мне нужно только проверить шары рядом друг с другом (потому что они отсортированы вдоль оси x), и я вырываюсь из второй петли каждый раз, когда проверяю шар против другого шара, xmin которого больше, чем xmax текущего шара , Так что он пропускает тысячи проверок.
Когда я это реализовал, это принесло огромное улучшение скорости. Тем не менее, я все еще хотел бы иметь возможность обрабатывать более 600-800 мячей. Я читал о Physics Engines, которые легко справляются с обнаружением столкновений между 10k объектами одновременно, поэтому я хотел бы думать, что я смог бы достичь 1-2k с небольшой работой.
После запуска profiler выяснилось, что Collision Detection потреблял около 55% моего времени, а рендеринг - около 45%. Итак, это мои две самые дорогие расходы.
Вопрос:
Можете ли вы придумать какие-нибудь лучшие алгоритмы или методы, которые позволили бы моему симулятору обрабатывать больше шаров?
Соответствующий код:
Весь проект:
svn checkout http://simucal -projects.googlecode.com / svn / ballbounce / trunk /
или нажмите здесь , чтобы просмотреть файлы вручную в браузере.
Разделы интересов: