27 мая 2010

физика ;)

Под резким влиянием полёта своей мысли, решил чуточку черкнуть про физические штуковины, что мне попадались при программировании. Вообще, физическую симуляцию можно разделить, в зависимости от задачи, на точную и быструю. Почему невозможно считать и быстро и точно? 

Потому как физических законов довольно много, сами ученые еще не придумали множество формул, которыми, наверно, будут пользоваться наши внуки. Одновременно удовлетворить выполнению всех этих законов довольно сложно, потому, зачастую, физики, а, впоследствии, и программисты, пользуются приближениями, ухищрениями и прочими "шалостями" для ускорения процесса обсчета физических процессов. Лично мне приходилось программировать симуляцию воздействия лазерного пучка на объект заданной формы. В общем, непростое дело, если честно. Штука медленная из-за того, что полностью считается на центральном процессоре. На графический перенести мне так и не удалось. Также делал симуляцию газов, жидкостей, деформации тел и другие красивости. Это все было программирование с академическими целями - потому все делалось исходя из формул, собственных выводов и переведенных статей.
В программе с лазерным пучком, график из 100 точек строился порядка часа. В принципе - быстро. Но в игровых программах требуется real-time симуляция, оттого точность теряется, и мы вынуждены искать методы быстрого расчета положений тел при физических взаимодействиях. Как сейчас помню, мужчина на лекции у нас в университете упомянул какую-то бесплатную физическую библиотеку, сказав "видел я как-то машинку, ездящую по трассе - выглядело здорово". Я решился переспросить название, в ответ услышал "Open Dynamics Engine". Быстро записав на полях тетради, я загорелся найти и изучить. В итоге потихоньку стали вырисовываться новые знания о физическом моделировании - ты задаешь все базовые положения, вызываешь Update() и на выходе у тебя положения и ориентации всех тел, участвующих в симуляции. Потом в ход идут всякие ухищрения для моделирования жидкостей, взрывов, парящих над поверхностью тел и другое. В итоге быстро начинаешь делать "обертку" для легкого использования физической библиотеки, настраиваешь параметры, долго придумываешь структуру модулей, их взаимосвязь. Как следствие - ODE мне очень понравился, я его советовал всем и с большой неохотой слушал реплики вроде "да есть намного лучше движки". Конечно обидно, что заголовки для этой библиотеки практически не обновляются, и из-за этого становится как-то не по себе - мало ли разработчики поправят bug'у, а я даже не смогу этим воспользоваться из-за отсутствия поддержки для Delphi. И, в определенной момент, я решил перейти на Box2d, вернее - посмотреть стабильность при моделировании двумерной физики. Скажу откровенно: по-началу я сильно серчал на эту библиотеку. Я так и не понял - почему размеры объектов задаются единожды при их создании? Почему я не могу изменить радиус объекта-круга в процессе симуляции? Также неясно, почему у каждого тела есть индивидуальные параметры вроде коэффициента трения, упругости и других? Ведь коэффициент трения - это параметр взаимодействия двух тел и не может иметь значение у конкретного тела в отрыве от остальных. Оказалось, при столкновении, коэффициентом трения будет выступать результат функции от значений трения, присвоенных каждому объекту. Меня лично тогда это немного покоробило: "ну в-о-о-о-т, не получится создать сложных систем, регулируя все самостоятельно" - думал я. Потом оказалось, что я не могу "приостанавливать" действие сочленений на время, пока они мне не нужны. Последней каплей было штатное отсутствие RayCast'ов. Тогда я думал, что без них и жить нельзя. Но в итоге двиг показал себя с очень положительной стороны. Стабильность, скорость и реалистичная симуляция - в принципе всё, что требуется от физической библиотеки, имеется в Box2d. В общем, для 2d - лучший выбор, мне кажется сейчас. Недавно, кстати, решил попробовать Newton. Как все отзываются - "намного лучше ODE". На мой взгляд - "главное, чтобы руки были прямые, а там уж..." В общем, опять работает первый импульс отторжения - "а почему силу добавлять можно только при CallBack'е?" или "вот накрутили с этими материалами - ведь неудобно, наверно!".
Помню, как когда-то давно решил сделать взрывную волну при помощи ODE. Тогда я сделал все просто - создаю "мягкую" (выкручиванием erp и cfm) сферу в точке контакта ракеты с объектом, а дальше, манипулируя размером самой сферы, создается эффект взрывной волны - все объекты исправно разлетаются в разные стороны. Выглядело здорово! Так вот, если приглядеться - на Box2d и Newton такого не сделать - ибо размеры всех объектов задаются при их создании. Сейчас, правда, я понимаю, что такой способ симуляции взрывной волны довольно убог и нефизичен, но факт остается фактом. С другой стороны, когда-то давно я делал верёвку при помощи ODE. Выглядело ужасно: при сильных нагрузках верёвка начинает "дрожать" - вероятно, сказываются ошибки при вычислениях сочленений верёвки. Чем больше кусочков, из которых состоит веревка, тем больших визуальных дребезжаний можно достичь. Кажется, 15 кусочков было уже пределом. В Box2d таких проблем практически не встречается - всё гладко и стабильно. Даже при 100 кусочках, связанных сочленениями, фпс практически не падает. Согласен, симуляция в 2d гораздо проще и менее ресурсоёмко, чем в 3d, но всё же - ведь часто возникает мнение, что лучше изучить один физ.двиг и использовать его при симуляции как дву- так и трехмерных движений. Учитывая вышесказанное, необходимо также учитывать меньшую стабильность при использовании двига, "заточенного" под 3d, при симуляции на плоскости.
Разница, на самом деле, не только в степенях свободы и стабильности при симуляции. При переходах между физическими двигами можно увидеть несколько разные подходы, что замедлит переброс проекта с одной библиотеки на другую. Например, в ODE при обработке контактного сочленения вызывается CallBack-функция, внутри которой разработчик сам решает - обрабатывать ли контакт, какой коэффициент трения установить, какую упругость. С одной стороны - можно почувствовать, что всё в Ваших руках - не проскользнёт ничего, управляем практически всем. С другой стороны - неизбежно придётся городить свой собственный велосипед, у которого будут параметры групп объектов (эти с этими не соударять, а вот эти с этими - пожалуйста) ну и так далее. В Box2d, к примеру, с этим проблем меньше. Уже существуют стандартные способы фильтрации - маски, группы, категории. Очень удобно. Хотя возможны способы и ручной фильтрации, что тоже замечательно (правда, лично у меня не было в этом необходимости до сих пор). С параметрами объектов также сразу видны различия - в ODE приходится самому хранить некие флаги, характеристики и т.д., чтобы в CallBack-функции выставить правильно коэффициенты трения, упругости, erp и cfm (почитайте manual, чтобы правильно понять, что это за чиселки). В Box2d основные коэффициенты хранят сами геометрии, и в этом есть своя прелесть - приятно видеть, что разработчики двига взяли на себя смелость внести базовые параметр внутрь своей библиотеки. В Newton все немного оригинальнее - каждый физический объект хранит ссылку на свой материал. Изначально все объекты ссылаются на default-материал, но можно создавать свои, назначать им параметры и в итоге присваивать телам. Наверно удобно, пока до этого не добрался. Правда иногда мозг буравят мысли - "ну какова вероятность того, что у нескольких тел будут одинаковые коэффициенты трения и упругости?" Наверно, только если эти объекты - одинакового типа в принципе. Хм, "деревянная стена седьмого типа" или же "отшлифованное металлическое кольцо". Зачастую бывает, что приходится чуточку править параметры объектов от уровня к уровню для идеального физического поведения - здесь чуточку утяжелить, тут убрать трение, а здесь добавить возможность немного пружинить от стен. Игроку это будет практически незаметно, но главное - без этих корректировок некоторые моменты иногда мешали бы игроку, отталкивали и раздражали бы.
Но легко прослеживаются и одинаковые подходы у разработчиков этих трех библиотек. К примеру, физический объект разделен на две составляющих - "тело" и "оболочка". Тело "знает" о силах, скоростях, моментах инерции и т.д. Оболочка - это геометрический контур, позволяющий находить пересечения объектов друг с другом. Интересно то, что "тело" - во всех трех библиотеках названо Body. С оболочкой намного смешнее: в ODE оно зовётся Geometry, в Box2d - Shape, в Newton - Collision. Но суть одинакова. Под вопросом осталась только масса. Параметр, принадлежащий, как бы, и телу и оболочке одновременно. Где её хранить? В итоге используется метод тела, собирающий тензор инерции из плотностей и форм своих оболочек. Не могу судить, наилучший ли это вариант, но пока проблем не возникало.
В итоге сейчас планирую совместить все три библиотеки в одном месте, абстрактно использующем физику, которому не будет особой разницы использовать функции Newton, Ode или Box2d. Но времени нет, оно сейчас полностью используется для доработки игры. Так что мне придется придержать желание повозиться с этими движками.
На этом пока все - надеюсь развивать сравнение используемой мной физики и продолжить описание различий, схожести и областей применения этих трёх двигов. Будут пожелания - всегда рад услышать.

Сообщения, схожие по тематике:

0 коммент.:

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