Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > Волгоградец

Рейтинг: 4.63. Голосов: 8.

Эксперименты с физикой. Часть 1.

Запись от Волгоградец размещена 28.03.2010 в 21:46
Обновил(-а) Волгоградец 29.03.2010 в 12:39

Давно смотрел на различные физические симуляции и молча завидовал людям, которые умеют делать веревки, ткань, определять коллизии... И вот, прочитав несколько книг, я увидел что не так уж это и сложно. Я попытаюсь создать простенький двухмерный физический движок и по ходу буду описывать свои действия. Для понимания материала, я бы посоветовал вспомнить школьную геометрию и векторную математику. Хотя я постараюсь описать некоторые моменты. Также хочу заметить, что код буду писать без глубокой оптимизации и с оглядкой на ООП (хотя это отрицательно скажется на производительности).
В первой серии туториалов мы создадим так называемый soft body физический движок. А именно, я покажу как смоделировать пружину, ткань, эластичную веревку, цепь.
Let's Get Started...

В первой части мы создадим простую пружину, которая послужит нам в дальнейшем для веревки и ткани. Я выбрал следующую реализацию:
- я буду создавать frame based симуляцию, т.е. я не буду учитывать точное время между кадрами, а буду принимать это время равным 1.
- для каждой силы (а это - гравитация, сила воздушного сопротивления и др.), я создам свой генератор силы, который будет принимать в качестве параметра частицу и добавлять соответствующую силу ко всем силам, действующим на данную частицу.
- для расчета положения частицы я буду использовать отдельный класс - интегратор, который будет принимать в качестве параметра частицу.

Последовательность действий такая - в начале каждого кадра я рассчитываю все силы, действующие на частицу, и добавляю их в один общий аккумулятор сил частицы. Так удобнее, ведь результирующая сила одна - и равна сумме всех сил. Затем интегратор рассчитает положение и скорость частицы в зависимости от ускорения, которое зависит от той самой результирующей силы.

Итак, начнем со строительства фундамента - создадим класс VVector2D (т.к. в сети можно найти уйму реализаций вектора, во избежание конфликта имен я добавил букву V перед именем класса. Далее, ко всем классам буду добавлять эту букву - заодно прославлю свой ник). Каждый метод описывать не буду - остановлюсь, как я считаю, чуть ли не самом важном методе в построении физических симуляций, на методе dotProduct() - скалярном произведении векторов.

Код AS3:
dotProduct(vector:VVector2D):Number
{
	return _x * vector.x + _y * vector.y;
}
Метод принимает экземпляр вектора и возвращает скалярное произведение двух векторов. Зная величину этого скалярного произведения, мы можем рассчитать угол между векторами таким образом:
dotProduct = |a|*|b| * cosA, где |a| и |b| - длины векторов.
Также мы легко можем узнать направление векторов относительно друг друга - если скалярное произведение больше 0, то вектора направлены в одну сторону, если меньше 0, то в противоположные, если равно 0, то перпендикулярны.
Еще одной не менее важной особенность скалярного произведения векторов является его геометрическое представление - оно показывает проекцию одного вектора на другой. Если один из векторов нормализован (т.е. его длина равна 1), то dotProduct даст нам точную величину проекции.

Название: pic1.png
Просмотров: 2386

Размер: 1.7 Кб

На картинке мы видим, как пунктирная линия показывает величину проекции вектора a на единичный вектор n. Мы скоро увидим применение этой особенности.

Далее создадим класс частицы Particle. Это то, на чем мы будем проводить наш физический эксперимент. Здесь ничего особенного - частица будет хранить позицию, массу (а также инверсную массу, т.е. отношение 1 к массе - чтобы избавиться от деления), скорость. Ускорение и аккумулятор будут рассчитываться каждый фрейм. Радиус и цвет нужны для отображения на экране - в расчетах они не участвуют.

Дальше идут силы.
Gravity - сила гравитации. Тут все просто - равна произведению ускорения свободного падения на массу частицы. Ускорения я выбрал равным 1 и направленным вниз, т.е. это вектор VVector2D(0.0, 1.0). Эту силу передаем в аккумулятор сил частицы.
Drag - сила воздушного трения. Равна произведению скорости частицы на коэффициент сопротивления и направлена в противоположную скорости сторону. Коэффициент я выбрал равным 0.1. Эту силу передаем в аккумулятор сил частицы.
AnchoredSpring - сила пружины. Здесь остановимся подробнее. В данном примере я сделаю пружину, один конец которой жестко зафиксирован и смещаться не будет. К другому концу будет подвешена частица. Сила рассчитывается следующим образом:
F = k * x,
где k - коэффициент жесткости пружины или stiffness.
x - расстояние, на которое мы сместили пружину. Т.е. представьте - в спокойном состоянии у пружины есть некая длина - так называемая rest length. Мы немного растянули пружину и ее длина увеличилась по сравнению с длиной покоя. Это и есть искомое x.

Название: pic2.png
Просмотров: 2331

Размер: 2.5 Кб

Помимо этих величин также имеется и коэффициент затухания пружины damping.
Немного векторной математики - и мы получаем силу и передаем ее в аккумулятор сил частицы.

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

Собрав все это вместе и запустив мы видим, что частица реалистично прыгает на пружине. Все вроде бы хорошо, но есть одно НО - тот проект, что я приложил настроен так, что все работает стабильно. Но если поменять жесткость пружины или массу частицы, мы можем увидеть, как частица начинает метаться из стороны в торону и затем улетает в бесконечность. Это происходит из-за того, что действующая сила пружины действует так, что выталкивает нашу частицу достаточно далеко и теперь, новая сила будет действовать сильнее предыдущей и т.д.
Чтобы этого не было можно поступить так:
- жестко задать параметры и пресекать лишнее неосторожное движение.
- использовать другой интегратор - например интегратор Verlet.

