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

Физика Тряпичной куклы(Ragdoll)

Опубликованно: 14.06.2017, 21:50
Последняя редакция, Andry: 01.10.2017 20:33

Ragdoll статья из Википедии

JMonkeyEngine3 имеет встроенную поддержку физики jBullet через пакет com.jme3.bullet. Физика не только несет ответственность за передачу столкновений, но и делает возможными шарниры и суставы. Один из примеров суставов физики — физика Тряпичной куклы(Ragdoll), показанная здесь.

ragdoll

Примеры кода

  • TestRagDoll.java (Совет: кликните что бы тянуть ragdoll)
  • TestBoneRagdoll.java — Этот ragdoll заменяет модель персонажа фальшивой в момент,«выстрела, чтобы имитировать падающего человека. (Также обратите внимание на DoF конечностей.)

Подготовка физики игры

  1. Создайте SimpleApplication с BulletAppState
    • Это дает нам PhysicsSpace для PhysicControl
  2. Добавить физический пол (фигура столкновений куб с массой ноль)

Создание Ragdoll

RagDoll — это простой «человек (манекен), который вы строите из фигур столкновения цилиндров. Ragdoll имеет 11 конечностей: 1 для плеч, 1 для тела, 1 для бедер; Плюс 2 руки и 2 ноги, которые состоят из двух конечностей. В вашей игре вы, скорее всего, замените цилиндры своими (лучше выглядящими) моделями конечности. В этом примере здесь мы просто используем простые цилиндры.

Конечность

Поскольку вы просто создаете ragdoll для этого примера, все конечности имеют одинаковую фигуру, и вы можете написать простой вспомогательный метод для их создания. Функция возвращает PhysicalControl с CollisionShape с указанием ширины, высоты, местоположения и вращения (по вертикали или по горизонтали), которые вы указываете. Вы выбираете CapsuleCollisionShape (цилиндр с закругленным верхом и снизу), чтобы конечности плавно сливались друг с другом.

private Node createLimb(float width, float height, Vector3f location, boolean rotate) {
        int axis = rotate ? PhysicsSpace.AXIS_X : PhysicsSpace.AXIS_Y;
        CapsuleCollisionShape shape = new CapsuleCollisionShape(width, height, axis);
        Node node = new Node("Limb");
        RigidBodyControl rigidBodyControl = new RigidBodyControl(shape, 1);
        node.setLocalTranslation(location);
        node.addControl(rigidBodyControl);
        return node;
}

Вы пишете собственный вспомогательный метод для инициализации конечностей. Посмотрите на снимок экрана выше для ориентации.

  • Все цилиндры имеют одинаковый диаметр, 0,2f.
  • Вы делаете тело и плечи длиннее других конечностей, 1.0f вместо 0.5f.
  • Вы определяете координаты для размещения конечностей, чтобы сформировать человека.
  • Плечи и бедра — горизонтальные цилиндры, поэтому мы устанавливаем вращение в true.
Node shoulders = createLimb(0.2f, 1.0f, new Vector3f( 0.00f, 1.5f, 0), true);
Node     uArmL = createLimb(0.2f, 0.5f, new Vector3f(-0.75f, 0.8f, 0), false);
Node     uArmR = createLimb(0.2f, 0.5f, new Vector3f( 0.75f, 0.8f, 0), false);
Node     lArmL = createLimb(0.2f, 0.5f, new Vector3f(-0.75f,-0.2f, 0), false);
Node     lArmR = createLimb(0.2f, 0.5f, new Vector3f( 0.75f,-0.2f, 0), false);
Node      body = createLimb(0.2f, 1.0f, new Vector3f( 0.00f, 0.5f, 0), false);
Node      hips = createLimb(0.2f, 0.5f, new Vector3f( 0.00f,-0.5f, 0), true);
Node     uLegL = createLimb(0.2f, 0.5f, new Vector3f(-0.25f,-1.2f, 0), false);
Node     uLegR = createLimb(0.2f, 0.5f, new Vector3f( 0.25f,-1.2f, 0), false);
Node     lLegL = createLimb(0.2f, 0.5f, new Vector3f(-0.25f,-2.2f, 0), false);
Node     lLegR = createLimb(0.2f, 0.5f, new Vector3f( 0.25f,-2.2f, 0), false);

