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

Физика: Гравитация, Столкновения, Силы

Опубликованно: 09.06.2017, 15:55
Последняя редакция, Andry: 01.10.2017 11:11

Физическое моделирование используется в играх и приложениях, где объекты подвергаются воздействию физических сил: подумайте о таких играх, как бильярд и симуляторы гоночных автомобилей. Массивные объекты тянутся под действием силы тяжести, заставляют объекты набирать обороты, трение замедляет их, твердые объекты сталкиваются и отскакивают друг от друга, и.т.д. Игры жанра Action и Adventure также используют физику для реализации твердых препятствий, падений и прыжков.

JMonkeyEngine3 имеет встроенную поддержку jBullet Physics (на основе Bullet Physics) через пакет com.jme3.bullet. В этой статье основное внимание уделяется RigidBodyControl, но также знакомит вас с остальным.

Если вы ищете информацию о том, как реагировать на физические события, такие как столкновения, читайте о слушателях физики.

Технический обзор

JME3 имеет полный, слегка адаптированный, но полностью упакованный API Bullet, который использует обычные математические объекты jME (Vector3f, Quaternion и.т.д.) В качестве входных/выходных данных. Доступны все обычные bullet объекты, такие как RigidBodies, Constraints (называются «Суставы(Joint) в jME3») и различные столкновения фигур. Доступны все форматы сеток(mesh) могут быть преобразованы с jME в bullet.

Объект PhysicsSpace является центральным объектом в bullet, и все объекты у которых должна быть физика, должны быть добавлены в него. Вы можете создать несколько физических пространств(Physics Space), чтобы иметь несколько независимых физических симуляций или запускать симуляции в фоновом режиме, для тех которые вы делаете в другом темпе. Вы также можете создать Bullet PhysicsSpace в jME3 с com.jme3.bullet.BulletAppState, который запускает PhysicalSpace вместе с циклом обновления, что является самым простым способом создания экземпляра физического пространства. Его можно запустить в режиме, где он работает параллельно с рендерингом, но синхронизируется с циклом обновления, поэтому вы можете безопасно применять изменения физики во время update() вызывая Controls и SimpleApplication.

Объекты базового bullet также доступны и простые в использовании как и control, которые могут быть привязаны к spatial элементам, чтобы непосредственно контролировать их силами и влиянием физики. Например, RigidBodyControl включает простой конструктор, который автоматически создает корпус столкновения фигур или сетки сталкивающиеся с фигурами на основе заданной входной массы и сетки с прилагающимся к ней spatial. Это дает возможной применять физику на геометрию так же просто, как spatial.addControl(new RigidBodyControl(1));

Из-за некоторых различий в том, как bullet и jME обрабатывают управление сценой и другими объектами, есть кое-что, что нужно запомнить о реализации control:

  • Столкновения фигур не обновляется автоматически при изменении сетки spatial.
    • Вы можете обновить его, подключив control или самостоятельно, используя CollisionShapeFactory.
  • В bullet параметр масштаба находится в фигуре столкновения (который эквивалентен сетке в jME3), а не на RigidBody, поэтому вы не можете изменять масштаб фигуру столкновения без изменения масштаба любого другого RigidBody ссылающегося на него
    • Обратите внимание, что вы должны распределять столкновения фигур, это важно, и что файлы j3o загружены из файла, также выполняются при инициализации дважды, поэтому это нужно учитывать.
  • Объекты с физикой остаются в физическом пространстве, когда их spatial отсоединяются от графа сцены!
    • Используйте PhysicsSpace.remove(physicsObject) или просто physicsControl.setEnabled(false); что бы затем удалить их из PhysicsSpace
  • Если вы применяете силы к объекту с физикой в вызове update(), силы могут не применяться, потому что внутренне bullet все еще работает со скоростью 60 кадров в секунду, тогда как ваше приложение может работать на уровне 120.
    • Вы можете использовать интерфейс PhysicsTickListener что бы регистрироваться в физическом пространстве и использовать метод preTick(), чтобы убедиться, что вы действительно применяете силу в нужный момент.
    • Чтение значений из объектов с физикой в цикле обновления всегда должно давать правильные значения, но они могут не изменяться в течение нескольких кадров, по той же причине.
  • Чтение или запись объектов с физикой во время фазы визуализации не рекомендуется, так как это происходит, когда физическое пространство ступенчато и может привести к повреждению данных. Вот почему отображение отладки не работает должным образом в потоке BulletAppState
  • Bullet всегда использует только координаты мира, нет такой концепции, как узлы, поэтому объект будет перемещен в местоположение в мире без учета его родительской spatial.
    • Вы можете настроить это поведение, используя метод setApplyPhysicsLocal() для физических control, но помните, что пространство физики все еще работает только в координатах мира, чтобы вы могли визуально отделять вещи, которые на самом деле все еще будут сталкиваться в физическом пространстве.
    • Используйте локальное применение для имитации, например: для внутренней физической системы проходящего поезда, просто создайте еще один BulletAppState и добавьте все модели с control физики в локальном режиме к узлу. Когда вы перемещаете узел, физике будет все равно, но объекты будут перемещаться вместе с узлом.

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

  • 1 единица длины (1.0f) равна 1 метр,
  • 1 единица веса (1.0f) составляет 1 килограмм,
  • Большинство значений крутящего момента и вращения выражены в радианах.