В следующей части я покажу второй вариант - мы напишем новый интегратор Верле. Будет круто, оставайтесь на связи!

tutorial 1.zip
Всего комментариев 16

Комментарии

Старый 28.03.2010 23:50 mayakwd вне форума
mayakwd
 
Аватар для mayakwd
вот это уже здорово, движок изнутри. ждем-с продолжения.
Старый 29.03.2010 10:03 Котяра вне форума
Котяра
 
Аватар для Котяра
Цитата:
ко всем классам буду добавлять эту букву - заодно прославлю свой ник
а зачем? Для этих целей придумали package,namespace и @autor..
А понял.. Вы - подающий надежды гений))))
Старый 29.03.2010 11:43 Jewelz вне форума
Jewelz
 
Аватар для Jewelz
))))

а статья хорошая
Старый 29.03.2010 12:39 Волгоградец вне форума
Волгоградец
 
Аватар для Волгоградец
Котяра, офигеть! Убил. Т.е. я уже на второй ступени в пути к мастерству?
Старый 29.03.2010 19:22 MrPoma вне форума
MrPoma
 
Аватар для MrPoma
Я могу точно сказать, что я на третьем пункте застрял :-)
Старый 30.03.2010 17:54 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Я ветеран и правда не понимаю, почему отсекать и швырять экспешны и трейсы при "плохих" результатах это плохо. Гораздо проще поймать изменение которого быть не должно и сразу пофиксить, чем пропустить и ломать голову, когда проект вырастет в 20 раз.

Волгоградец, спасибо, очень интересно.
Старый 31.03.2010 18:32 shaman4d вне форума
shaman4d
 
Аватар для shaman4d
Ай молодца +1 (я тоже всегда завидовал людям, которые могут вить веревки)
Старый 21.04.2010 21:36 chingachgoog вне форума
chingachgoog
 
Аватар для chingachgoog
Цитата:
И вот, прочитав несколько книг, я увидел что не так уж это и сложно.
А что за книги?
Старый 21.04.2010 23:06 Волгоградец вне форума
Волгоградец
 
Аватар для Волгоградец
Вот несколько
Game Physics - David H. Eberly
Game Physics Engine Development - Ian Millington
Physics for Game Developers - David M Bourg
Mathematics and Physics for Programmers - Danny Kodicek
Essential Mathematics for Games and Interactive Applications - James M. Van Verth
И конечно блоги, статьи и форумы.
Старый 22.04.2010 14:51 chingachgoog вне форума
chingachgoog
 
Аватар для chingachgoog
Т.е. все не русскоязычное?
Старый 22.04.2010 15:32 Волгоградец вне форума
Волгоградец
 
Аватар для Волгоградец
Так точно. Из русскоязычных только gamedev.ru и тамошние спецы.
Старый 22.04.2010 15:43 chingachgoog вне форума
chingachgoog
 
Аватар для chingachgoog
А почему не русские или переведенные на русский?
Есть же. Вот, например: Физика для разработчиков компьютерных игр
Автор: Конгер Д.
Старый 22.04.2010 17:11 Волгоградец вне форума
Волгоградец
 
Аватар для Волгоградец
И все. больше нету ). По крайней мере я не знаю. Да и для меня без разницы на каком языке читать. Просто у меня сложилось мнение, что хороших русских книг по программированию нет (есть либо переведенные, но джентльмены предпочитают оригиналы, либо лажа), поэтому я русские даже не рассматриваю. Но про эту книгу ничего не скажу, не знаю.
Старый 06.05.2010 18:18 Yurbalife вне форума
Yurbalife
Простите, мне стало интересно, чем отличается скалярное произведение _х * vесtоr.у - _у * vесtоr.х, это в классе VVесtоr2D, и _х * vесtоr.х + _у * vесtоr.у со вторым понятно, нашел формулу, еще есть формула с произведением длин на косинус угла между ними. Если не трудно, объясните, пожалуйста.
Старый 06.05.2010 18:47 Волгоградец вне форума
Волгоградец
 
Аватар для Волгоградец
_х * vесtоr.у - _у * vесtоr.х - это векторное произведение или crossProduct. По идее оно должно возвращать вектор, который перпендикулярен двум перемножаемым векторам (например - если векторно умножить обычные оси x и y - то в результате получим ось z, которая перпендикулярна и x и y - т.е. плоскости, содержащей оба этих вектора). Но в 2D это не нужно, поэтому я возвращаю скалярную величину. Она может быть нужна для определения направления вращения.
И да, еще можно определить и dotProduct и crossProduct с помощью тригонометрических выражений. Результат одинаковый, но скорость выполнения разная.
Помимо всего сказанного есть еще другие применения - в википедии есть примеры.
Старый 08.05.2010 11:29 Герыч вне форума
Герыч
 
Аватар для Герыч
векторное произведение векторов A и B в 2D можно интерпертировать как скалярное произведение A и перпендикуляра к B.

В частности это можно использовать, чтобы разложить вектор по двум перпендикулярным составляющим. Если e - какое-либо единичное направление,
то A = e*(A,e)+eперп. * (A,еперп),
где еперп=(ey,-ex). То есть e*(A,e)+eперп. * [A,е]

Может пригодиться, когла надо выделить тангенсальную и нормальную составляющую скорости, чтобы к примеру применить трение на поверхности.
 

 


Часовой пояс GMT +4, время: 03:05.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.