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

Столкновение и пересечение

Опубликованно: 08.05.2017, 20:28
Последняя редакция, Andry: 29.06.2017 18:04

Термин столкновение может использоваться для обозначения физических взаимодействий (когда физические объекты сталкиваются, толкаются и сталкиваются друг с другом), а также к не физическим пересечениям в трехмерном пространстве. Эта статья посвящена не физическим (математическим) столкновениям.

Нефизическое обнаружение столкновения интересно, потому что оно использует меньше вычислительных ресурсов, чем обнаружение физического столкновения. Нефизические вычисления выполняются быстрее, потому что они не имеют никаких побочных эффектов, таких как толкание других объектов или их отскакивание от них. Такие задачи, как выбор мыши легко реализуются с помощью математических методов, таких как трассировка лучей и пересечения. Опытные разработчики оптимизируют свои игры путем поиска путей имитации определенных (в противном случае дорогостоящих физических) взаимодействий нефизическим способом.

Пример: Одним из примеров оптимизации является физика колеса автомобиля. Вы могли бы сделать колёса полностью физическими дисками, а jME рассчитывала бы каждую крошечную физическую силу — звучит очень точным? Но это полный перебор, и слишком медленно для гоночной игры. Более производительное решение — сбрасывать четыре невидимых луча вниз с автомобиля и вычислять пересечения с полом. Эти не физические колеса требуют (в простейшем случае) только четыре вычисления за такт для достижения эффект, которые игроки вряд ли смогут отличить от настоящих.

Collidable

Интерфейс com.jme3.collision.Collidable объявляет один метод, который возвращает, колличество столкновений которые были найдены между двумя Collidables: collideWith(Collidable other, CollisionResults results).

  • Объект результатов com.jme3.collision.CollisionResults представляет собой ArrayList сопоставимых объектов com.jme3.collision.CollisionResult.
  • Вы можете выполнить итерацию над CollisionResults, чтобы определить другие стороны, участвующие в столкновении.
    Обратите внимание, что jME подсчитывает все стокновения, это означает, что луч, пересекающий к примеру куб, будет учитывать два удара, один на фронте, где луч входит, и один на спине, где луч выходит.
Методы CollisionResults  Применение
size()  Возвращает количество объектов CollisionResult.
getClosestCollision()  Возвращает CollisionResult с самым низким расстоянием.
getFarthestCollision()  Возвращает CollisionResult с самым дальним расстоянием.
getCollision(i)  Возвращает CollisionResult с индексом i.

Объект CollisionResult содержит информацию о второй стороне события столкновения.

Методы CollisionResult  Применение
getContactPoint()  Возвращает координату точки контакта на второй стороне, как Vector3f.
getContactNormal()  Возвращает вектор нормали в точке контакта, как Vector3f.
getDistance()  Возвращает расстояние между Collidable и второй стороной, как float.
getGeometry()  Возвращает геометрию второй стороны.
getTriangle(t)  Связывает t с треугольником t на сетке второй стороны, которая была удалена.
getTriangleIndex()  Возвращает индекс треугольника на сетке второй стороны, который был достигнут.

Пример кода

Предположим, у вас есть две collidables a и b и вы хотите обнаружить столкновения между ними. Сторонами столкновения могут быть геометрия, привязки узлов с геометриями (включая rootNode), плоскости, квадраты, линии или лучи. Важным ограничением является то, что вы можете столкнуться только с геометрией или ограничивающими объемами или лучами. (Это означает, например, что должно быть Type Node или Geometry и b соответственно типа BoundingBox, BoundingSphere или Ray.)

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

  // Вычислить результаты обнаружения
  CollisionResults results = new CollisionResults();
  a.collideWith(b, results);
  System.out.println("Number of Collisions between" +
      a.getName()+ " and " + b.getName() + ": " + results.size());
  // Используйте результаты
  if (results.size() > 0) {
    // Как реагировать при обнаружении столкновения
    CollisionResult closest  = results.getClosestCollision();
    System.out.println("What was hit? " + closest.getGeometry().getName() );
    System.out.println("Where was it hit? " + closest.getContactPoint() );
    System.out.println("Distance? " + closest.getDistance() );
  } else {
    // Как реагировать, когда не произошло столкновение
  }
}

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

  // Вычислить результаты
  CollisionResults results = new CollisionResults();
  a.collideWith(b, results);
  System.out.println("Number of Collisions between" + a.getName()+ " and "
   + b.getName() " : " + results.size());
  // Используйте результаты
  for (int i = 0; i < results.size(); i++) {
    // Для каждого удара мы знаем расстояние, точку удара, имя геометрии.
    float     dist = results.getCollision(i).getDistance();
    Vector3f    pt = results.getCollision(i).getContactPoint();
    String   party = results.getCollision(i).getGeometry().getName();
    int        tri = results.getCollision(i).getTriangleIndex();
    Vector3f  norm = results.getCollision(i).getTriangle(new Triangle()).getNormal();
    System.out.println("Details of Collision #" + i + ":");
    System.out.println("  Party " + party + " was hit at " + pt + ", " + dist + " wu away.");
    System.out.println("  The hit triangle #" + tri + " has a normal vector of " + norm);
  }

