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

Траверс SceneGraph

Опубликованно: 06.05.2017, 22:38
Последняя редакция, Andry: 20.06.2018 16:40

Вы можете выполнять поиск по всему графу сцены и выполнять поиск отдельных Spatial (Узлов и Геометрий) по специальным критериям, таким как название Spatial или класс Spatial, пользовательским данным Spatial или элементам Control Spatial-а. Вы делаете это, когда хотите изменить найденные узлы (переместить их, вызвать метод и.т.п.), но вы не имеете для них локальных переменных.

Примеры использования

Пример 1:

  1. Вы создали процедурный сценарий с большим количеством динамически генерируемых элементов.
  2. Вы хотите найти какой то конкретный Spatial в постоянно меняющихся условиях, и изменить его состояние.

Пример 2:

  1. Вы создали статичную сцену в jMonkeyEngine SDK и экспортировали ей как .j3o-файл.
    Сцена также содержит интерактивные объекты, например излучатель частиц, spatial-ы с пользовательскими данными или spatial-ы с вашими пользовательскими Control-ами.
  2. Вы загружаете .j3o сцену, используя assetManager.
  3. Вы хотите взаимодействовать с одним из интерактивных элементов загруженной сцены, в вашем Java-коде.
    Например, вы хотите вызвать emitAllParticles() у излучателя частиц. Или вы хотите найти все Геометрии NPC с пользовательским CivilianControl и вызвать метод CivilianControl, который заставит их начать действовать.

В этих случаях вы можете использовать SceneGraphVisitorAdapter для идентификации и доступа к рассматриваемым Spatial.

Пример кода

Для каждого поиска вы создаете com.jme3.scene.SceneGraphVisitorAdapter, котором реализуются ваши критерии поиска и то что вы хотите сделать с найденными Spatial-ами. Затем вы вызываете метод Spatial-а depthFirstTraversal(visitor) или breadthFirstTraversal(visitor) (например, rootNode или лучше подузел), чтобы начать поиск.

SceneGraphVisitor visitor = new SceneGraphVisitor() {

  @Override
  public void visit(Spatial spat) {
    // Критерием поиска может быть класс Control:
    MyControl control = spatial.getControl(MyControl.class);
    if (control != null) {
      // у вас есть доступ к любому методу, например. название(name).
      System.out.println("Instance of " + control.getClass().getName()
                       + " found for " + spatial.getName());
    }
  }

};

// Теперь сканируйте дерево сначала в глубину ...
rootNode.depthFirstTraversal(visitor);
// ... или сканируйте его в ширину.
rootNode.breadthFirstTraversal(visitor);

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

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

Класс SceneGraphVisitorAdapter можно использовать для сканирования по отдельности Геометрий и Узлов.

Смотрите также


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

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

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