У вас теперь есть план человека. Но если вы сейчас запускаете приложение, отдельные конечности будут падать независимо друг от друга так как у ragdoll все еще не хватает суставов.

Сустав

Как и раньше, вы пишете небольшой вспомогательный метод. На этот раз его цель — быстро соединить две конечности A и B в точке соединения, которую мы укажем.

  • Преобразование A и B вектора connectionPoint из глобального координатного пространства в локальное координатное пространство.
  • Используйте ConeJoint, специальный сустав, который приближается к степени свободы, которую обычно имеют конечности. Конструктор ConeJoint требует наличия двух узлов и двух локальных опорных координат, которые мы только что определили.
  • Установите ограничения суставов, чтобы разрешить качание, но не скручивание.
private PhysicsJoint join(Node A, Node B, Vector3f connectionPoint) {
        Vector3f pivotA = A.worldToLocal(connectionPoint, new Vector3f());
        Vector3f pivotB = B.worldToLocal(connectionPoint, new Vector3f());
        ConeJoint joint = new ConeJoint(A.getControl(RigidBodyControl.class),
                                        B.getControl(RigidBodyControl.class),
                                        pivotA, pivotB);
        joint.setLimit(1f, 1f, 0);
        return joint;
}

Используйте вспомогательный метод для соединения всех конечностей с суставами, которые находятся, на одном конце конечности.

join(body,  shoulders, new Vector3f( 0.00f,  1.4f, 0));
join(body,       hips, new Vector3f( 0.00f, -0.5f, 0));
join(uArmL, shoulders, new Vector3f(-0.75f,  1.4f, 0));
join(uArmR, shoulders, new Vector3f( 0.75f,  1.4f, 0));
join(uArmL,     lArmL, new Vector3f(-0.75f,  0.4f, 0));
join(uArmR,     lArmR, new Vector3f( 0.75f,  0.4f, 0));
join(uLegL,      hips, new Vector3f(-0.25f, -0.5f, 0));
join(uLegR,      hips, new Vector3f( 0.25f, -0.5f, 0));
join(uLegL,     lLegL, new Vector3f(-0.25f, -1.7f, 0));
join(uLegR,     lLegR, new Vector3f( 0.25f, -1.7f, 0));

Теперь ragdoll связан. Если вы сейчас запустите приложение, кукла упадет, но конечности останутся вместе.

Прикрепление всего к сцене

Мы создаем один (без физики) Узел с именем ragDoll и присоединяем к нему все остальные узлы.

ragDoll.attachChild(shoulders);
ragDoll.attachChild(body);
ragDoll.attachChild(hips);
ragDoll.attachChild(uArmL);
ragDoll.attachChild(uArmR);
ragDoll.attachChild(lArmL);
ragDoll.attachChild(lArmR);
ragDoll.attachChild(uLegL);
ragDoll.attachChild(uLegR);
ragDoll.attachChild(lLegL);
ragDoll.attachChild(lLegR);

Чтобы использовать ragdoll в сцене, мы присоединяем его главный узел к rootNode и к PhysicsSpace.

rootNode.attachChild(ragDoll);
bulletAppState.getPhysicsSpace().addAll(ragDoll);

Применение сил

Чтобы тянуть куклу в верх, вы можете добавить обработчик ввода, который вызывает следующее действие:

Vector3f upforce = new Vector3f(0, 200, 0);
shoulders.applyContinuousForce(true, upforce);

Мы можем использовать действие, чтобы поднять куклу и вернуть ее на ноги, или что-то еще. Подробнее о Силах здесь.

Обнаружение столкновений

Ознакомьтесь с разделом PhysicsCollisionEvent в документации по общей физике о том, как обнаруживать столкновения. Вы можете обнаруживать столкновения конечностей с конечностями и полом и инициировать игровые события.

Рекомендации

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


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

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

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