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

Компаунды, или дешёвые невыпуклые тела с коллизией.

В предыдущих постах я рассказывал о Хуллах и Тримешах. Теперь настала очередь компаундов.

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



Теория закончилась, переходим к практике. Возьмём за основу пример 2. Там можно было по нажатию на пробел создавать кубики. Попробуем соорудить вместо них что-то типа столов. Для начала нам потребуется моделька стола. Её можно было бы создать в максе, но, я думаю, связь между компаундом и моделью будет яснее, если мы соберём эту подельку прямо в блитзе, из кубиков:

Global TableMesh = CreateCube()
ScaleMesh TableMesh,3,0.3,1.5
PositionMesh TableMesh,0,3.3,0

leg = CreateCube()
ScaleMesh leg,0.3,1.5,0.3
PositionMesh leg,2.7,1.5,-1.2
AddMesh leg, TableMesh
PositionMesh leg,0,0,2.4
AddMesh leg, TableMesh
PositionMesh leg,-5.4,0,0
AddMesh leg, TableMesh
PositionMesh leg,0,0,-2.4
AddMesh leg, TableMesh
FreeEntity leg
HideEntity TableMesh
Собственно, в глобальную переменную создаётся модель стола и скрывается. Можете временно убрать HideEntity и убедиться, всё ли в порядке.
Теперь надо создать для этой модели физическое тело - компаунд. Так как мы собирали модельку из кубиков, то и компаунд собирать будем из таких же кубиков.

Опять немного теории.
Создать Compound несколько сложнее, чем простое тело. Сначала создаётся КомпаундДескриптор. Это своего рода контейнер информации о геометрии будущего компаунда. В него заносятся выпуклые физические тела, затем поворачиваются и располагаются как надо в соответствии с тем, что мы хотим получить. Затем из Дескриптора создаётся непосредственно Компаунд, к которому можно прикладывать силу, указывать координаты и т.п., т.е. всё, что можно творить с обычным физическим телом.

Итак,

pxCreateCompoundDesc()
Функция создаёт дескриптор и возвращает его хендл. Параметров нет.

Создадим дескрипторв нашей проге:

Desc = pxCreateCompoundDesc()
Теперь в него нужно добавлять физические тела (кстати, они в данном случае называются Shape'ы), т.к. сам он "пустой".
Чтобы добавить в него кубик, нужна команда:

pxCompoundAddCubeShape(Desc%, dx#, dy#, dz#)
Добавляет кубик к дескриптору. Возвращает хендл созданного Shape'а. Параметры:
Desc - дескриптор, куда добавлять кубик.
dx, dy, dz - масштаб по осям для кубика (аналогично pxBodyCreateCube, смотрите выше подробное описание если что-то упустили)

Обратите внимание: массу указывать не надо. Как бы это не физическое тело, а фигура, не имеющая массы (возможно, потому она и называется Shape а не Body). Она будет общая для всего компаунда и указывается при его (компаунда, не дескриптора) создании. Центр массы будет рассчитан там же.

Итак, добавим по очереди кубики в наш дескриптор, чтобы они соответствовали модели стола. Так как мы модель стола собирался из кубиков, то все параметры для позиционирования и для масштабирования у нас есть, осталось только использовать их. Создадим столешницу, напомню, что при создании модели код выглядел так:

Global TableMesh = CreateCube()
ScaleMesh TableMesh,3,0.3,1.5
PositionMesh TableMesh,0,3.3,0
Теперь такой же кубик делаем и для дескриптора:

Sh = pxCompoundAddCubeShape(Desc,3,0.3,1.5)
Это я создал куб в дескрипторе, отмасштабировал его, и хендл созданного шейпа у меня теперь лежит в переменной Sh. А как же его переместить? Для этого пригодится команда:

pxCompoundSetShapePos(shape%, x#, y#, z#)
Устанавливает позицию для шейпа. Аргументы: shape - хендл шейпа, x#, y#, z# - координаты куда надо устанавливать шейп.
Собственно, аналог PositionEntity, только для Shape'ов дескриптора. Ничего сложного тут нет.

Теперь переместим и наш шейп туда, где он должен стоять (а стоять он должен там же, где и столешница-меш, то есть в 0,3.3,0) :

pxCompoundSetShapePos(Sh,0,3.3,0)
По аналогии создаём и располагаем кубики и для ножек стола:

Sh = pxCompoundAddCubeShape(Desc,0.3,1.5,0.3)
pxCompoundSetShapePos(Sh,2.7,1.5,-1.2)
Sh = pxCompoundAddCubeShape(Desc,0.3,1.5,0.3)
pxCompoundSetShapePos(Sh,2.7,1.5,1.2)
Sh = pxCompoundAddCubeShape(Desc,0.3,1.5,0.3)
pxCompoundSetShapePos(Sh,-2.7,1.5,-1.2)
Sh = pxCompoundAddCubeShape(Desc,0.3,1.5,0.3)
pxCompoundSetShapePos(Sh,-2.7,1.5,1.2)
Так, дескриптор создан и все шейпы в ём - тоже. Теперь настало время создавать непосредственно физическое тело. Это делается командой:

pxCreateCompound (Desc, mass#)
Создаёт физическое тело из дескриптора. Возвращает хендл этого самого тела. Аргументы: Desc - дескриптор (естественно со всеми уже заранее созданными в нём шейпами) , mass - масса создаваемого тела.

Вот теперь давайте создадим физическое тело нашего стола:

Global TableBody = pxCreateCompound(Desc,1)
Из ранее созданного дескриптора создалось тело с массой 1.
Так как это обыкновенное тело, с ним можно вытворять всё то же что и с любым другим телом. Давайте отключим ему коллизию (как в более ранних примерах мы это делали чтобы тело-эталон не мешалось):

pxBodySetFlagCollision TableBody,0
Готово. Теперь изменим пару строчек в функции CreatepxCube чтобы вместо кубиков создавались столы:

pxC\mesh = CreateCube()
pxC\body = pxBodyCreateCube(1,1,1,1)
меняем на:

pxC\mesh = CopyEntity(TableMesh)
pxC\body = pxCopyBody(TableBody)
В персой строке вместо модели куба копируется меш стола, а во второй - вместо создания физического куба копируется тело - компаунд стола. Всё. Можно запускать и нажимать на пробле. Только вот они создются все в одной точке и потому падают ровной стопкой. Добавим некоторый элемент рандомности при создании:

pxBodySetPosition pxC\body,x+Rnd(-10,10),y,z+Rnd(-2,2)
Вот, теперь вся невыпуклость компаундов налицо. Ножки столов засовываются между ножек других столов и т.д. (прямо-таки камасутра для мебели )



Однако обратите внимание на такую вещь (вы, наверное, уже заметили): если два компаунда создать "друг в друге" (если слишком часто нажимать на пробел), то сложные компоунды иногда не смогут "выскочить" друг из друга, как это ранее легко делали хуллы и так и останутся слипшимися. Это не есть гуд, но что поделать. Так что следите за тем, где вы создаёте компаунды.

Полный код примера вы найдёте в аттаче "PhysXExample8.zip"
(там я переименовал типы и функции из Cube в Table чтобы они соответствовали своему названию )

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

Следующий пост ждите примерно через неделю
Вложения
Тип файла: zip PhysXExample8.zip (708 байт, 1914 просмотров)
__________________
Мои проекты:
Анальное Рабство
Зелёный Слоник
Дмитрий Маслов*
Различие**
Клюква**

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


Последний раз редактировалось ABTOMAT, 17.01.2009 в 19:54.
(Offline)
 
Ответить с цитированием
Эти 30 пользователя(ей) сказали Спасибо ABTOMAT за это полезное сообщение:
3dr1aN (17.01.2009), ACTIVATOR (20.01.2009), baton4ik (01.02.2010), Blender (17.01.2010), Brain (15.01.2010), CRASHER (18.01.2009), den (27.07.2010), Diablomania (14.08.2009), Egor Rezenov (17.10.2010), h1dd3n (31.01.2009), H@NON (18.01.2009), Harter (04.11.2009), HolyDel (17.01.2009), Hurrit (16.05.2010), is.SarCasm (20.02.2010), Main Cry (23.04.2009), m_512 (13.02.2009), Nex (23.06.2009), NitE (17.01.2009), PackegerX (03.02.2010), Randomize (20.01.2009), Sashka007 (17.01.2009), SBJoker (17.01.2009), Slavik (24.06.2009), strayhnd (30.06.2010), Tadeus (17.01.2009), tormoz (17.01.2009), viper86 (08.02.2009), WhiteBlack (27.07.2010), ІГРОГРАЙКО (02.07.2009)