Показать сообщение отдельно
Старый 01.02.2009, 03:11   #8
ABTOMAT
Ференька
 
Аватар для ABTOMAT
 
Регистрация: 26.01.2007
Адрес: улица Пушкина дом Колотушкина
Сообщений: 10,741
Написано 5,461 полезных сообщений
(для 15,675 пользователей)
Ответ: Учебник по PhysX Wrapper для Blitz3D

Луч, силы, импульсы.

Теперь дела пойдут повеселее! Будем толкать наши физические тела!
Итак, для начала немного подготовимся.
Возьмём за основу пример №2, тот, где можно было создавать кубики.
Немного переделаем функцию создания куба, чтобы она ещё и возвращала ссылку на его тип:
Function CreatepxCube.pxCube(x#,y#,z#)
...
Return pxC
И создадим для опытов один кубик, в самом начале:
Cube.pxCube = CreatepxCube(0,10,0)
Пробел пока не долбим. В центре внимания - этот куб. Можно даже его раскрасить, чтобы потом мы могли в дальнейшем его отличать от остальных:
EntityColor Cube\mesh,200,0,0
Ну-с, приступим. Научим наш куб прыгать. Пускай он прыгает по пробелу, а онг у нас занят. Невелика проблема, я перенёс создание куба на клавишу Tab:
If KeyHit(15) Then CreatepxCube(0,10,0)
Переходим непосредственно к физиксу. Чтобы кубик подпрыгнул, к нему надо применить силу, а точнее, импульс. Вообще, в курсе физики это считается разными вещами, но из-за схожести эффекта и (видимо) расчётов, сила, импульс и некоторые другие явления объединены в одну функцию. Вот она:
pxBodyAddForce(body%, vx#, vy#, vz#, mode%)
Применяет силу к центру массы тела. Внимание! Нельзя применять силу к статическим телам (масса = 0)

body - тело, на которое применяется сила (импульс, ...), vx, vy, vz - вектор силы (чем он "длиннее" - тем большая сила приложится), mode - режим.

Если с первыми четырьмя аргументами всё более-менее ясно, то на последнем остановимся поподробней. Итак, этот параметр указывает, что именно делать с телом:
0 - приложить силу. По заветам товарища Ньютона, a=F/m, ускорение, которое получает материальная точка, прямо пропорционально приложенной силе и обратно пропорционально массе, т.е. чем большую силу приложат к телу, тем большее оно приобретёт ускорение, но чем больше масса тела, тем это самое ускорение будет меньше. Собсно, этой командой мы прилагаем силу, а тело, в зависимости, от своей массы, приобретает то или иное ускорение. При одной и той же силе тело массой 1 улетит дальше чем тело с массой 10. На деле будет выглядеть, как будто тело куда-то тянут или толкают. Используется для постоянного толкания тела. Например, для перемещения персонажа.
1 - приложить импульс. Здесь происходит резкий толчок. Ускорение так же зависит от массы. По определению импульса, P=m*V, то есть импульс, применённый на тело с аргументом-вектором P, будет выглядеть так, как будто в тело врезалось тело с массой m с мгновенной скоростью V, но так, что вектор mV = вектору P. Очень удобно, если по каким-то причинам нужно смоделировать столкновение тел, а моделировать одно их них нельзя или не желательно. Например, выстрел пулей в ящик можно сымитировать, описав пулю шариком и пульнуть им в ящик, чтобы они столкнулись. Но зачем нам моделировать ещё одно лишнее физическое тело, когда достаточно применить на ящик импульс, чтобы он отскочил?
2 - действие на скорость (или change of speed, как гласит документация). Это импульс, игнорирующий массу объекта. Эффект будет тот же, как если бы у тела, на которое применяют сиё, была бы масса 1. То есть если к двум телам (массы 1 и 100) сответственно применить импульс, скажем, 10, то первое подскочит, а второе еле дрогнет. А если к тем же самым телам применить точно такой же change of speed, то оба подпрыгнут совершенно одинаково.
3 - smooth impulse, сглаженный импульс. Тот же импульс что и с параметром 1, но применяется более плавно. Если честно, от обычного отличается не слишком сильно, хотя выглядит и правда мягче. Думаю, для имитации попадания пули подойдёт простой импульс, а для толчка ногой - сглаженный.
4 - smooth change of speed - собственно, тот же change of speed, но более мягкий. Аналогично паре 1 и 3.
5 - ускорение. Та же сила (параметр 0), но игнорирующая массу, аналогично паре 1 и 2.

Кстати в дальнейшем слова "сила" и "импульс" часто будут синонимами (если не указано обратное) т.к. с нашей, юзерской точки зрения, это почти одно и то же.

В теоретической физике вышеописанное - разные вещи, но на практике мы просто получим сообщение разного ускорения телу для разных случаев. Используйте то, что будет более удобно в конкретной ситуации. Естественно никто не станет кратковременно применять огромную силу на тело, чтобы заставить его подпрыгнуть, и не станет пытаться толкать тело вперёд маленькими импульсами, когда можно долговременно применять на него силу. И незачем использовать change of speed, когда придётся вычислять значение исходя из массы вручную, когда impulse учтёт эту массу автоматом.

Фактически, чаще всего используются только режимы 0 (сила) и 1 (импульс), остальные - крайне редко.

Ну что ж, заставим наше тело подпрыгивать по нажатию пробела. Для этого применим на него импульс с вертикальным вектором 10:
If KeyHit(57) pxBodyAddForce Cube\body,0,10,0,1
Запускаем, смотрим, тело и правда прыгает. Даже может взлететь, т.к. когда оно в воздухе, то прыгать дальше ему всё равно не запрещают. Конечно, тут надо определять, находится ли тело на земле, если да - то разрешить прыгать, если нет - то нет... Но это отдельная больная тема, о которой я расскажу в дальнейшем. А пока что я рассказываю не об этом и такого "прыжка" вполне хватит для опытов.

Теперь попробуем применять силу. Заставим тело толкаться в разные стороны по нажатию клавиш WASD.
If KeyDown(17) pxBodyAddForce Cube\body,0,0,10,0
По нажатию W я применил силу с вектором вперёд. Тестируем. Работает. Кстати, попробуйте понажимать пробел и W - прямо запуск космического корабля. Хотя если задуматься - там двигатели могут давать постоянную тягу вперёд и толчки вверх, так что в таком случае наблюдаемая сцена вполне реальна.
Добавим другие клавиши:
If KeyDown(17) pxBodyAddForce Cube\body,0,0,10,0
If KeyDown(31) pxBodyAddForce Cube\body,0,0,-10,0
If KeyDown(30) pxBodyAddForce Cube\body,-10,0,0,0
If KeyDown(32) pxBodyAddForce Cube\body,10,0,0,0
Теперь кубик можно толкать в разных направлениях.

Помните игру Ballance? Собственно, с PhysX'ом вот так всё просто. Вставить сюда вместо кубика шар, убрать прыжки, загрузить уровень в trimesh - и будет вам Ballance

Попробуем (табуляцией) засыпать наш кубик другими кубами. Теперь можно подпрыгнуть из груды, распихивать их. Конечно, для распихивания сила явно маловата, но ведь можно и увеличить!

Вот, собственно, и всё о pxBodyAddForce. Теперь настала пора познакомиться с её сестрой-близнецом:

pxBodyAddForceAtLocalPos(body%,vx#,vy#,vz#,px#,py# ,pz#,mode%)
Применяет силу/импульс к телу в позиции его локальных координатах.

body - тело, на которое применяется сила (импульс, ...), vx, vy, vz - вектор силы,px,py,pz - локальные координаты точки куда прилагать силу, mode - режим.

Как вы помните, в pxBodyAddForce сила применялась к центру массы тела. Тут же можно применить силу в какую угодно точку тела, указав её локальные координаты. Это очень удобно, т.к. если тело перевернётся, то не придётся заново вычислять координаты точки куда прилагать силу в соответствии с поворотом тела, т.к. она локальна.
Все остальные параметры 100% совпадают с pxBodyAddForce.

Попробуем заюзать на практике. Давайте сначала уберём всё, что было ранее связано с WASD:
If KeyDown(17) pxBodyAddForce Cube\body,0,0,10,0
If KeyDown(31) pxBodyAddForce Cube\body,0,0,-10,0
If KeyDown(30) pxBodyAddForce Cube\body,-10,0,0,0
If KeyDown(32) pxBodyAddForce Cube\body,10,0,0,0
И давайте теперь попробуем "подвешивать" куб за один из его углов. Для этого изменим код "прыжка". Теперь будем использовать pxBodyAddForceAtLocalPos, во-вторых, режим пускай будет 0 (простая сила), а в-третьих, передадим туда локальные координаты правого верхнего угла:
If KeyDown(57) pxBodyAddForceAtLocalPos Cube\body,0,10,0,1,1,1,0
Прямо как на крючке))
Кстати, можно указывать позицию не только на поверхности тела, но и за его пределами.

Теперь рассмотрим другую команду:

pxBodyAddLocalForceAtLocalPos(body%,vx#,vy#,vz#,px #,py#,pz#,mode%)
Применяет локальную силу/импульс к телу в позиции его локальных координатах.

body - тело, на которое применяется сила (импульс, ...), vx, vy, vz - локальный вектор силы, px,py,pz - локальные координаты точки куда прилагать силу, mode - режим.

Собственно, это аналог предыдущей функции, но теперь и сила применяется локально. То есть если мы укажем вектор 0,0,1, то тело будет двигаться вперёд. Есви оно перевернётся, то оно будет двигаться туда, где перед у тела. Если pxBodyAddForce - это в некоторой степени аналог TranslateEntity, то pxBodyAddLocalForce - аналог MoveEntity.

Так, как же нам может оно здесь пригодиться? Давате включим фантазию. Представим, что наш кубик - это катер на воздушной подушке над ледяной пустыней. У такого катера сзади 2 огромных вентилятор - один справа, другой слева. Когда работают оба, катер движетя вперёд. Когда один из них (например, правый) снижает обороты или вовсе замолкает, то левый поворачивает весь катер вправо. Или как, например, если обе гусеницы танка крутятся одинаково, то танк едет прямо, а если одна едет быстрее другой, то танк поворачивается в ту сторону, которая едет медленней.

Дык вот, сделаем нашему кубику такие "двигатели". Пускай левый работает по клавише A, а правый - по клавише D. Для этого будем применять силы в тех точках, где бы располагались "турбины". Пускай они располагаются на 10 влево и вправо соответствующий. Так далеко - чтобы результат был более явным. Сила каждого - 10 по оси Z. Вот что у меня вышло:
If KeyDown(30) pxBodyAddLocalForceAtLocalPos Cube\body,0,0,10,-10,0,0,0
If KeyDown(32) pxBodyAddLocalForceAtLocalPos Cube\body,0,0,10,10,0,0,0
Также я думаю, надо бы удлиннить кубик при создании, чтобы видеть эффект:
ScaleEntity pxC\Mesh, 1,1,5
pxC\body = pxBodyCreateCube(1,1,5,1)
pxBodySetPosition pxC\body,x,y,z
Вот, теперь запускаем и давим сначала обе клавиши - едет прямо. Отпускаем одну - поворачивается. Типа, гоночки Конечно, до гонок далеко: не хватает, в первую очередь, колёс, да и ускорения просто дикие. Но главное - теперь вы знаете как использовать локальную силу в локальной позиции.
__________________
Мои проекты:
Анальное Рабство
Зелёный Слоник
Дмитрий Маслов*
Различие**
Клюква**

* — в стадии разработки
** — в стадии проектирования
Для проектов в стадии проектирования приведены кодовые имена


Последний раз редактировалось ABTOMAT, 01.02.2009 в 04:00.
(Offline)
 
Ответить с цитированием
Эти 26 пользователя(ей) сказали Спасибо ABTOMAT за это полезное сообщение:
3dr1aN (01.02.2009), baton4ik (02.02.2010), Blender (17.01.2010), Brain (15.01.2010), Buraki (02.02.2009), den (27.07.2010), Diablomania (14.08.2009), H@NON (01.02.2009), HolyDel (01.02.2009), Hurrit (16.05.2010), indri (05.06.2009), Main Cry (23.04.2009), Mr_F_ (20.07.2009), m_512 (13.02.2009), Nex (23.06.2009), NitE (01.02.2009), PackegerX (03.02.2010), Randomize (17.10.2009), Slavik (24.06.2009), strayhnd (30.06.2010), Tadeus (01.02.2009), tormoz (01.02.2009), TxN (15.08.2009), viper86 (08.02.2009), WhiteBlack (27.07.2010), ІГРОГРАЙКО (02.07.2009)