Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество
Главная
    Документация jMonkeyEngine
        jMonkeyEngine Уроки и Документация
            Документация для продвинутых пользователей
                Физика петлей и суставов

Физика петлей и суставов

Опубликованно: 13.06.2017, 9:21
Последняя редакция, Andry: 13.06.2017 22:45

JMonkeyEngine3 имеет встроенную поддержку физики jBullet через пакет com.jme3.bullet.

Игровая физика используется не только для расчета столкновений, но и для имитации шарниров и суставов. Подумайте о цепях шкивов, шатких канатных мостах, качающихся маятниках или (ловушке) дверных и сундучных петлях. Физика является отличным дополнением, например, для action игр или игр головоломок.

В этом примере мы создадим маятник. Сустав(joint) — это (невидимая) связь между корпусом маятника и сцеплением. Вы увидите, что вы можете использовать то, что вы узнали из простого маятника, и применить это к другим суставным/шарнирным объектам (канатные мосты и.т.д.).

Примеры кода

Обзор этого приложения с физикой

  1. Создадим SimpleApplication с BulletAppState
    • Это дает нам PhysicsSpace для PhysicalControls
  2. Для маятника мы используем Spatial с PhysicsControl, и мы применяем к ним физические силы.
    • Части «маятника» являются Physics Control Spatial с Collision Shapes.
    • Мы создаем фиксированный hookNode и динамический pendulumNode.
  3. Мы можем при желании, применить силу и повернуть сустав на петле, или позволить свободно суставу реагировать на силу тяжести.
    • Для физических сил мы будем использовать метод joint.enableMotor();

Создание фиксированного узла

hookNode — это фиксированная точка, из которой висит маятник. У неё нет массы.

Node hookNode=PhysicsTestHelper.createPhysicsTestNode(
    assetManager, new BoxCollisionShape(new Vector3f( .1f, .1f, .1f)),0);
hookNode.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f,0,0f));

rootNode.attachChild(hookNode);
getPhysicsSpace().add(hookNode);

Для веревочного моста было бы два фиксированных узла, где мост прикреплен к склону горы.

Создание динамического узла

pendulumNode — является динамической частью конструкции. У него есть масса.

Node pendulumNode=PhysicsTestHelper.createPhysicsTestNode(
    assetManager, new BoxCollisionShape(new Vector3f( .3f, .3f, .3f)),1);
pendulumNode.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f,-1,0f));
rootNode.attachChild(pendulumNode);
getPhysicsSpace().add(pendulumNode);

Для тросового моста каждый набор досок будет одним динамическим узлом.

Понимание DOF, суставов и шарниров

PhysicsHingeJoint является невидимой связью между двумя узлами — здесь между телом маятника и сцеплением. Почему шарниры и суставы представлены одним и тем же классом? Шарниры и суставы имеют что-то общее: они ограничивают механическую степень свободы(mechanical degree of freedom) (DOF) другого объекта.

Рассмотрим свободно падающий «объект без привязки в физическом 3D пространстве: он имеет 6 DOF:

  • Он перемещается по 3 осям
  • Он вращается вокруг 3 осей

Теперь рассмотрим некоторые примеры объектов с суставами:

  • Индивидуальное звено цепи свободно вращаться и передвигаться, но соединены в цепь, движения связями с окружающими звеньями сильно ограничиваются.
  • Рука человека может вращаться вокруг некоторых осей, но не вокруг любых. Плечевой сустав позволяет одно и ограничивает другое.
  • Шарнир двери является одним из самых ограниченных типов соединений: он может вращаться только вокруг одной оси.

Вы поймете, что при создании любого типа соединения важно правильно указать DOF, которые ограничивают суставы, и DOF, разрешенные суставом. Для типичных DOF конечностей персонажа ragDoll jME даже предлагает специальный сустав ConeJoint.

Создание соединения

Вы создаете HingeJoint после того, как создали узлы, которые должны быть соединены вместе. В фрагменте кода вы видите, что для конструктора HingeJoint требуются два узла. Вы также должны указывать оси и опорные точки — это степени свободы, о которых вы только что слышали.

private HingeJoint joint;
...
  public void simpleInitApp() {
    ...
    // hookNode и pendulumNode создаются здесь...
    ...

    joint=new HingeJoint(hookNode.getControl(RigidBodyControl.class), // A
                     pendulumNode.getControl(RigidBodyControl.class), // B
                     new Vector3f(0f, 0f, 0f),  // опорная точка локальная для to A
                     new Vector3f(0f, 1f, 0f),  // опорная точка локальная для B
                     Vector3f.UNIT_Z,           // DoF оси of A (ось Z)
                     Vector3f.UNIT_Z  );        // DoF оси of B (ось Z)

Позиция опорной точки будет в (0,0,0) в глобальном 3D пространстве. В локальном пространстве A, которое находится в (0,0,0) и в локальном пространстве B (помните, что позиция B была установлена на (0, -1,0)), которая равна (0,1,0).

Задайте следующие параметры для каждого соединения:

  • PhysicsControl A и B — два узла, которые должны быть соединены
  • Vector3f опорная точка A и опорная точка B — координаты точки присоединения относительно A и B
    • Точки обычно лежат на поверхности PhysicsControl Spatial, редко посередине.
  • Vector3f axisA и axisB — вокруг которых оси каждого узла могут вращаться.
    • В нашем примере мы ограничиваем маятник колебанием только вдоль оси Z.

Не забудьте добавить все объекты суставов в физическое пространство, точно так же, как и с любыми физическими объектами.

bulletAppState.getPhysicsSpace().add(joint);
Если вы хотите, чтобы сустав был видимым, прикрепите Геометрию к динамическому узлу и переместите его в исходное положение.

Применение физических сил

Вы можете применить силы к динамическим узлам (те, которые имеют массу), и посмотреть, как перетаскиваются другие связанные («сцепленные») объекты.

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

Метод вызова сустава — enableMotor().

joint.enableMotor(true, 1, .1f);
joint.enableMotor(true, -1, .1f);
  1. Включите двигателя, задав true
  2. Укажите скорость, с которой соединение должно вращаться вокруг указанной оси.
    • Используйте положительные и отрицательные числа для изменения направления.
  3. Укажите импульс для этого двигателя. Тяжелые массы нуждаются в большем импульсе для перемещения.

Когда вы отключите двигатель, сцепленные узлы снова подвергаются воздействию силы тяжести:

joint.enableMotor(false, 0, 0);

Переведено для jmonkeyengine.ru, оригинал
Автор перевода: Andry

Добавить комментарий

jMonkeyEngine.ru © 2017. Все права сохранены.