Bullet физика работает по умолчанию со скоростью 60 кадров в секунду. Эта скорость не зависит от фактической частоты кадров и не блокирует частоту кадров 60 кадров в секунду. Вместо этого, когда фактическое значение fps выше, чем физическая частота кадров, система отобразит интерполированные позиции для объектов с физикой. Когда частота кадров ниже, чем частота кадров физики, физическое пространство будет выполняться несколько раз за кадр, чтобы компенсировать недостающие вычисления.

Внутренне обновление и синхронизация реальных объектов с физикой в BulletAppState происходит следующим образом:

  • Обратные вызовы столкновений (BulletAppState.update())
  • Пользовательское Обновление (simpleUpdate в основном цикле, update() в Control и AppStates)
  • Физика для Графа сцены синхронизации и применения (updateLogicalState())
  • Пошаговая физика (до или параллельно с Application.render())

Примеры кода

Примеры полного кода:

Приложение с Физикой

Краткий обзор того, как написать приложение jME с физическими возможностями:

Для получения доступа к объекту physicalSpace выполните в приложение один раз описанные ниже шаги:

  • Сделайте свое приложение расширением класса com.jme3.app.SimpleApplication.
  • Создайте поле BulletAppState:
    private BulletAppState bulletAppState;
  • Инициализируйте свой bulletAppState и присоедините его к менеджеру состояния:
    public void simpleInitApp() {
        bulletAppState = new BulletAppState();
        stateManager.attach(bulletAppState);
В вашем приложении вы всегда можете получить доступ к BulletAppState через ApplicationStateManager:

BulletAppState bas = app.getStateManager().getState(BulletAppState.class);

Для каждого Spatial, который вы хотите сделать с физикой:

  1. Создайте CollisionShape.
  2. Создайте PhysicalControl из CollisionShape и значения массы.
  3. Добавьте PhysicalControl в свой Spatial.
  4. Добавьте PhysicalControl в PhysicalSpace.
  5. Прикрепите Spatial к rootNode (как обычно).
  6. (Необязательно) Внедрите интерфейс PhysicsCollisionListener для ответа на PhysicsCollisionEvent.

Давайте посмотрим на детали:

Создание CollisionShape

CollisionShape — упрощенная фигура, для которой физика легче вычислять, чем для истинной фигуры модели. Этот упрощающий подход значительно ускоряет моделирование.

Прежде чем вы сможете создать Physics Control, вы должны создать CollisionShape из пакета com.jme3.bullet.collision.shapes. (Прочитайте подсказку в разделе «PhysicsControls Примеры кода, как использовать стандартные CollisionShapes по умолчанию для кубов и сфер.)

Без-Сетки(Mesh) CollisionShape  Применение Примеры 
BoxCollisionShape()  Кубическое поведение не катится. Длинные или кубические объекты, такие как кирпичи, ящики, мебель. 
SphereCollisionShape()  Сферическое поведение, может катиться. Компактные объекты, такие как яблоки, футбольные мячи, пушечные ядра, компактные космические корабли. 
CylinderCollisionShape()  Трубчатое и дискообразное поведение может катиться одной стороной. Обширные объекты, такие как столбы.
Диско-образные объекты, такие как колеса, пластины. 
CompoundCollisionShape()  CompoundCollisionShape позволяет настраивать комбинации фигур. Используйте метод addChildShape() на составном объекте, чтобы добавить к нему другие фигуры и поместить их относительно друг друга. Автомобиль с колесами (1 коробка + 4 цилиндра) и.т.д 
CapsuleCollisionShape()  Встроенная составная фигура вертикального цилиндра с одной сферой сверху и одной сферой внизу. Обычно используется с CharacterControls: корпус в форме цилиндра не застревает в углах и вертикальных препятствиях; закругленный с верху и снизу не застревают на лестничных ступенях и наземных препятствиях. Люди, животные. 
SimplexCollisionShape()  Точка физики, линии, треугольник или прямоугольник Фигуры, определяется от однойо до четырех точек. защитное ограждение 
PlaneCollisionShape()  2D-плоскость. Очень быстро. Плоский сплошной пол или стена. 

Все без-сетки CollisionShapes могут использоваться для динамических(dynamic), кинематических(kinematic), а также статических(static) Spatial объектов. (Примеры кода см. Ниже)

Сетка(Mesh) CollisionShape  Применение Примеры 
MeshCollisionShape  Фигуры с точными сетками для статических или кинематических Spatial объектов. Может иметь комплекс фигур с отверстиями и отростками.
Ограничения: Невозможно обнаружить столкновение двух фигур с точными сетками, только фигуры без-сетки могут столкнуться с такой фигурой. Эта Фигура не работает с динамическими Spatial.
Целая статичная модель уровня игры. 
HullCollisionShape  Менее точная фигура для динамических Spatial объектов, которые не могут быть легко предоставлены CompoundShape.
Ограничения: Фигура выпуклая (ведет себя так, как если бы вы упаковали объект), т.е. Отверстия, отростки и.т.д., Не представлены индивидуально.
Динамическая 3D-модель. 
GImpactCollisionShape  Фигура с точной сеткой для динамических Spatial. Использует http://gimpact.sourceforge.net/.
Ограничения: Нагружает CPU, используйте экономно! Мы рекомендуем использовать HullCollisionShape (или CompoundShape) вместо этого для повышения производительности. Столкновения между двумя фигурами с точными сетками не могут быть обнаружены, только фигуры без-сетки могут столкнуться с этой фигурой.
Сложные динамические объекты (например, пауки) в виртуальной реальности или научное моделирование. 
HeightfieldCollisionShape  Фигура с точной сеткой, оптимизированная для статических ландшафтов. Эта фигура намного быстрее, чем другие фигуры с точными сетками.
Ограничения: Требуются данные карты высот. Столкновения между двумя фигурами с точной сеткой не могут быть обнаружены, только фигуры без-сетки могут столкнуться с этой фигурой.
Статические ландшафты. 

На CollisionShape вы можете применить несколько свойств

Методы CollisionShape  Свойства Примеры 
setScale(new Vector3f(2f,2f,2f))  Вы можете изменить масштаб collisionshapes (будь то Simple или Mesh). Однако вы не можете изменить масштаб CompoundCollisionShape. Фигура сферического столкновения изменит свой радиус на основе X-составляющей вектора, прошедшего в. Вы должны масштабировать фигура столкновения, прежде чем присоединять его к physicsSpace, или вы должны считывать её в physicsSpace каждый раз, когда изменяется масштаб. Масштабировать игрока по оси Y на 2:

new Vector3f(1f,2f,1f)

 

Фигуры с точными сетками могут использовать CollisionShapeFactory в качестве конструктора (примеры кода см. Ниже).

Выбирайте простую и наиболее применимую фигуру для сетки, для того что вы хотите сделать: если вы придаете кубу сферическую фигуру столкновения, он будет катиться; Если вы дадите мячу коробчатую фигуру столкновения, он будет лежать а не катится на наклонной плоскости. Если фигура слишком велика, объект, похоже, будет плавать; Если фигура слишком мала, она, похоже, погрузится в землю. Во время разработки и отладки вы можете сделать видимым фигуры столкновений, добавив следующую строку после инициализации bulletAppState:

// JME sdk 3.0.10  и более ранние
bulletAppState.getPhysicsSpace().enableDebug(assetManager);

или

// новые версии
bulletAppState.setDebugEnabled(true);

CollisionShape примеры кода

  • Один из способов использования конструктора и сетки Геометрии для статических Spatial:
    MeshCollisionShape level_shape =
        new MeshCollisionShape(level_geo.getMesh());
  • Один из способов использования конструктора и сетки Geometry для динамических Spatial:
    HullCollisionShape shape =
        new HullCollisionShape(katamari_geo.getMesh());
  • Создание динамической составной фигур для всего Узла и подузлов:
    CompoundCollisionShape myComplexShape =
        CollisionShapeFactory.createMeshShape((Node) myComplexGeometry );
  • Создание динамической фигуры HullCollisionShape (или CompoundCollisionShape с HullCollisionShapes в качестве дочерних элементов) для Геометрии:
    CollisionShape shape =
        CollisionShapeFactory.createDynamicMeshShape(spaceCraft);
  • Угловая, составная фигура состоящая из фигур без сетки и фигур с точной сеткой:
    CompoundCollisionShape boxShape =
        CollisionShapeFactory.createBoxShape((Node) crate_geo);
  • Круглая, без сетки составная фигура:
    SphereCollisionShape sphereShape =
        new SphereCollisionShape(1.0f);

Создание PhysicsControl

BulletPhysics доступны в jME3 через классы PhysicalControls из пакета com.jme3.bullet.control. JME3 PhysicsControl классы непосредственно расширяют объекты BulletPhysics и являются рекомендуемым способом использования физики в приложении jME3. PhysicsControls являются гибкими и могут быть добавлены к любому Spatial, чтобы заставить его действовать в соответствии с физическими свойствами.

Стандартные PhysicsControls  Применение Примеры 
RigidBodyControl  Это наиболее часто используемый PhysControl. Вы можете использовать его для динамических объектов (твердых объектов, которые могут быть подвержены столкновениям, силам или гравитации), для статических объектов (твердых, но не затронутых никакими силами) или кинематических объектов (твердых объектов с дистанционным управлением). Воздействие снарядов, перемещение препятствий, таких как ящики, катящиеся и прыгающие шары, лифты, летающие самолеты и космические корабли.
Твердые неподвижные полы, стены, статические препятствия.
GhostControl  Используйте для обнаружения столкновений и пересечений между физическими объектами. Сам GhostControl нетвердый и невидим. GhostControl движется со Spatial к которому подключен. Используйте GhostControls для реализации пользовательских игровых взаимодействий, добавив их в видимую геометрию. «Радиус-агрессии» монстра, столкновения CharacterControl, детекторы движения, фотоэлектрические датчики тревоги, ядовитые или радиоактивные периметры, пожирающие призраки и.т.д.
Специальные PhysicsControls  Применение Примеры 
VehicleControl
PhysicsVehicleWheel 
Специальный Control используется для «наземных» транспортных средств с подвеской и колесами. Автомобили, танки, навесы, корабли, мотоциклы …
CharacterControl  Специальный Control используется для Ходячих персонажей. Вертикальные ходячие люди, животные, роботы …
RagDollControl  Специальный Control, используемый для разваливания, поворота или падения персоонажей. Падающие люди, животные, роботы, «тряпичные куклы

Нажмите ссылку для получения подробной информации о специальных PhysControls. В этой статье рассказывается о RigidBodyControl.

Physics Control примеры кода

Наиболее часто используемым физический control является RigidBodyControl. Конструктор RigidBodyControl принимает до двух параметров: форму столкновения и массу (floa в килограммах). Параметр массы также определяет, является ли объект динамическим (подвижным) или статическим (фиксированным). Для статического объекта, такого как пол или стена, укажите нулевую массу.

RigidBodyControl myThing_phys =
    new RigidBodyControl( myThing_shape , 123.0f ); // динамичный
RigidBodyControl myDungeon_phys =
    new RigidBodyControl( myDungeon_shape , 0.0f ); // статичный
Если вы дадите своему полу ненулевую массу, он выпадет из сцены!

Далее создайте Геометрию куба с по умолчанию правильным значением BoxCollisionShape:

Box b = new Box(1,1,1);
Geometry box_geo = new Geometry("Box", b);
box_geo.addControl(new RigidBodyControl( 1.0f )); // явная ненулевая масса, неявный BoxCollisionShape

Далее создаём MeshCollisionShape для всей загруженной (статической) сцены:

...
gameLevel.addControl(new RigidBodyControl(0.0f)); // явная нулевая масса, неявный MeshCollisionShape
Сферы и кубы автоматически возвращаются к правильному значению CollisionShape по умолчанию, если вы не укажете CollisionShape в конструкторе RigidBodyControl. Сложные статические объекты могут возвращаются к MeshCollisionShapes, если только это не узел, и в этом случае он станет составной CompoundCollisionShape, содержащей MeshCollisionShape

Добавить PhysicsControl к Spatial

Для каждого Spatial с физической в сцене:

  1. Добавьте PhysicalControl в Spatial.
    myThing_geo.addControl(myThing_phys);
  2. Не забудьте также присоединить Spatial к rootNode, как всегда!

Добавить PhysicsControl для PhysicsSpace

PhysicsSpace является объектом в BulletAppState, который похож на rootNode для Физических Control.

  • Так же, как вы добавляете Геометрию в rootNode, вы добавляете свой PhysicalControl в PhysicalSpace.
    bulletAppState.getPhysicsSpace().add(myThing_phys);
    rootNode.attachChild(myThing_geo);
  • rootNode, также удаляйте PhysicalControl из PhysicalSpace:

    bulletAppState.getPhysicsSpace().remove(myThing_phys);
    myThing_geo.removeFromParent();
Вы можете либо добавить PhysicsControl в PhysicsSpace, либо добавить PhysicsControl в геометрию, а затем добавить геометрию в PhysicsSpace. JME3 понимает оба варианта и результат тот же.

Изменение масштаба PhysicsControl

Чтобы изменить масштаб PhysicalControl, вы должны изменить масштаб принадлежащей ему collisionshape.

MeshCollisionShapes может иметь установленный масштаб, но он работает только при построении геометрии (а не в узле). CompoundCollisionShapes нельзя масштабировать в это время (тип, полученный при создании CollisionShape из узла с использованием импортированных моделей).

Когда вы импортируете модель из blender, она часто приходит как узел (даже если она содержит только 1 сетку), который де-факто автоматически преобразуется в CompoundCollisionShape. Поэтому, когда вы пытаетесь масштабировать это, это не сработает! Ниже приведен пример того, как масштабировать импортированную модель:

// Не масштабируется
// Эта модифицированная версия содержит Node -> Geometry (name = "MonkeyHeadGeom")
Spatial model = assetManager.loadModel("Models/MonkeyHead.j3o");
model.addControl(new RigidBodyControl(0));
// Не будет работать, поскольку теперь это CompoundCollisionShape содержащий MeshCollisionShape
model.getControl(RigidBodyControl.class).getCollisionShape().setScale(new Vector3f(2, 2, 2));
bulletAppState.getPhysicsSpace().add(model);

// Работает отлично
Spatial model = assetManager.loadModel("Models/MonkeyHead.j3o"); // Та же модель
 // ВАЖНО: вы должны перейти к геометрии, чтобы это работало
Geometry geom = ((Geometry) ((Node) model).getChild("MonkeyHeadGeom"));
geom.addControl(new RigidBodyControl(0));
// Отлично работает (масштабирование MeshCollisionShape)
geom.getControl(RigidBodyControl.class).getCollisionShape().setScale(new Vector3f(2, 2, 2));
bulletAppState.getPhysicsSpace().add(geom);

С соответствующим выходом ниже:

PhysicsSpace примеры кода

PhysicsSpace также управляет глобальными физическими настройками. Как правило, вы можете оставить настройки по умолчанию, и вам не нужно будет изменять следующие настройки, но хорошо бы знать, для чего они предназначены:

Методы bulletAppState.getPhysicsSpace()  Применение
setGravity(new Vector3f(0, -9.81f, 0));  Определяет глобальную гравитацию.
setAccuracy(1f/60f);  Определяет физическую точность. Чем выше точность, тем медленнее игра. Уменьшите значение, если объекты проходят друг через друга, или отскакивают странно. (Например, измените значение с 1f / 60f на что-то вроде 1f / 80f.)
setMaxSubSteps(4);  Компенсирует низкий FPS: задает максимальное количество дополнительных шагов, которые будут использоваться в качестве шагов физики, когда игровой fps ниже fps физики. Это поддерживает детерминизм в физике в медленных (низкий-fps) играх. Например, максимальное число из 2 может компенсировать частоты кадров до 30 кадров в секунду (физика имеет точность по умолчанию 60 кадров в секунду). Обратите внимание, что слишком высокое значение этого параметра может привести к тому, что физический движок снизит свой собственный fps в случае его перегрузки.
setWorldMax(new Vector3f(10000f, 10000f, 10000f));
setWorldMin(new Vector3f(-10000f, -10000f, -10000f)); 
Определяет размер физического пространства как два противоположных угла (применяется только к расширенной фазе AXIS_SWEEP).

Задание Физических Свойств

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

На RigidBodyControl вы можете установить следующие физические свойства.

Методы RigidBodyControl  Свойства Примеры 
setGravity(new Vector3f(0f,-9.81f,0f))  Вы можете изменить гравитацию отдельных физических объектов после их добавления в PhysicalSpace. Гравитация — это вектор, указывающий от этого Spatial к источнику силы тяжести. Чем длиннее вектор, тем сильнее гравитация.
Если гравитация является абсолютным направлением для всех объектов (например, на поверхности планеты), установите этот вектор глобально всем объектам через PhysicsSpace, а не отдельно.
Если центр тяжести относительный (например, к черной дыре), то setGravity() на каждом Spatial постоянно корректируйте векторы силы тяжести при каждом такте их цикла update().
Для планеты Земля:

new Vector3f(0f,-9.81f,0f)

 

setMass(1f)  Устанавливает массу в килограммах. Динамические объекты имеют массу > 0,0f. Тяжелым динамическим объектам требуется больше силы для перемещения, а легкие движутся с небольшим количеством силы.
Статические неподвижные объекты (стены, полы, включая здания и террасы) должны иметь массу нуля!
Человек: 60f, мяч: 1.0f
Этаж: 0.0f (!) 
setFriction(1f)  Трение.
Скользкие объекты имеют низкое трение. Земля имеет высокое трение.
Лед, скольский: 0.0f
Почва, бетон, камень: 1.0f 
setRestitution(0.0f)  Прыгательность. По умолчанию объекты не активен (0.0f). Для упругого резинового объекта установите это > 0.0f.
И объект, и поверхность должны иметь ненулевую реституцию для подпрыгивания.
Этот параметр влияет на производительность, поэтому используйте его экономно.
Кирпич: 0.0f
Резиновый шар: 1.0f 
setCcdMotionThreshold()  Количество движения в 1 физический такт, чтобы вызвать непрерывное обнаружение движения в движущихся объектах, которые толкают друг друга. Редко используется, но необходимо, если ваши движущиеся объекты застревают или перекатываются друг на друге. Диаметр от 0,5 до 1 * 

На RigidBodyControl вы можете применить следующие физические силы:

Методы RigidBodyControl  Движение
setPhysicsLocation()  Размещает объекты. Не используйте setLocalTranslation() для объектов с физикой.

Убедитесь в том, что не делаете наложений CollisionShapes при их размещении.

setPhysicsRotation()  Поворачивает объект. Не используйте setLocalRotate() для объектов с физикой.
setKinematic(true)  По умолчанию RigidBodyControl являются динамическими (kinematic=false) и подвержены влиянию сил. Если вы установите kinematic=true, объект больше не будет затронут силами, но он по-прежнему влияет на других. Кинематика твердая и должна иметь массу.
(См. Подробное объяснение ниже.)

Кинематический в сравнении с Динамическим и Статическим

Все объекты с физикой …

  • Не должны перекрываться.
  • Может обнаруживать столкновения и сообщать несколько значений о воздействии.
  • Могут реагировать на столкновения динамически, статически или кинематически.
Свойства  Static Kinematic  Dynamic
Примеры  Неподвижные препятствия: Полы, стены, здания, … Твердые объекты с дистанционным управлением: дирижабли, метеориты, лифты, двери; Сетевые или дистанционно управляемые NPC; Невидимые «воздуховоды для шарниров и суставов.  Интерактивные объекты: вращающиеся шары, перемещаемые ящики, падающие столбы, космический корабль с нулевой g …
Есть ли масса?  нет, 0.0f да[1], >0.0f


    1. Инерция рассчитана для кинематических объектов, и вам нужна масса для этого.

да, >0.0f
Как он движется?  никогда setLocalTranslation();  setLinearVelocity(); applyForce();
setWalkDirection(); for CharacterControl
Как разместить в сцене?  setPhysicsLocation();
setPhysicsRotation();
setLocalTranslation();
setLocalRotation(); 
setPhysicsLocation();
setPhysicsRotation();
Может ли он двигаться и подталкивать других?  нет да  да
Это зависит от силы?
(Падает, когда он в воздухе? Может быть толкнул другими?) 
нет нет  да
Как активировать это поведение? 
setMass(0f);
setKinematic(false);
setMass(1f);
setKinematic(true); 
setMass(1f);
setKinematic(false);

Когда я использую кинематические(Kinematic) объекты?

  • Кинематики твердые, и персонажи могут «стоять на них».
  • Когда они сталкиваются, Kinematics толкает динамические объекты, но динамический объект никогда не толкают кинематику.
  • Вы можете повесить кинематику вверх «в воздухе и прикрепить к ней другие PhysControls, используя шарниры и суставы. Представьте их как «воздушные крюки для летающих авианосцев, плавающие острова в облаках, подвесные мосты, качели, цепи …
  • Вы можете использовать Кинематики для создания мобильных объектов с физикой с дистанционным управлением, таких как передвижные платформы для лифтов, летающие поезда/дирижабли. Вы полностью контролируете движение Кинематики, они никогда не «падают» или «опрокидываются».
Положение кинематического RigidBodyControl автоматически обновляется в зависимости от его Spatial перемещения. Вы перемещаете Spatials с кинематическим RigidBodyControl программно, это означает, что вы пишете код перемещения и вращения в цикле обновления. Вы описываете движение кинематических объектов либо с помощью таких методов, как setLocalTranslation() или move(), либо с помощью MotionPath.

Силы: перемещение динамических объектов

Используйте следующие методы для перемещения динамических объектов с физикой.

Методы PhysicsControl  Движение
setLinearVelocity(new Vector3f(0f,0f,1f))  Установить линейную скорость этого объекта.
setAngularVelocity(new Vector3f(0f,0f,1f))  Установить скорость вращения объекта; Компоненты x, y и z — скорость вращения вокруг этой оси.
applyCentralForce(…)  Переместить (толкнуть) объект один раз с определенным импульсом, выраженный как Vector3f.
applyForce(…)  Переместить (толкнуть) объект один раз с определенным импульсом, выраженный как Vector3f. При желании вы можете указать, где на объекте нажимается сила толчка.
applyTorque(…)  Вращайте (крутите) объект один раз вокруг его осей, выраженный как Vector3f.
applyImpulse(…)  Идеализированное изменение импульса. Это толкание, которое вы будете использовать на бильярдном столе.
applyTorqueImpulse(…)  Идеализированное изменение импульса. Это толкание, которое вы будете использовать на бильярдном столе.
clearForces()  Отменяет все силы (силу, крутящий момент) и.т.д. И останавливает движение.
Технически можно расположить PhysControl с помощью setLocalTranslation(), например чтобы разместить их в исходном положении на сцене. Однако вы должны быть очень осторожны, чтобы не вызывать «невозможное состояние, когда один объект с физикой накладывается с другим! В игре вы обычно используете только сеттеры, показанные здесь.

PhysicsControls также поддерживает следующие расширенные функции:

Методы PhysicsControl  Свойства
setCollisionShape(collisionShape)  Изменяет фигуру столкновения после создания.
setCollideWithGroups()
setCollisionGroup()
addCollideWithGroup(COLLISION_GROUP_01)
removeCollideWithGroup(COLLISION_GROUP_01) 
Группы столкновений представляют собой целые битовые маски — перечисления доступны в CollisionObject. Все объекты с физикой по умолчанию находятся в COLLISION_GROUP_01. Два объекта сталкиваются, когда группа collideWithGroups из одного содержит Collision Group другого. Используйте это, чтобы повысить производительность, группируя объекты, которые никогда не сталкиваются в разных группах (движок экономит время, потому что ему не нужно проверять их).
setDamping(float, float)  Первое значение представляет собой линейный порог, а второй — угловой. Это имитирует демпфирующую силу, например, для подводных сцен.
setAngularFactor(1f)  Задайте величину вращения, которая будет применена. Значение нуля отменяет весь результат вращательной силы. (?)
setSleepingThreshold(float,float)  Устанавливает спящие пороги, которые определяют, когда объект деактивируется для экономии ресурсов. Первое значение представляет собой линейный порог, а второй — угловой. Низкие значения сохраняют объект активным, когда он почти не двигается (медленная точная производительность), высокие значения сразу же заставляют объект спать (неточная скорость). (?)
setCcdMotionThreshold(0f)  Устанавливает количество движения, которое должно произойти в одном физическом такте, чтобы вызвать непрерывное обнаружение движения в движущихся объектах, которые толкают друг друга. Это позволяет избежать проблем с быстрыми объектами, перемещающимися через другие объекты. Установите значение «0» для отключения (по умолчанию).
setCcdSweptSphereRadius(.5f)  Bullet не использует полную фигуру столкновения для непрерывного обнаружения столкновения, вместо этого он использует «развернутую фигуру сферы», чтобы приблизить движение, которое может быть неточным и вызвать странное поведение, такое как объекты, проходящие через друг друга или застревание. Только для быстро движущихся динамических тел.
Вы можете установить ApplyPhysicsLocal(true) для объекта, чтобы он двигался относительно своего локального физического пространства. Вы могли бы сделать это, если вам нужно физическое пространство, которое перемещается с узлом (например, космический корабль с искусственной гравитацией, окруженный нулевым пространством). По умолчанию установлено значение false, и все движения по отношению к миру.

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

  • Несколько объектов слишком медленные? Не злоупотребляйте PhysicalControl. Хотя PhysicalControl «спят», когда они не двигаются, создание мира исключительно из динамических объектов физики быстро приведет вас к пределам возможностей вашего компьютера.
    Решение: Повысьте производительность, заменив некоторые физические Spatial нефизическими Spatial. Используйте нефизические для не-твердых вещей, для которых вам не нужно обнаруживать столкновения — листва, растения, эффекты, призраки, все отдаленные или недоступные объекты.
  • Сложная фигура слишком медленная? Разделение уровня в управляемые части помогает движку повысить производительность: чем меньше ресурсоемкая для CPU в широкой фазе, тем больше фильтрует части сцены, которые вне досягаемости. Вычисляются только столкновения для объектов, которые фактически близки к действию.
    Решение: Огромная статическая модель города или ландшафта никогда не должна загружаться как одна огромная сетка. Разделите сцену на несколько объектов физики, каждый из которых имеет свои собственный столкновение. Выберите наиболее простой CollisionShape; Используйте фигуры с точными сетками только для тех случаев, когда точность важнее скорости. Например, вы можете использовать очень быстрый PlaneCollisionShape для плоских улиц, этажей и внешнего края сцены, если вы держите эти штуки отдельно.
  • Выброс? Если у вас есть узлы с физикой, лихорадочно дрожащие и бросаемые «без видимых причин», это означает, что вы создали невозможное состояние — твердые объекты накладывающиеся друг на друга. Это может произойти, если вы размещаете твердые Spatial объекты слишком близко к другим твердым Spatial, например при перемещении их с помощью setLocalTranslation().
    Решение: Используйте режим отладки, чтобы сделать CollisionShapes видимыми, и убедитесь, что CollisionShapes не накладываются.

    bulletAppState.getPhysicsSpace().enableDebug(assetManager);
  • Багги? Если вы получаете странное поведение, например, физические узлы, проходящие через друг друга, или застревание без причины.
    Решение: Посмотрите на аксессуаров(методы доступа) физического пространства и измените характеристики и другие параметры.
  • Требуется больше интерактивности? Вы можете активно контролировать физику игры путем запуска сил. Вы также можете захотеть настроить реакцию на столкновения, например вычитание здоровья, награждения очками или воспроизведением звука.
    Решение: Чтобы определить, как игра реагирует на столкновения, вы используете «Слушатели физики».

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

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

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