Зная расстояние от столкновений будет полезно, например, когда пересекаются линии и лучи с другими объектами.

(Ограничивающий Объем)Bounding Volumes

com.jme3.bounding.BoundingVolume — это интерфейс для работы с контейнером набора точек. Все BoundingVolumes являются Collidable и используются в качестве оптимизация для вычисления не физических столкновений быстрее: всегда быстрее вычислять пересечение простых фигур, таких как сферы и коробки, чем сложных фигур, таких как модели.

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

Везде где быстрый темп действий, например шутеры используют BoundingVolumes в качестве оптимизации. Оберните все сложные модели в более простые формы — в итоге вы получите одинаково полезные результаты обнаружения столкновений, но быстрее. Подробнее об ограничениях объемов …

Поддерживаемые типы:

  • Type.AABB = Выровненный по осям ограничивающий прямоугольник(Box), это означает, что она не вращается, что делает его менее точным. Com.jme3.bounding.BoundingBox — это прямоугольный параллелепипед, используемый в качестве контейнера для группы вершин куска геометрии. У BoundingBox есть центр и экстенты от этого центра вдоль осей x, y и z. Это ограничивающий объем по умолчанию, поскольку он довольно быстро генерируется и дает лучшую точность, чем ограничивающая сфера.
  • Type.Sphere: com.jme3.bounding.BoundingSphere — это сфера, используемая в качестве контейнера для группы вершин куска геометрии. A BoundingSphere имеет центр и радиус.
  • Type.OBB = Ориентированный ограничивающий прямоугольник. Этот ограничивающий прямоугольник является более точным, поскольку он может вращаться вместе с содержимым, но является более дорогостоящим в вычислительном отношении. (В настоящее время не поддерживается.)
  • Type.Capsule = Цилиндр с закругленными концами, также называемый «круглая сфера». Обычно используется для мобильных символов. (В настоящее время не поддерживается.)
Примечание. Если вы ищете ограничивающий объем для физических объектов, используйте CollisionShapes.

Применение

Например, вы можете использовать Bounding Volumes на пользовательских сетках или сложных нефизических фигурах.

mesh.setBound(new BoundingSphere());
mesh.updateBound();

Столкновение Сеток и Графа Сцены

Один из поддерживаемых Collidable — это сетки с объектами графа сцены. Чтобы выполнить запрос обнаружения конфликтов для графа сцены, используйте `Spatial.collideWith(). Это пройдёт графа сцены и вернет обнаруженные столкновения сетки. Обратите внимание, что первое столкновение с определенным графом сцены может занять много времени, это связано с тем, что для сеток должна быть создана специальная структура данных «Инициирование интервальной иерархии (BIH)». В более поздний моменты сетка может измениться, и дерево BIH станет устаревшим, в этом случае вызовите Mesh.createCollisionData() в измененной сетке, чтобы обновить дерево BIH.

Пересечение

com.jme3.math.Ray — бесконечная линия с началом, направлением и без конца; Тогда как com.jme3.math.Line — это бесконечная линия только с направлением (нет начала, нет конца).

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

  • Нажмите, чтобы выбрать: Вы можете определить, что совершен щелчек пользователя, и луч брошен с камеры вперед в направлении камеры. Теперь определите ближайшее столкновение луча с rootNode, и у вас будет выбранный объект.
  • Поле зрения: Бросьте луч от игрока в сторону другого игрока. Затем вы обнаруживаете все столкновения этого луча с другими сущностями (стены и листва с оконными стеклами) и используете это, чтобы рассчитывать, насколько вероятно, что можно увидеть другого игрока.
Эти простые, но мощные тесты пересечения лучём поверхности называются Ray Casting. В отличие от более продвинутой техники трассировки лучей, Ray Casting не следит за отражением луча после первого попадания — луч просто идет прямо.

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

TODO:

  • Bounding Interval Hierarchy (com.jme3.collision.bih.BIHNode)
  • com.jme3.scene.CollisionData

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

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

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