Эксперименты с физикой. Часть 5.
Запись от Волгоградец размещена 12.05.2010 в 10:06
Сегодня поговорим о коллизиях. Рассмотрим столкновение шара и бесконечной плоскости. Затем добавим столкновение между шарами. Для определения коллизии шар-плоскость можно использовать знаменитую теорему о разделяющих плоскостях. Звучит она так - если между телами есть такая плоскость, которая эти тела разделяет - значит тела не пересекаются (логично). На словах звучит не очень понятно - попробуем визуализировать. Представим, что на столе лежит яблоко. Возьмем теперь лист бумаги и попытаемся просунуть его между столом и яблоком. Естественно это сделать не получится. Теперь поднимем яблоко и увидим, что наш лист легко проходит между телами - это и есть наша разделяющая плоскость. Но, как легко заметить, мы можем задать положение листа бесконечным количеством способов - чуть выше, чуть ниже, повернув, наклонив и т.д. Какую же именно плоскость выбрать? А использовать стоит плоскость, параллельную стороне одной из фигур. Алгоритм такой - мы берем два тела и последовательно перебираем все грани первой фигуры, проверяя - разделяет ли данная плоскость тела. Если находится хотя бы одна такая плоскость - значит тела не пересекаются. Если такой плоскости нет - переходим ко второму телу и проверяем заново.
Для нашего случая все намного проще - у нас бесконечная плоскость и шар - нужно проверить только одну плоскость - параллельную самой плоскости. Как же это сделать? Очень просто - мы берем любую точку на плоскости находим вектор из этой точки до центра шара и проецируем этот вектор на нормаль плоскости. Взглянем на рисунок.
На первой картинке мы видим проекцию a вектора v на нормаль n. Легко заметить - что проекция больше радиуса шара - т.е. расстояние от плоскости до центра шара больше его радиуса - значит они не пересекаются. На второй картинке проекция a меньше радиуса, что значит, что шар пересек плоскость... Надеюсь вы помните как находить проекцию - это dot product (скалярное произведение векторов).
Переходим к делу. Заведем вспомогательный класс Wall, представляющий плоскость - она будет хранить позицию, направление и нормаль. Позиция нужна для отрисовки и нахождения вектора от точки на плоскости до центра шара (на рисунках - это точка откуда выходит вектор v). Для нахождения пересечения создадим класс ParticlePlaneCollisionDetector с единственным методом findIntersection(). Весь код для определения пересечения состоит из 4 строчек! Ни единого деления и корня! Смотрим что получилось.
ballPlaneCollision.swf
Итак, мы имеем взаимное проникновение двух тел - как теперь сделать так, чтобы визуально тела не пересекались? Элементарно - выталкиваем тело на величину проникновения вдоль нормали. И вот что вышло.
ballPlaneResolution.swf
Теперь добавим интергратор и еще пару плоскостей.
ParticlesPlanes.swf
Не хватает отскоков от поверхности. На картинке показано, как найти скорость v' после отскока. Здесь e - коэффициент упругости, который принимает значения от 0 до 1 (0 - значит тело не отскочит, 1 - нормальная скорость после отскока будет такой же, как и до), f - коэффициент трения, который принимает значения от 0 до 1 (0 - значит трения нет, 1 - тангенциальная скорость после отскока будет равна 0).
ParticlesPlanesWithBound.swf
Теперь добавим коллизии между шарами. Принцип действия такой же, как и пересечение плоскость-шар - находим расстояние между шарами и если оно меньше суммы радиусов, значит мы имеем пересечение. Мы находим величину проникновения шаров друг в друга и затем каждый из шаров двигаем на половину этого расстояния вдоль нормали (нормаль в этом случае - это вектор расстояния между шарами). Для более правдоподобного поведения мы можем двигать шары на величину, пропорциональную их массам, но мы не будем это делать.
ParticleParticlePlane.swf
В демку я добавил сетку для так называемой broad phase - это фаза для определения возможности пересечения шаров. Например, если шары находятся в разных частях экрана - какой смысл их проверять. Сетка действует очень просто - размер ячейки равен диаметру шара. В каждом шаге рассчитывается какая частица находится в какой ячейке и проверяются всего 9 ячеек на предмет нахождения частиц в них. Но все равно система очень медленная - уже при 80 шарах начинаются тормоза (в релиз компиляции немного побольше) - так что есть еще место для оптимизации.
Напоследок скажу, что в системе, которую мы сделали не рассчитываются скорости после удара - поэтому после столкновения шаров они не отскакивают так как надо - но тем не менее благодаря интегратору небольшая видимость отскока есть.
Ну и напоследок несколько демок.
С помощью связей можно сделать псевдо твердое тело - например ящик.
Box.swf
Блоб - здесь он не идеален, его легко сломать.
Blob.swf
Вроде все. Я рассказал все что знаю о soft body physics. Следующие уроки (если будут) будут посвящены твердым телам - rigid bodies - будем создавать что-то типа Box2D.
tutorial5.zip
Всего комментариев 15
Комментарии
12.05.2010 23:16 | |
Спасибо за уроки!
|
13.05.2010 10:38 | |
Спасибо за вашу рубрику. Надеюсь будет продолжение.
|
05.06.2010 19:31 | |
Нет rotation-a... Где rotation??
|
07.06.2010 12:15 | |
mikleb, да, можно будет попробовать. Времени жаль очень мало.
Ariel, в том то и полезность метода Верле - создается иллюзия правдивого движения без тяжелых расчетов. |
08.06.2010 23:33 | |
Э-э-э.. Тяж0лые расчеты... Вот ведь шарик кружится без тяжелых расчетов.
И как это у Вас у стены (Wall) имеется _direction? Ну _position я еще могу понять, но направление, выраженное через вектор... у стены.. Зачем? |
10.06.2010 23:10 | |
Привет.
Отличные уроки. У меня к вам вопрос по 5-ым туторам: 1172: Definition ru.inils.utils: Debugger could not be found. import ru.inils.utils.Debugger - откуда взять? Спасибо. |
17.06.2010 09:22 | |
Да-да, ужо разобрались.. У Пеннера в книжке так и указывается. Типа, вектора юзаются, как Number2D...
И неужели в Вашем мега-двиге не будет rotation-a? Как же без него? И еще одно. У Вас повсеместно использованы геттеросеттеры. Для таких критических участков (скорость) это не есть хорошо. Я бы даже сказал, плохо. Паблик переменные рулят! И в детекторе столкновений у Вас сидит try-catch, шо тоже конкретно заваливает все показатели по скоростям. |
|
Обновил(-а) Ariel 18.06.2010 в 00:38
|
19.06.2010 03:54 | |
Да, очень интересно. Скажем, как подшивать к интегратору Верле этот пресловутый rotation...
Ждем-с! |
11.01.2011 09:16 | |
Волгоградец, продолжение будет? Очень уж интересная тема
|
11.01.2011 11:26 | |
Да, будет когда-нибудь. Наработки есть - надо привести все это в подобающий вид - но лень и нехватка времени... :-).
|
Последние записи от Волгоградец
- Изометрическая сортировка. Новый подход. (25.01.2013)
- Stage3D заметки (06.04.2012)
- Embed клипа с одним кадром. (16.01.2012)
- Производительность операций с floating point number (18.03.2011)
- FTE based text controls (10.01.2011)