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

Другие примитивы и хуллы в компаунде.

Итак, в прошлый раз я рассказал о том, как сделать компаунд из кубиков. Теперь надо рассказать о других примитивах, там всё по аналогии. Итак, давайте возьмём за основу пример 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"

Собственно, хуллов, как и примитивов, в дескрипторе (-> в компаунде) можно создавать несколько и комбинировать различными путями. Возможно в середине недели напишу "довесочек" типа создания уже реального предмета из хуллов. В следующую субботу напишу статью, наконец, про силы и импульсы - это самые шишечки На сегодня у меня всё, спасибо за внимание.
Вложения
Тип файла: zip PhysXExample9.zip (830 байт, 1684 просмотров)
Тип файла: zip PhysXExample10.zip (678 байт, 1685 просмотров)
Тип файла: zip PhysXExample11.zip (3.2 Кб, 1703 просмотров)
__________________
Мои проекты:
Анальное Рабство
Зелёный Слоник
Дмитрий Маслов*
Различие**
Клюква**

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

(Offline)
 
Ответить с цитированием
Эти 22 пользователя(ей) сказали Спасибо ABTOMAT за это полезное сообщение:
3dr1aN (25.01.2009), baton4ik (01.02.2010), Blender (17.01.2010), Brain (15.01.2010), den (27.07.2010), Diablomania (14.08.2009), h1dd3n (26.01.2009), H@NON (01.02.2009), HolyDel (27.07.2010), indri (05.06.2009), Main Cry (23.04.2009), m_512 (13.02.2009), Nex (23.06.2009), Randomize (25.01.2009), Reizel (21.01.2010), Slavik (24.06.2009), strayhnd (30.06.2010), Tadeus (24.01.2009), tormoz (24.01.2009), viper86 (08.02.2009), WhiteBlack (27.07.2010), ІГРОГРАЙКО (02.07.2009)