Другие примитивы и хуллы в компаунде.
Итак, в прошлый раз я рассказал о том, как сделать компаунд из кубиков. Теперь надо рассказать о других примитивах, там всё по аналогии. Итак, давайте возьмём за основу пример 8 и попробуем усложнить столик, добавив в него новые примитивы.
Для начала давайте уберём ножки стола, сначала из меша, теперь он создаётся вот так:
Global TableMesh = CreateCube()
ScaleMesh TableMesh,3,0.3,1.5
PositionMesh TableMesh,0,3.3,0
HideEntity TableMesh
И из создания тела:
Desc = pxCreateCompoundDesc()
Sh = pxCompoundAddCubeShape(Desc,3,0.3,1.5)
pxCompoundSetShapePos(Sh,0,3.3,0)
Global TableBody = pxCreateCompound(Desc,1)
pxBodySetFlagCollision TableBody,0
Теперь нас просто создаются столешницы. Надо заюзать капсулу.
В прошлый раз я создавал меш капсулы вот этой фуцнкцией, в данном случае она тоже пригодится (кстати я её маленько подправил):
Function CreateCapsule(height#,radius# )
cyl = CreateCylinder()
ScaleMesh cyl, radius, height-radius*0.5, radius
sph = CreateSphere()
ScaleMesh sph, radius,radius,radius
PositionMesh sph, 0,height-radius*0.5,0
AddMesh sph, cyl
PositionMesh sph, 0,-height*2+radius,0
AddMesh sph, cyl
FreeEntity sph
Return cyl
End Function
Итак, к мешу столешницы приделаем ножку-капсулу:
leg = CreateCapsule(1.5,1.0)
PositionMesh leg,0,1.5,0
AddMesh leg, TableMesh
FreeEntity leg
Чтобы создать капсулу в компаунде, потребуется команда:
pxCompoundAddCapsuleShape(Desc%, radius#, height#)
|
Создаёт шейп-капсулу в дескрипторе. Аргументы:
Desc - дескриптор, куда добавлять, radius и height - радиус и высота капсулы (см. выше пост про примитивы = полная аналогия). Возвращает хендл созданного шейпа.
Теперь к дескриптору компаунда приделаем шейп-капсулу с теми же параметрами:
Sh = pxCompoundAddCapsuleShape(Desc,1.0,1.5)
pxCompoundSetShapePos(Sh,0,1.5,0)
Всё, теперь можно запускать и давить на пробел. Как видите, получился столик с ножкой-капсулой. Т.к. нижний её конец круглый, то "столик" должен падать, однако если его просто создать и никак не воздействовать, этого не происходит (наверное, вы раньше замечали это и с капсулами-телами). Это происходит потому что капсула в данном случае идеальна и столешница тоже находится чётко посередине ножки, т.е. чентр тяжести точно над капсулой. Потому-то она и не сваливается на бок. Давайцте при создании немного поворачивать тело на рандомный угол. Делается это командой (как, вы ещё о ней не знаете?):
pxBodySetRotation (body%, pitch#, yaw#, roll#)
|
Задаёт абсолютный угол поворота. По сути, идентична блицовскому RotateEntity, только для физических тел. Параметры: body - тело, которое собираемя вертеть, pitch, yaw, roll - соответственно углы.
Используем эту функцию чтобы повернуть наш "столик" на рандомный угол при создании:
pxBodySetRotation pxT\body,Rnd(-10,10),Rnd(-10,10),Rnd(-10,10)
Теперь порядок. Можно сделать угол поворота побольше:
Теперь совсем рандомщина
Давайте теперь сделаем капсулу не такую толстую:
leg = CreateCapsule(1.5,0.5)
...
Sh = pxCompoundAddCapsuleShape(Desc,0.5,1.5)
И добавим ей на конец шар. Для этого создадим его сначала в меше:
sph = CreateSphere()
ScaleMesh sph,2,2,2
PositionMesh sph,0,-0.5,0
AddMesh sph, TableMesh
FreeEntity sph
А теперь надо создать и в компаунде. Тут используем команду:
pxCompoundAddSphereShape(Desc%, radius#)
|
Создаёт шейп-сферу в дескрипторе. Аргументы: Desc - дескриптор, куда добавлять, radius# - радиус сферы. Возвращает хендл созданного шейпа.
Создадит теперь и сферу-шейп и расположим её так же, как и меш:
Sh = pxCompoundAddCapsuleShape(Desc,0.5,1.5)
pxCompoundSetShapePos(Sh,0,1.5,0)
Можно запускать. Вот что получилось у меня:
Полный код примера вы найдёте в аттаче "PhysXExample9.zip"
Так, со сферами и с капсулами разобрались. Далее по списку - цилиндер.
int pxCompoundAddCylinderShape( Desc%, radius#, height#, nbEdge%)
|
Создаёт шейп-цилиндр в дескрипторе. Аргументы:
Desc - дескриптор, куда добавлять, radius и height - радиус и высота цилиндра, nbEdge - количество граней цилиндра. Полная аналогия с pxBodyCreateCylinder (см. выше). Возвращает
- кто бы мог подумать? - хендл созданного шейпа.
Заюзаем на практике. За основу я взял Пример 9. Уберите оттуда всё, что связано с капсулой и сферой, они тут не понадобятся. Теперь заюзаем цилиндр вместо ножки стола. Создадим его в меше:
leg = CreateCylinder(8)
ScaleMesh leg,1.0,1.5,1.0
PositionMesh leg,0,1.5,0
AddMesh leg, TableMesh
FreeEntity leg
Тут всё Блицевское, так что, я думаю, понятно.
Далее создаём цилиндр в дескрипторе (опять же, скайлим его точно так же и позиционируем точно так же, как и меш):
Sh = pxCompoundAddCylinderShape(Desc,1,1.5,8)
pxCompoundSetShapePos(Sh,0,1.5,0)
Запускаем - ок. Давайте-ка уберём ту рандомщину с поворотами:
pxBodySetRotation pxT\body,Rnd(-100,100),Rnd(-100,100),Rnd(-100,100)
Заметьте - теперь падая на ронвый пол, даже если тело получает слабые толчки, то всё равно становится ровно, в отличие от капсулы, потому что донышко у него плоское.
Полный код примера вы найдёте в аттаче "PhysXExample10.zip"
Ну что ж, теперь - самое интересное - Хулл!
Потому как хулл может быть произвольной формы, то и возможностей он даёт гораздо больше. Как и обычное тело-хулл, хулл-шейп создаётся из массива точек. Рассмотрим такую команду:
pxCompoundAddHullShape(Desc%,vbank%,nvert%)
|
Создаёт в дескрипторе шейп-хулл, возвращает его хендл. Аргументы: Desc - дескриптор, куда создавать, vbank - банк вершин, nvert - количество вершин в том банке.
Структура vbank'а - такая же как и при создании хулла-тела, то есть такая:
Размер банка - количество вершин * 12
n*12+0 - координата X n-ной вершины (вещественное число - float)
n*12+4 - координата Y n-ной вершины (вещественное число - float)
n*12+8 - координата Z n-ной вершины (вещественное число - float)
|
Как и в случае с pxBodyCreateHull, этот банк можно загружать из файла, можно брать прямо из меша и т.п., воспользуемся вторым случаем. Вот функция, которая создаёт хулл в дескрипторе на основе меша и возвращает его (шейпа) хендл:
Function CompoundCreateAddHullShape%(Desc, mesh%)
Local nsurf = CountSurfaces(mesh)
Local nvert = 0
For ns = 1 To nsurf
Local surf = GetSurface(mesh,ns)
nvert = nvert + CountVertices(surf)
Next
vbank = CreateBank(nvert*4*3)
nv = 0
For ns = 1 To nsurf
surf = GetSurface(mesh,ns)
nvv = CountVertices(surf)
For nvc = 0 To nvv - 1
PokeFloat vbank,nv*12+0,VertexX(surf,nvc)
PokeFloat vbank,nv*12+4,VertexY(surf,nvc)
PokeFloat vbank,nv*12+8,VertexZ(surf,nvc)
nv = nv+1
Next
Next
Local bbb%= pxCompoundAddHullShape(Desc,vbank, nvert)
FreeBank vbank
Return bbb
End Function
Как видите, она создаёт банк координат вершин из меша, а потом из него создаёт в указанном дескрипторе шейп.
Внимание! Перед импортом меша из Макса, проделайте действия, описанные в посте №4 про хуллы, чтобы избежать глюков (ResetXForm и т.д.)!
Теперь опробуем на деле. Возьмём Пример 10. Уберём из него создание меша и компаунда стола и перепишем его опять.
Но для начала нам понадобится моделька чтоыб из неё делать хулл. Далеко ходить не надо, используем модельку из
поста №4.
Загрузим её(предварительно убрав все "упоминания" о старом объекте):
Global TableMesh = LoadMesh("PressPapier.b3d")
HideEntity TableMesh
Это, значит, визуальный меш. Так пока и оставим.
Тперь загрузим-ка упрощённый меш для создания из него хула (надеюсь, понятно почему?):
TableMeshPhys = LoadMesh("PressPapierPhys.b3d")
Далее - создадим дескриптор как обычно
Desc = pxCreateCompoundDesc()
И чуть пониже, чтоб не откладывать в долгий ящик, сразу создание компаунда и удаление меша:
FreeEntity TableMeshPhys
Global TableBody = pxCreateCompound(Desc,1)
pxBodySetFlagCollision TableBody,0
Теперь надо создать шейпы. Попробуем создать хулл при помощи вышевыложенной функции:
Sh = CompoundCreateAddHullShape(Desc,TableMeshPhys)
Запускаем, тестим. Ну, это у нас получилось как обычные хуллы (т.к. хулл-то в дескрипторе всего один
) Теперь попробуем создать ещё один такой же хулл и повернуть относительно первого на 90°...
Sh = CompoundCreateAddHullShape(Desc,TableMeshPhys)
Это я создал второй такой же хулл.
Да, чуть не забыл, чтобы повернуть шейп в дескрипторе, нужно использовать эту команду:
pxCompoundSetShapeRot(shape%,pitch#,yaw#,roll#)
|
Поворачивает шейп. Аргументы: shape - хендл шейпа, pitch#,yaw#,roll# - соответственно углы в радианах.
Итак, поднимем новый шейп относительно первого, перевернём его чтобы креглешом смотрел вверх и ещё на 90°:
pxCompoundSetShapeRot(sh,0,90,180)
pxCompoundSetShapePos(sh, 0, 6, 0)
Вот я его перевернул и переместил. Теперь то же, но для меша:
TableMesh2 = CopyMesh(TableMesh)
RotateMesh TableMesh2,0,90,180
PositionMesh TableMesh2,0,6,0
AddMesh TableMesh2,TableMesh
FreeEntity TableMesh2
Скопировал, перемернул, переместил, аттачнул, удалил лишний.
В-общем-то, должно быть понятно. Запускаем, тестим, теперь у нас компоунд из нескольких хуллов:
Полный код примера вы найдёте в аттаче "PhysXExample11.zip"
Собственно, хуллов, как и примитивов, в дескрипторе (-> в компаунде) можно создавать несколько и комбинировать различными путями. Возможно в середине недели напишу "довесочек" типа создания уже реального предмета из хуллов. В следующую субботу напишу статью, наконец, про силы и импульсы - это самые шишечки
На сегодня у меня всё, спасибо за внимание.