По умолчанию, каждый “from”
объект, добавленный в
CollisionTraverser, проверяется
на коллизии с каждым узлом коллизий,
находящимся в сцене. Тест на коллизии
с видимой геометрией не проходится. Для
базового приложения этого может быть
достаточно, однако, часто может
потребоваться больше контроля над
коллизиями. Для этого в Панде предусмотрены
маски коллизий. Каждый CollisionNode имеет
две маски: "from" — используется,
когда узел выступает в качестве "from"
-объекта ( т. е. он добавлен в
CollisionTraverser), и
"into", которая используется если
узел является "into" объектом (т. е.
находится в графе сцены и проходит
проверку на коллизии).
В дополнение, узлы GeomNodes также имеют
маску "into", и могут выступать в роли
"into"-объектов. (В то время как, только
CollisionNode может быть "from"-объектом.)
Перед тем как будет проведена проверка
коллизий для двух узлов, производится
побитовое логическое сравнение их
масок. В частности, "from"-маска
from-объекта, и "into"-маска into-объекта.
Если результат сравнения не равен 0, то
происходит проверка коллизии, в противном
случае, объекты игнорируются.
------------------------
Примечание переводчика:
Небольшое пояснение для тех у кого фраза
побитовое логическое сравнение вызывает
макушечно-чесательный рефлекс. Ни для
кого, думаю не секрет, что компьютер
использует двоичную систему счисления,
т. е. данные представляются в виде 0
и 1. Соответственно, и любое число может
быть представлено в виде нулей и единиц.
Так вот, для побитового сравнения
используется это самое двоичное (битовое)
представление. Каждый бит одного числа
логически сравнивается с соответствующим
битом второго числа. Логически — значит
используется логическое «И» - конъюнкция.
Правила логического
сравнения:
0 и 0 = 0
0 и 1 = 0
1 и 0 = 0
1 и 1 = 1
Пример: сравним два числа
6 и 2
6: 0110
2: 0010
0 и 0 = 0 ; 1 и 0 = 0 ; 1 и 1 = 1 ; 0
и 0 = 0
итого получаем число
0010, что в десятичном представлении
является числом 2. Результат больше нуля
и коллизия будет обсчитана
Сравним 6 с 1 6: 0110
1: 0001
0 и 0 = 0 ; 1 и 0 = 0 ; 1 и 0 = 0 ; 0
и 1 = 0
Результат 0000 т. е.
просто 0 — коллизия не будет рассчитываться.
Запустив
интерпретатор питона можно так же
проверить результат — это делается с
помощью оператора & т. е.
пишем 6&2, нажимаем enter
и получаем 2
------------------------
Маска назначается с помошью класса
BitMask32, который является 32-хбитным целым
числом с некоторыми дополнительными
методами, позволяющими оперировать
отдельными битами числа.
Маска from должна назначаться
напрямую для node, а
не для nodePath:
nodePath.node().setFromCollideMask(BitMask32(0x10))
Однако, маска into для удобства может быть
назначена и для NodePath; это так же рекурсивно
заменит маски для узлов того же уровня
и подчинённых:
nodePath.setCollideMask(newMask, bitsToChange, nodeType)
Параметр newMask определяет маску, которая
должна быть назначена. Остальные
параметры опциональны; если они опущены,
то каждому узлу, включённому в nodePath
будет назначена маска newMask как маска
into.
Параметр bitsToChange определяет набор
битов для изменения, в случае, если
менять предполагается не всю маску;
нулевые биты в bitsToChange не будут
модифицированы.
Параметр nodeType определяет тип узлов,
чья маска будет модифицирована. Например,
CollisionNode.getClassType()
- изменены будут только CollisionNodes.
Примеры:
nodePath.setCollideMask(BitMask32(0x10))
Устанавливает маску into для nodePath, и всех
его чайлдов, в значение 0x10 вне зависимости
от предыдущего значения.
nodePath.setCollideMask(BitMask32(0x04), BitMask32(0xff))
Заменяет 8 нижних битов для nodePath и всех
его чайлдов значением 0x04, оставляя
неизменными верхние 24 бита.
Значения по умолчанию для CollisionNode
могут быть получены с спомощью
CollisionNode.getDefaultCollideMask() ,
а для GeomNode — с помощью
GeomNode.getDefaultCollideMask() .
Например, если вы хотите создать
CollisionNode коллидящийся с видимой геометрией,
можно попробовать сделать что-то вроде
этого:
nodePath.node().setFromCollideMask(GeomNode.getDefaultCollideMask())
Функция NodePath.getCollideMask() возвращает
объединение масок для узла и всех его
чайлдов. Поскольку NodePath.setCollideMask()
вызывается рекурсивно для чайлдов узла,
то эффект следующего кода может
кардинально отличаться от того, что
казалось бы он делает на первый взгляд:
nodePath.setCollideMask(nodePath.getCollideMask())
Если вам нужно установить маску только
для определённой части модели, то можно
воспользоваться функцией find():
box=loader.loadModel("box")
box.find("**/Cube;+h").setCollideMask(BitMask32.bit(0))
|