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

Andry

Опубликованно: AndryAndry27.11.2017, 16:08
Последняя редакция, Andry: 29.11.2017 5:49
  1. Если вы еще не установили SDK jMonkeyEngine3 то сделайте это, запустите среду IDE, и создайте JME3 проект.
  2. Установите приложения MakeHuman и Blender, и инструменты MakeHuman Blender.
    • Загрузите последнюю стабильную версию приложения MakeHuman с www.makehuman.org
    • Загрузите последние стабильные инструменты MakeHuman Blender с www.makehuman.org
    • Загрузите соответствующую (не обязательно последнюю) версию приложения Blender с www.blender.org
    • Установите приложение MakeHuman как указанно в описании установки MakeHuman
    • Установите приложение Blender.
    • Разархивируйте плагин импорта инструментов MakeHuman в папку скриптов Blender. На машинах с Windows 7 это включает распаковку архива в
      C:\Program Files\Blender Foundation\Blender\<версия>\scripts\addons
    • Запустите приложение Blender, откройте редактор Параметры Blender(Blender User Preferences), активируйте вкладку Дополнения(Addons) и установите флажок для
        MakeHuman: Import-Runtime: MakeHuman Exchange 2 (.mhx2)
    • Нажмите кнопку [Сохранить настройки](Save User Preferences).
    • Разархивируйте плагин экспорта инструментов MakeHuman в папку плагинов MakeHuman.
  3. Создание файла .mhx2, содержащего фигуру человека.
    • Запустите приложение MakeHuman.
    • На вкладке Settings(Настройки) вы можете переключится на Русский язык.
    • Настройте фигуру человека, используя вкладки Моделирование, Геометрии и Материалы.
    • На вкладке Поза / Анимировать выберите нужный скелет для анимации, если это необходимо.
    • На вкладке Файлы выберите вкладку Сохранить. Обратите внимание, что есть две кнопки Сохранить: одна в окне Сохранить как(в виде []), с помощью которой просто задаётся название и путь, и другая в главном окне. Файл .mhm не записывается, пока вы не нажмете вторую кнопку [Сохранить].
    • Сохраните файл (если вам может понадобится внести в него изменения позже).
    • На вкладке Файлы выберите вкладку Экспорт.
    • Выберите пункт MakeHuman Exchange (mhx2) в качестве формата экспорта.
    • Экспортируйте файл. Тут так же как и с сохранением есть две кнопки […], которая просто задает путь, и есть кнопка [Экспорт]. Файл .mhx2 не записывается, пока вы не нажмете кнопку [Экспорт] в главном окне.
    • Теперь вы можете закрыть приложение MakeHuman.
  4. Преобразование файла .mhx2 в файл .blend:
    • Запустите приложение Blender и удалите исходный куб.
    • На панели инструментов редактора Информация выберите Файл ▸ Импорт ▸ MakeHuman (.mhx2)…
    • В открывшемся окне выберите ваш файл .mhx2 и нажмите кнопку [Import MHX2].
    • После завершения импорта вы можете просмотреть и отредактировать модель с помощью редактора 3D Вида.
    • Далее на панели инструментов редактора Информация выберите Файл ▸ Сохранить как…
    • В открывшемся окне выберите путь в папке assets/Models вашего JME3 проекта.
    • Кликните по кнопке [Сохранить как файл Blender] и файл будет сохранён.
    • Теперь вы можете закрыть приложение Blender.
  5. Преобразование файла .blend в файл .j3o:
    • Запустите IDE jMonkeyEngine3.(У меня в IDE jMonkeyEngine3 для версии 3.1 зависало при конвертировании но прекрасно конвертировалось в jMonkeyBuilder)
    • Откройте проект JME3.
    • В узле Project Assets вашего проекта откройте папку Models.
    • Щелкните [ПК мыши] файл .blend и выберите Convert to j3o binary.

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


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

Вы можете попробовать новый jME3 и внести исправления и функции! В этом документе показано, как загрузить, настроить, создать и запустить последнюю версию разработки из источников. Эти инструкции работают в среде IDE NetBeans 8.x или выше.

Предпосылки

  1. У вас есть аккаунт GitHub.
  2. Является участником проекта jMonkeyEngine.

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

Чтобы развернуть репозиторий jMonkeyEngine в своей учетной записи GitHub:

  1. Перейдите на страницу https://github.com/jMonkeyEngine/jmonkeyengine.
  2. В меню в верхней части страницы выберите кнопку «Вилка».
В дальнейшем всегда замените ~ на путь к вашему домашнему каталогу.

Загрузка исходников

Клонирование источников из хранилища.

  1. В NetBeans перейдите в Team ▸ Git ▸ Clone.
    1. URL-адрес репозитория:
    2. https://github.com/jMonkeyEngine/jmonkeyengine
      Используйте URL-адрес для своей вилки и клонируйте свою вилку, если вы не являетесь членом, и вы хотите внести свой вклад.
    3. Вы можете оставить user / pw пустым для анонимного доступа, если только вы не нажмете фиксацию.
    4. Укажите папку назначения.
    5. Локальная папка: ~ / NetBeansProjects] / jmonkeyengine
    6. Нажмите «Далее.
  2. Выбрать:

      мастер*

      Нажмите «Далее.
  3. Проверьте правильность информации автозаполнения в диалоговом окне «Целевая директория».
    1. Необязательный:
        Сканирование проектов NetBeans после клонирования
    2. Нажмите «Готово» и подождите.

Через некоторое время загрузка закончится.

Информация о том, как тянуть /

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

Участники и нечлены Pull / Push
Обновите локальную копию и нажмите фиксации с помощью команды NetBeans. Git ▸ Remote ▸ Pull From Upstream или Git ▸ Remote ▸ Push To Upstream.

Не члены
Чтобы обновить вилку на GitHub:

  1. Перейдите к своей версии репозитория на GitHub.
  2. Нажмите кнопку «Новый запрос на подачу» вверху.
  3. Обратите внимание, что репозиторий jMonkeyEngine будет слева, а ваш репозиторий будет справа.
  4. Нажмите кнопку «Базовая вилка», а в раскрывающемся меню выберите разветвленный репозиторий.
  5. Выберите ссылку «сравнить все вилки».
  6. Нажмите кнопку «Головная вилка» и в раскрывающемся списке выберите «jMonkeyEngine / jmonkeyengine».
  7. Нажмите зеленую кнопку «Создать запрос на растяжение».
  8. Дайте краткое и информативное название, в поле комментария дайте краткое описание изменений и нажмите зеленую кнопку «Создать запрос на растяжение» еще раз.
  9. Выберите кнопку фиксации и слияния.
  10. Нажмите кнопку Commit And Merge еще раз, чтобы подтвердить свой выбор.

Чтобы отправить изменения в репозиторий jMonkeyEngine после нажатия на свою вилку:

  1. Перейдите к своей версии репозитория на GitHub.
  2. Нажмите кнопку «Новый запрос на подачу» вверху.
  3. Обратите внимание, что репозиторий jMonkeyEngine будет слева, а ваш репозиторий будет справа.

  4. Нажмите зеленую кнопку «Создать запрос на растяжение». Дайте краткое и информативное название, в поле комментария дайте краткое описание изменений и нажмите зеленую кнопку «Создать запрос на растяжение» еще раз.
Все
См. Раздел Как внести вклад в jMonkeyEngine перед отправкой P / R.

Проверка клонированных подпроектов

Посмотрите на узел Subprojects и убедитесь, что клонированные подпроекты:

  • jme3-android
  • jme3-android-native
  • jme3-blender
  • jme3-bullet
  • jme3-bullet-native
  • jme3-bullet-native-android
  • jme3-core
  • jme3-desktop
  • jme3-effects
  • jme3-examples
  • jme3-ios
  • jme3-jbullet
  • jme3-jogg
  • jme3-jogl
  • jme3-lwjgl
  • jme3-lwjgl3
  • jme3-networking
  • jme3-niftygui
  • jme3-plugins
  • jme3-terrain
  • jme3-testdata
  • jme3-vr

Подробное описание отдельных файлов jar см. В этом списке.

Создайте проект и запустите пример приложения

Когда вы создаете движок из корневого узла, часть процесса сборки включает в себя создание файлов заголовков для подпроекта jme3-bullet. Это обновляет временную метку в файлах заголовков, даже если вы их не редактировали. Затем они будут отмечены как измененные, что добавит их к следующему фиксации.

Чтобы предотвратить их совершение, прежде чем делать что-либо еще:

  1. В окне «Проекты» откройте узел подпроекта jme3-bullet.
  2. Перейдите в папку «Исходные пакеты / <пакет по умолчанию».
  3. Выберите все файлы заголовка .h, чтобы выделить их.
  4. RMB выберите выделенные файлы, затем выберите Git ▸ Ignore ▸ Exclude From Commit
  1. RMB выберите корневой узел проекта jmonkeyengine и очистите и создайте проект.
  2. В окне «Проекты» выберите RMB и откройте узел jme-examples, который содержит примеры приложений. Вы делаете это для любого подпроекта, который вы хотите внести.
  3. Каждый файл в папке «Исходные пакеты» с основным классом (например, jme3test.model / TestHoverTank.java или jme3test.games/CubeField.java) является приложением.
  4. Щелкните правой кнопкой мыши пример приложения и выберите «Запустить файл» (Shift-F6).
  5. Как правило, в примерах приложений:
    1. перемещение мыши и клавиши WASD
    2. клавиша Esc выходит из приложения
Вы можете RMB выбрать узел jme-examples и выбрать Run, чтобы запустить приложение Test Chooser независимо от того, открываете ли вы узел проекта.

Дополнительно: всплывающие окна Javadoc и исходная навигационная система в NetBeans

Если вы работаете с источниками jmonkeyengine:

  1. Подтвердите в окне «Файлы», что javadoc был создан в ~ / NetBeansProjects / jmonkeyengine / dist / javadoc
  2. В редакторе поместите курсор в класс jme и нажмите ctrl-space, чтобы просмотреть javadoc.

Если вы работаете над проектом игры, который зависит от jmonkeyengine:

  1. В источнике jmonkeyengine:
    1. RMB, выбрав узел подпроекта и выбрав «Задачи ▸», установит встроенные банки для этого подпроекта в вашу локальную папку репозиториев org.jmonkeyengine, которые на linux равны ~ / .m2, а в Windows могут быть в AppData или в вашем домашнем каталоге ,
    2. RMB, выбирая корневой узел и выбрав «Задачи» ▸ dist, создает распределение примеров jME3 со всеми двоичными файлами jme3, javadoc и внешними библиотеками в ~ / NetBeansProjects / jmonkeyengine / dist.
    3. RMB, выбирая корневой узел и выбрав «Задачи» ▸ libDist строит и копирует двоичные файлы и источники движка в ~ / NetBeansProjects / jmonkeyengine / build / libDist.
    4. RMB, выбирая корневой узел и выбрав «Задачи» ▸ copyLib копирует зависимости ядра с ~ / NetBeansProjects / jmonkeyengine / build / libDist / lib-ext.
  2. В своем игровом проекте добавьте jme3 jar RMB, выбрав узел Libraries и выбрав Add Jar / Folder.
  3. Перейдите в выбранную папку и выберите интересующую вас библиотеку. Проверьте «как относительный путь» и нажмите «Открыть».
  4. RMB выберите недавно добавленную банку и выберите «Изменить».
  5. В диалоговом окне Edit Jar Reference, JavaDoc: выберите в папку javadoc /. Проверьте «как относительный путь» и нажмите «Открыть».
  6. В диалоговом окне «Редактировать привязку» выберите «Источники: выберите папку, которая содержит ваши источники». Проверьте «как относительный путь» и нажмите «Открыть».
  7. В редакторе поместите курсор в класс jme и нажмите ctrl-space, чтобы просмотреть javadoc. Ctrl-click любой метод jme3, чтобы перейти к его определению в источниках.

Этот совет работает для любой сторонней библиотеки JAR, которую вы используете. (Возможно, вам придется загружать javadoc / sources со своей домашней страницы отдельно).

Используемые источники: https://github.com/jMonkeyEngine/jmonkeyengine


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

Это Замечание «Примечание». Они предназначены, чтобы дать вам дополнительную информацию по теме того что вы в данный момент просматриваете.
Это Замечание «Совет». Они предназначены для того, чтобы дать вам небольшой, но полезный практический совет.
Это Замечание «Важное». Оно означает, что информация в нём имеет большую значимость или значение и не должна игнорироваться.
Это Замечание «Осторожно». Когда вы их видите, вы должны обратить особое внимание на информацию в них. Они означают что вам следует соблюдать осторожность, чтобы избежать ошибок.
Это Замечание «Предупреждение». Информация в них должна восприниматься очень серьезно потому что она указывает на возможные проблемы, или другие неприятные ситуации которые могут возникнуть, если их игнорировать.

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

Чтобы выполнить этот пример, вам нужно знать основы моделирования, такие как расширение граней/слияние вершин/(перемещение вершин/рёбер/граней)/и.т.д.

Пред просмотр

preview

Шаг 1 — Подготовка

  • Откройте Blender с новой сценой
  • Добавьте простой куб(если его нет). Чтобы сделать это, нажмите shift+a и выберите Куб
  • 2 (1)

  • Нажмите T чт бы открыть окно инструментов. Выберите вкладку Опции и установите
      X-зеркало(X mirror)
  • 4 (1)

  • Подразделите(Subdivide) этот куб, чтобы получить больше граней
    • Это можно сделать с помощью модификатора → подразделение поверхности (это будет позже)

    5 (1)

  • Клавишей N откройте вторую панель инструментов. Теперь давайте загрузим пример изображения, которое поможет нам построить Варга. Я нашел подходящее нам изображение Варга на devian art. Не забудьте для этого переключится в ортогональный режим NumPad5, настроить параметр Ось(Axis) и настроить нужный вид, например с помощью клавиши NumPad3.
  • example

  • Сделаем простую Фигуру Варга как на изображениях
  • 6 (1)
    7 9

Шаг 2 — Моделирование

  • В окне инструментов T — воспользуемся инструментом Сгладить вершины(Smooth Vertex), который может нам помочь в моделировании варга.
  • 10

  • Чтобы легко добавить рёбра, используйте инструмент Резать петлёй со сдвигом(loop cut and slide), который работает таким образом:
  • 12 13

  • Перейдите к модификаторам и добавьте Отражение(Mirror) поверхности
  • 14

  • Добавьте недостающие детали, такие как глаза/и.т.п.
    Нужно знать, как использовать экструдирование выделенных вершин (клавиша E) и объединение экструдированных выделенных вершин.
  • 15
    16

  • Для использования гладкого затенения просто установите его в окне инструментов в Затенение/UV ▸ Грани ▸ Гладко.
  • 17

  • Применить модификатор просто нажав кнопку [Применить] в модификаторе Отражение(Mirror).
  • Удалите удвоения (удаляет вершины, которые слишком близки друг другу).
  • 18

    Шаг 3 — Арматура

    • Shift-a и добавьте арматуру в режиме объекта.
      shift+a, чтобы добавить кость в режиме редактирования
    • 19

    • хвост должен быть выполнен другим способом. Начните строить скелет с начала хвоста (не заканчивается)
    • 21

    • Показывать имена и изменять вид арматуры (если хотите)
    • 22

    • установить имена для костей (через окно свойств или окно опций «n»)
    • 23

    • Выберите только боковые кости, нажмите shift-d, чтобы скопировать их, и сделайте зеркало. Не забудьте иметь курсор в 0,0,0 и иметь такие настройки, как на изображении (если нет, вам нужно просто переместить скопированные кости вручную)
    • 25

    • Нажмите «w» и выберите «flip names»
    • 26
      27

    • В режиме объекта:
      • Выбрать модель
      • С помощью арматуры SHIFT
      • Нажмите «p» и выберите «с автоматическими весами»

      28

    • Попробуйте переместить ногу в режиме «Поза»
      Режим «Поза» работает как режим редактирования, используйте «r», чтобы повернуть кость. используя «x /» y / «z после того, как« g / »r /« s также будет работать здесь, как и все остальное.
    • 29

    • Перейти к просмотру анимации
    • 30

    • Добавить новое действие
    • 31

    • Выберите все кости в режиме «Поза» и примените расположение / поворот / масштаб. Для этого нажмите «i» и выберите его как на изображении:
    • 32

      alt-r / alt-g / alt-s — четкое вращение / расположение / масштаб
    • есть возможность копировать позы
    • 33

    • а также скопировать их в зеркальную позу
    • 35

    • в редакторе действий вы можете легко удалить / переместить / масштабировать кадры
    • 34

    • Если анимация работает не линейно (и вам это не нравится), вы можете изменить ее в окне редактора кривых
    • 36

    • Thats all for Animations, для более простого ознакомления с вики / документацией JME.

    Шаг 4 — Текстурирование

    • Переместите арматуру на второй слой. нажмите «m», чтобы сделать это.
    • 37

    • В режиме редактирования необходимо отметить шов на краях, чтобы подготовить модель для текстурирования. нажмите ctrl-e, чтобы сделать это.
    • 38

    • сделайте это схоже с этим (или вы можете сделать это лучше):
    • 40
      41
      43

    • Нажмите «u» и выберите первый вариант «развернуть»,
    • В УФ-окне вы можете свести к минимуму растягивание (свести к минимуму изменение растяжения с помощью мыши).
    • 44

    • сделайте 2 геометрии для модели:
      • тело (содержит лица для тела)
      • глаза (содержит лица для глаз)
    • 45
      48

    • для глаз, которые вы можете использовать «Сферная проекция для разворота»,
    • 49

    • Выберите изображение текстуры
    • 50

    • в окне опций «n», например, на изображении, чтобы увидеть текстуру. (ViewPort необходимо установить как сплошное, ViewPort находится рядом с объектом / Редактировать)
    • 52

    • Просто создайте текстуру модели (используя режим текстуры — там, где находится объект / режим редактирования)
      под «t инструментами вы можете изменить цвет / размер / etc кисти
    • 55

    • Используя инструмент 2d, например Gimp / Photoshop, используйте фильтр / модификатор, чтобы получить красивую кожу
    • 56

    • Теперь нужно экспортировать только через Ogre Mesh или просто через Blend-файл (используя SDK).
    • Для глаз и тела используйте отдельные файлы j3m, а затем установите их в SceneComposer.
    также не забывайте о редакторе NLA и отправляйте конверты, чтобы анимация работала!

    вот документы:

    Создание ресурсов в Blender3D

    Готово!


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

    Asset Management

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

    Создание моделей в 3dsMax

    Для этого урока я использовал 3D Studio Max 2012 и бесплатную версию OgreMax 2.4.3

    Создать модель и кости

    • Создать новый файл
    • Выберите вкладку «Создать»> «Геометрия»> «Цилиндр»
    • 3dsmax-0

    • Нарисуйте цилиндр, скажем, с 8 сегментами высоты (должно быть достаточно для гладкой деформации)
    • Также проверьте «Создание картографических кодов».
    • 3dsmax-1

    • Нажмите вкладку «Создать»> «Системы»> «Кости»
    • 3dsmax-2

    • Добавить кости в центре цилиндра
    • 3dsmax-3

    • Выберите цилиндр, щелкните его правой кнопкой мыши и нажмите «Преобразовать в:»> «Преобразовать в редактируемую сетку», чтобы предотвратить проблемы с OgreMax
    • Перейдите на вкладку «Изменить»> «Список модификаторов» и добавьте модификатор «Кожа»
    • 3dsmax-4

    • Под «Bones:» нажмите «Добавить» и выберите все ваши кости
    • 3dsmax-5

    • Вы также можете редактировать конверты, но для небольшого теста настройки по умолчанию в порядке

    Создание анимации

    • Выберите цилиндр и нажмите вкладку «Отобразить»> «Зафиксировать выбранный», чтобы было легче выбрать кости во время анимации
    • Выберите две верхние кости и включите режим «Авто-ключ»
    • 3dsmax-6

    • Первый ключевой кадр будет создан автоматически. Переместите ползунок анимационной дорожки на кадр 5
    • Немного переместите выделенные кости. Сетка цилиндра будет деформирована. Поскольку вы находитесь в режиме «Авто-ключ», будет создан ключевой кадр
    • 3dsmax-7

    • Создайте несколько дополнительных ключевых кадров. Вы также можете выбрать больше костей и переместить или повернуть их. Я создал 25 кадров, и последний ключевой кадр равен первому, так что анимация является петлевой
    • После создания анимации отключите режим «Авто-ключ»

    Настройки OgreMax

    • Откройте меню «Настройки сцены OgreMax» в меню
    • На вкладке «Меши» включите «Экспорт файлов XML» и отключите «Экспорт двоичных файлов», а также «Экспорт вершинных цветов»,
    • 3dsmax-8

    • Перейдите на вкладку «Окружающая среда» и снимите флажок «Экспортировать параметры среды». В противном случае импортер JME выдаст исключение NullPointerException
    • 3dsmax-9

    • Если вы текстурировали свою модель, вы также можете проверить «Скопировать растровые изображения в каталог экспорта» на вкладке «Растровые изображения»
    • Разблокируйте цилиндр, щелкнув вкладку «Дисплей»> «Освободить все» и выберите его
    • Выбрав выбранный цилиндр, откройте диалоговое окно «Настройки объекта OgreMax» в меню
    • Откройте вкладку «Mesh Animations» и выберите «Скелет», «Экспортный скелет»: «Да»,
    • Ниже «Mesh Animations» нажмите кнопку «Добавить …»
    • Назначьте имя треку, возможно, «качайте». Тип трека должен быть «Кожа. Установите правильную «Начальную / конечную рамки» для вашей анимации
    • 3dsmax-10

    • Нажмите ОК, и вы увидите анимацию в таблице. Вы можете добавить дополнительные анимации, выбрав другие диапазоны кадров, если хотите
    • 3dsmax-11

    Экспорт и импорт

    • Когда все анимации находятся в списке, выберите «OgreMax»> «Экспорт»> «Экспортировать сцену» и назовите файл «worm.scene»,
    • Создайте тестовый класс JME, который импортирует файл, получает контроллер анимации и запускает анимацию «вобуляции»
    import com.jme3.animation.AnimChannel;
    import com.jme3.animation.AnimControl;
    import com.jme3.animation.Skeleton;
    import com.jme3.app.SimpleApplication;
    import com.jme3.asset.plugins.FileLocator;
    import com.jme3.light.AmbientLight;
    import com.jme3.light.PointLight;
    import com.jme3.material.Material;
    import com.jme3.math.ColorRGBA;
    import com.jme3.scene.Geometry;
    import com.jme3.scene.Node;
    import com.jme3.scene.Spatial;
    import com.jme3.scene.control.LodControl;
    import com.jme3.scene.debug.SkeletonDebugger;
    
    /**
     * This is a test class for loading a Ogre XML scene exported by OgreMax.
     *
     * @author Stephan Dreyer
     *
     */
    public class TestOgreMaxImport extends SimpleApplication {
    
      @Override
      public void simpleInitApp() {
        assetManager.registerLocator("Assets/model/ogre/test/", FileLocator.class);
    
        // create the geometry and attach it
        final Node model = (Node) assetManager.loadModel("worm.scene");
        // resize it, because of the large 3dsmax scales
        model.setLocalScale(.001f);
    
        // attach to root node
        rootNode.attachChild(model);
        addLodControl(model);
    
        final AnimControl ac = findAnimControl(model);
    
        try {
          // add a skeleton debugger to make bones visible
          final Skeleton skel = ac.getSkeleton();
          final SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton",
              skel);
          final Material mat = new Material(assetManager,
              "Common/MatDefs/Misc/Unshaded.j3md");
          mat.setColor("Color", ColorRGBA.Green);
          mat.getAdditionalRenderState().setDepthTest(false);
          skeletonDebug.setMaterial(mat);
          ((Node) ac.getSpatial()).attachChild(skeletonDebug);
    
          // create a channel and start the wobble animation
          final AnimChannel channel = ac.createChannel();
          channel.setAnim("wobble");
        } catch (final Exception e) {
          e.printStackTrace();
        }
    
        // add some lights
        rootNode.addLight(new AmbientLight());
        rootNode.addLight(new PointLight());
      }
    
      public void addLodControl(final Spatial parent) {
        if (parent instanceof Node) {
          for (final Spatial s : ((Node) parent).getChildren()) {
            addLodControl(s);
          }
        } else if (parent instanceof Geometry) {
          final LodControl lc = new LodControl();
          lc.setDistTolerance(1f);
          parent.addControl(lc);
        }
      }
    
      /**
       * Method to find the animation control, because it is not on the models root
       * node.
       *
       * @param parent
       *          The spatial to search.
       * @return The {@link AnimControl} or null if it does not exist.
       */
      public AnimControl findAnimControl(final Spatial parent) {
        final AnimControl animControl = parent.getControl(AnimControl.class);
        if (animControl != null) {
          return animControl;
        }
    
        if (parent instanceof Node) {
          for (final Spatial s : ((Node) parent).getChildren()) {
            final AnimControl animControl2 = findAnimControl(s);
            if (animControl2 != null) {
              return animControl2;
            }
          }
        }
    
        return null;
      }
    
      public static void main(final String[] args) {
        new TestOgreMaxImport().start();
      }
    }

    Вы увидите странные движения червей. Повеселись!

    3dsmax-12

    3ds Max Двножная Анимация для JME3

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

    Создание персонажа в 3dsMax

    Я не буду подробно рассказывать вам, как моделировать персонажа. Там я много хороших учебных пособий в Интернете, я использовал этот.

    • Вы можете создать двуногий, прежде чем приступать к моделированию, поэтому довольно легко подогнать пропорции двуногих.
    • После создания модели и двуногого я получил что-то вроде этого:
    • 1

    • Я добавил модификатор Meshmooth с 2 итерациями и получил этот результат:
    • 3dsmax_biped_2

    • После сглаживания вашей сетки вы можете исправить вершины с помощью модификатора Edit Mesh. Наконец, вы добавляете модификатор Physique.
    • Теперь вы можете редактировать свои конверты в соответствии с вашей моделью.

    Создание простой анимации ходьбы

    • Выберите сундук вашего бипеда, выберите вкладку «Движение (1)>« Шаг стопы »(2)>« Создать несколько шагов (3)
    • Вам нужно выбрать «В режиме места» (4), чтобы персонаж двигался на месте, не меняя своего местоположения.
    • 3dsmax_biped_3_1

    • Теперь вы можете немного поиграть с настройками, я скорректировал «Фактическая длина шага» и «Фактическая высота шага».
    • Для «Количество шагов 6 будет достаточно, потому что анимация будет циклически позже.
    • Примечание. Вы также можете создавать или редактировать шаги вручную и перемещать или поворачивать их.
    • После того, как все шаги будут созданы, нажмите кнопку «Создать клавиши для неактивных шагов» на панели «Панель шагов»
    • Теперь вы можете проверить свою анимацию, нажав кнопку «Play» на временной шкале.

    Подготовка экспорта и настройка OgreMax

    • «Настройки сцены OgreMax должны быть такими же, как показано выше.
    • Поскольку вы хотите, чтобы ваша анимация была зациклена, вам нужно найти два ключевых кадра, где ноги находятся почти в одном положении. Для моих настроек я выбрал кадры 48-78 для анимации прогулок.
    • Выберите сетку символов и откройте диалоговое окно «Настройки сцены OgreMax».
    • Откройте вкладку «Mesh Animations» и выберите «Скелет», «Экспортный скелет»: «Да»,
    • Ниже «Mesh Animations» нажмите кнопку «Добавить …»
    • 3dsmax_biped_4

    • Введите имя трека, например. «ходить.
    • Убедитесь, что для типа дорожки задано значение «Physique.
    • Установите начальный и конечный фреймы, для меня это 48-78.
    • Закройте диалоговое окно, нажав «Ok.
    • Примечание. Было бы полезно создать также трек «start_run», который сочетается между анимацией стенда и ходьбы. Я бы использовал для этого фрейм 0-47.
    • Поскольку у вас есть гладкая модель с большим количеством полигонов, может быть полезно создать уровни детализации (LOD). Когда камера будет дальше, будет отображаться низкополитическая сетка вашего персонажа.
    • 3dsmax_biped_5

    • Откройте вкладку «Mesh LOD» в настройках объекта.
    • Достаточно выбрать «Автоматическая настройка», но если ваша анимация начнет выглядеть странно, вы можете создать ее вручную.
    • Я использовал 4 уровня LOD с расстоянием 1. Не беспокойтесь о настройке расстояния, вы можете изменить его позже в JME.
    • Для снижения уровня я использовал 20 процентов, которые дают хорошие результаты. Вы можете настроить все настройки в зависимости от ваших потребностей.
    • Закройте диалоговое окно, нажав «Ok.

    Фиксирование местоположения

    • Перед экспортом вам нужно сделать небольшое исправление, потому что ваша модель на самом деле не находится там, где вы ее видите. JME попадет в массу неприятностей, если вы не измените это.
    • Обеспечьте сохранение максимального файла. Иногда OgreMax выдает всю заявку во время экспорта. Если вы хотите изменить анимацию после экспорта, вы должны перезагрузить этот файл, потому что исправление местоположения меняет то, что я действительно не могу понять.
    • 3dsmax_biped_6

    • Щелкните правой кнопкой мыши инструмент «Выбрать и переместить» на верхней панели инструментов. Появится диалоговое окно.
    • Установите X и Y в положение 0 и закройте диалог.
    • Есть еще один способ добиться этого. Если вы масштабировали, перемещали или поворачивали свою модель, просто откройте вкладку «Иерархия» и нажмите «Трансформировать» и «Масштаб» на панели «Сброс».

    Экспорт и импорт

    • Теперь вы можете экспортировать свою сцену. Выберите только сетку и используйте «Экспортировать выбранные объекты». Вам не нужна вся сцена, включая двуногий объект, но кости создаются автоматически во время экспорта.
    • Создайте тестовый класс JME для импорта сцены.

    Для этого я расширил первый класс:

    import com.jme3.animation.AnimChannel;
    import com.jme3.animation.AnimControl;
    import com.jme3.animation.Skeleton;
    import com.jme3.app.SimpleApplication;
    import com.jme3.asset.plugins.FileLocator;
    import com.jme3.light.AmbientLight;
    import com.jme3.light.PointLight;
    import com.jme3.material.Material;
    import com.jme3.math.ColorRGBA;
    import com.jme3.math.Vector3f;
    import com.jme3.scene.Geometry;
    import com.jme3.scene.Node;
    import com.jme3.scene.Spatial;
    import com.jme3.scene.control.LodControl;
    import com.jme3.scene.debug.SkeletonDebugger;
    import com.jme3.scene.shape.Box;
    
    /**
     * This is a test class for loading a Ogre XML scene exported by OgreMax.
     *
     * @author Stephan Dreyer
     *
     */
    public class TestOgreMaxImport extends SimpleApplication {
    
      @Override
      public void simpleInitApp() {
        assetManager.registerLocator("Assets/model/ogre/test/", FileLocator.class);
    
        // create the geometry and attach it
        final Node model = (Node) assetManager.loadModel("guy.scene");
        // resize it, because of the large 3dsmax scales
        model.setLocalScale(.02f);
    
        // attach to root node
        rootNode.attachChild(model);
        addLodControl(model);
    
        final AnimControl ac = findAnimControl(model);
    
        try {
          // add a skeleton debugger to make bones visible
          final Skeleton skel = ac.getSkeleton();
          final SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton",
              skel);
          final Material mat = new Material(assetManager,
              "Common/MatDefs/Misc/Unshaded.j3md");
          mat.setColor("Color", ColorRGBA.Green);
          mat.getAdditionalRenderState().setDepthTest(false);
          skeletonDebug.setMaterial(mat);
          ((Node) ac.getSpatial()).attachChild(skeletonDebug);
    
          // create a channel and start the walk animation
          final AnimChannel channel = ac.createChannel();
          channel.setAnim("walk");
        } catch (final Exception e) {
          e.printStackTrace();
        }
    
        flyCam.setMoveSpeed(40f);
        cam.setLocation(new Vector3f(15, 10, 15));
        cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
        cam.setFrustumNear(1f);
    
        // add some lights
        rootNode.addLight(new AmbientLight());
    
        final PointLight pl = new PointLight();
        pl.setPosition(new Vector3f(-3f, 3f, 1f));
        rootNode.addLight(pl);
    
        // add a box as floor
        final Box b = new Box(100f, 0.1f, 100f);
        final Geometry geo = new Geometry("floor", b);
    
        final Material mat = new Material(assetManager,
            "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.LightGray);
        geo.setMaterial(mat);
    
        rootNode.attachChild(geo);
      }
    
      /**
       * Method to traverse through the scene graph and add a {@link LodControl} to
       * the mesh.
       *
       * @param parent
       *          The Node to add the control to.
       */
      public void addLodControl(final Spatial parent) {
        if (parent instanceof Node) {
          for (final Spatial s : ((Node) parent).getChildren()) {
            addLodControl(s);
          }
        } else if (parent instanceof Geometry) {
          final LodControl lc = new LodControl();
    
          // the distance for LOD changes is set here, you may adjust this
          lc.setDistTolerance(1f);
          parent.addControl(lc);
        }
      }
    
      /**
       * Method to find the animation control, because it is not on the models root
       * node.
       *
       * @param parent
       *          The spatial to search.
       * @return The {@link AnimControl} or null if it does not exist.
       */
      public AnimControl findAnimControl(final Spatial parent) {
        final AnimControl animControl = parent.getControl(AnimControl.class);
        if (animControl != null) {
          return animControl;
        }
    
        if (parent instanceof Node) {
          for (final Spatial s : ((Node) parent).getChildren()) {
            final AnimControl animControl2 = findAnimControl(s);
            if (animControl2 != null) {
              return animControl2;
            }
          }
        }
    
        return null;
      }
    
      public static void main(final String[] args) {
        new TestOgreMaxImport().start();
      }
    }

    После запуска класса вы можете увидеть приятную плавную анимацию (если она негладкая, вам нужно настроить кадры дорожки):

    3dsmax_biped_7

    Как вы можете видеть, LOD работает:

    3dsmax_biped_8


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

    Я хочу создать и настроить jME3 приложение


    Как начать писать предварительно сконфигурированную jME игру?

    Напишите Java класс, который расширяет com.jme3.app.SimpleApplication.

    Подробнее: Hello SimpleApplication, TestAppStateLifeCycle.

    Как изменить цвет фона?

    viewPort.setBackgroundColor(ColorRGBA.Blue);

    Могу ли я настроить класс SimpleApplication?

    Да! На самом деле, вы ДОЛЖНЫ настраивать его! Для ваших собственных игр вы всегда создаете пользовательский базовый класс, который расширяет класс com.jme3.app.SimpleApplication. Отныне это уже не простое приложение — теперь это ваша игра. Настройте параметры приложения, реализуйте методы и настройте их!

    Подробнее: SimpleApplication, AppSettings.

    Как я могу переключаться между экранами или состояниями?

    Вы должны разбить логику приложения на компоненты, распространив это на отдельные AppStates. AppStates можно подключить и отключить от игры. AppStates имеют доступ ко всем объектам (rootNode, PhysicsSpace, inputManager и.т.п.) и методам в вашем основном приложении. Таким образом, каждый AppState может принести свой собственный набор обработчиков ввода, узлов GUI, spatial узлов и даже своего собственные подмножества игровой механики в цикле update().

    Подробнее: Application States.

    Как приостановить/возобновить игру?

    Вы разбиваете свое приложение на несколько AppStates и реализуете методы setEnabled() для каждого состояния. Затем вы создаете, например, GameRunningAppState и GamePausedAppState. Задача GamePausedAppState состоит в том, чтобы прикрепить все ваши AppStates, которые содержат логику и GUI экрана паузы, и отделить все AppStates, которые содержат логику и GUI воспроизводящейся игры. GameRunningAppState делает обратное. Присоединяя один или другой к игре, вы переключаетесь между приостановленными и возобновлёнными состояниями.

    Подробнее: Application States.

    Как отключить вывод журнала на консоль?

    Во время разработки вы можете переключить уровень серьезности журнала с по умолчанию, на то чтобы больше не печатать предупреждения FINE, а только WARNING-ги(предупреждения).

    java.util.logging.Logger.getLogger("").setLevel(Level.WARNING);

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

    java.util.logging.Logger.getLogger("").setLevel(Level.SEVERE);

    Подробнее: Ведение журнала.

    Почему происходит сбой выполнения с «Cannot locate resource»(Не удается найти ресурс)?

    Обязательно загружайте модели, преобразованные в двоичный формат .j3o, а не в исходных форматах Ogre или Wavefront. Если вы загружаете игровые ресурсы из zip-файлов, обязательно скорректируйте сценарий сборки, затем скопируйте их в папку сборки.

    Подробнее: Менеджер ресурсов(Asset Manager)

    Что такое java.lang.LinkageError: Version mismatch(Несоответствие версии)?

    Это редкое исключение показывает сообщение, подобное следующему: Exception in thread “LWJGL Renderer Thread java.lang.LinkageError: Version mismatch: jar version is (number), native library version is (another number)(Исключение в потоке «Поток Рендеринга LWJGL» java.lang.LinkageError: Несоответствие версии: версии jar (номер), и версия исходной библиотеки (другой номер)). jME3 нуждается в родных библиотеках(Java native library) (файлах DLL, .jnilib, lib*.so) для запуска LWJGL и jBullet. Правильные версии этих библиотек включены в установку SDK или загрузку бинарников. Однако существуют обстоятельства, при которых jME3 не может определить, какую копию родных библиотеки он должен использовать:

    Возможные причины

    • Если вы устанавливаете другое приложение, которое нуждается в другой версии родных библиотек, и это приложение глобально устанавливает свою версию поверх jME3.
    • Если старая копия родной библиотеки находится в каталоге проекта, в вашем домашнем каталоге или в пути к библиотекам Java или в classpath.
    • Если вы связали со старой копией в настройках среды IDE.

    После чего Java предполагает, что вы предпочитаете эти родные библиотеки поверх связанных, и ваше приложение jME3 завершается из-за запуска с неправильной версией.

    Чтобы исправить это, выполните поиск файлов .dll (Windows), .jnilib (Mac) и .so (Linux) для jBullet и LWJGL на вашем жестком диске, а также в ваших путях и настройках IDE, убедитесь, что это все не мешает. (Если у вас есть другие версии jME, установленные и связанные каким-то образом, с устаревшие родные библиотеки также могут быть в файлах lwjgl.jar или jbullet.jar!)


    Я хочу загрузить свою сцену


    Как заставить объекты появляться/исчезать в 3D-сцене?

    Чтобы сделать так что бы spatial появился в сцене, вы присоединяете его к корневому узлу(rootNode) (или к узлу, прикрепленному к корневому узлу). Чтобы удалить spatial объект, вы отсоединяете его от своего родительского узла.

    rootNode.attachChild(spatial); // появляться в сцене
    rootNode.detachChild(spatial); // удалите из сцены

    Подробнее: The Scene Graph, Hello Node, Hello Asset, Spatial, com.jme3.scene.Node и com.jme3.scene.Geometry.

    Почему я получаю AssetNotFoundException когда загружаю X?

    Сначала проверьте правильность пути к папке asset. По умолчанию это относится к папке asset вашего проекта:

    // Загрузит .../jMonkeyProjects/MyGame/assets/Models/Ninja/Ninja.j3o
    Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.j3o");

    Если вы не используете по умолчанию папке asset, убедитесь, что вы зарегистрировали локатор в AssetManager. Доступны различные типы Локаторов.

    this.assetManager.registerLocator("assets/", FileLocator.class); // по умолчанию
    this.assetManager.registerLocator("c:/jme3User/JMEisSoCool/myAwesomeFolder/", FileLocator.class);
    this.assetManager.registerLocator("town.zip", ZipLocator.class);

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

    Подробнее: Менеджер ресурсов(Asset Manager)

    Как создавать 3D-модели, текстуры, звуки?

    Следуйте нашим рекомендациям для программного конвейера мультимедийных игровых ресурсов.
    Вы создаете 3D-модели в 3D редакторе сетки, например Blender, и экспортируете их с помщью Ogre Mesh XML (анимированные объекты, сцены) или в формате Wavefront OBJ (статические объекты, сцены). Вы создаете текстуры в графическом редакторе, например Gimp, и экспортируете их формате PNG или JPG. Вы создаете звуки в аудиоредакторе, например Audacity, и экспортируете их как WAVE или OGG.

    Подробнее: 3D Модели, Программный конвейер мультимедийных игровых ресурсов, JME3-импортер blend-в-j3o;
    Скачать Blender, Интро-учебник Blender, Плагин Blender-в-Ogre, Сравнение функций 3D-графического программного обеспечения (Wikipedia).

    Как загрузить 3D-модель в сцену?

    Используйте jMonkeyEngine SDK для преобразования моделей из форматов Ogre XML или Wavefront OBJ в двоичный формат .j3o. Загрузите файл .j3o с помощью AssetManager.

    // Загрузит .../jMonkeyProjects/MyGame/assets/Models/Ninja/Ninja.j3o
    Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.j3o");

    Подробнее: Hello Asset, Asset Manager, com.jme3.assets.AssetManager, com.jme3.scene.Geometry, jMonkeyEngine SDK конвертирование в j3o,
    Примеры кода: TestOgreLoading.java, TestOgreConvert.java.

    Как инициализировать сцену?

    Используйте метод simpleInitApp() в SimpleApplication (или initApp() в Application).

    Подробнее: Hello SimpleApplication, SimpleApplication.java.


    Я хочу преобразовать объекты в сцене


    Как перемещать или поворачивать или изменять размер spatial?

    Чтобы перемещать, поворачивать или изменять размер spatial, вы используете преобразования. Вы можете объединить преобразования (например, выполнять повороты вокруг нескольких осей за один шаг, используя Кватернион со slerp() или com.jme3.math.Transform со interpolateTransforms().

    spatial.setLocalTranslation(1,-3,2.5f); spatial.rotate(0,3.14f,0); spatial.scale(2,2,2);

    Подробнее: Hello Node, Spatial, Матчасть для чайников.

    Как я могу сделать spatial двигающимся сами по себе?

    Измените переметите (положение) геометрии в цикле обновления с помощью setLocalTranslation() для не с физикой и applyForce() или setWalkDirection() для тех что с физикой объектов. Вы также можете определять и дистанционно управлять движением spatial, используя Кинематики, например для записи роликов или реализовывать движущиеся платформы, лифтов, дирижаблей и.т.п.

    Подробнее: Hello Loop, Цикл Обновления, Пользовательские Control-ы, Кинематики
    Примеры кода: TestBumpModel.java, TestOgreLoading.java

    Как получить доступ к именованной под-сете в Модели?

    Geometry submesh = (Geometry) model.getChild("door 12");

    Подробнее: Spatial

    Как создать процедурные или пользовательские фигуры?

    Вы можете программно создавать com.jme3.scene.Mesh.

    Подробнее: Пользовательские сетки


    Я хочу изменять поверхность объектов в сцене


    Почему моя UV развертка / текстурирование выглядят неправильно?

    Наиболее вероятная причина — текстуры перевернуты. Возможно, вы используете следующий метод по умолчанию:

    material.setTexture("ColorMap", assetManager.loadTexture("myTexture.jpg"));

    Вы можете установить логическое значение в конструкторе TextureKey, чтобы перевернуть или не перевернуть. Переключите логическое значение, чтобы узнать, исправляет ли он проблему с UV разверткой / текстурированием:

    material.setTexture("ColorMap", this.assetManager.loadTexture(new TextureKey("myTexture.jpg", false)));

    Как масштабировать, зеркалировать или обертывать текстуру?

    Вы не можете масштабировать текстуру, но вы масштабируете координаты текстуры в сетке, к которой применяется текстура:

    mesh.scaleTextureCoordinates(new Vector2f(2,2));

    Вы можете выбрать среди различных com.jme3.texture.Texture.WrapModes для отдельных текстурных карт материала: BorderClamp, EdgeClamp, Clamp; MirrorBorderClamp, MirrorEdgeClamp, MirrorClamp; Повторите, MirroredRepeat.

    material.getTextureParam("DiffuseMap").getTextureValue().setWrap(WrapMode.Repeat);

    Как изменить цвет или блеск материала?

    Используйте AssetManager для загрузки Материалов и изменения настроек материала.

    Подробнее: Hello Material, Как использовать Материалы, Обзор Материалов, Asset Manager.
    Примеры кода: TestNormalMapping.java, TestSphere.java.

    Как сделать поверхность дерева, камня, металла и.т.п.?

    Создавайте Текстуры как файлы изображений. Используйте AssetManager для загрузки Материала и использования наложение текстур для улучшения внешнего вида.

    Подробнее: Hello Material, Как использовать Материалы, Обзор Материалов, Asset Manager, com.jme3.assets.AssetManager, Blender: Создание Bump Maps и Normal Maps
    Примеры кода: TestSimpleBumps.java

    Почему материалы слишком яркие, слишком темные или мерцающие?

    Если вы используете освещеамый материал (на основе Lighting.j3md), вы должны прикрепить источник света к корневому узлу(rootNode), иначе вы ничего не увидите. Если вы используете цветной освещаемый материал, убедитесь, что вы указали цвет Ambient (может совпадать с цветом Diffuse), если вы используете AmbientLight. Если вы видите объекты, но они серые или слишком темные, установите цвет освещения на белый или сделайте его ярче (вы можете умножить значение цвета на скаляр) или добавьте глобальный белый источник света (AmbientLight). Подобным же образом, настройте свет если все слишком белое. Если материалы мерцают под направленным светом, измените вектор направления света. Измените цвет фона (который не зависит от источников света), чтобы получить лучший контраст при отладке проблем освещения.

    Как сделать геометрию бросающую тень?

    Используйте com.jme3.shadow.BasicShadowRenderer вместе с com.jme3.light.DirectionalLight, и setShadowMode().

    Подробнее: Свет и тень
    Примеры кода: TestEverything.java, TestShadow.java

    Как сделать прозрачный материал?

    Назначьте текстуру с альфа-каналом в Материал и установите режим смешивания Материала в альфа. Используйте это для создания прозрачных или полупрозрачных материалов, таких как стекло, оконные стекла, вода, листья деревьев и.т.п.

    material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);

    Подробнее: Hello Material, Как использовать Материалы

    Как заставить отключится отсечение?

    При отладке пользовательских сеток вы можете отключить com.jme3.material.RenderState.FaceCullMode, чтобы видеть сетки как изнутри так и снаружи.

    someMaterial.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);

    Вы также можете отключить отсечение com.jme3.scene.Spatial.CullHint для целого spatial, чтобы заставить jme рассчитать его, даже если он находится за камерой и вне видимости.

    someNode.setCullHint(CullHint.Never);

    Подробнее: Spatial

    Могу ли я нарисовать только контур сцены?

    Добавьте состояние рендеринга в материал и активируйте Wireframe.

    material.getAdditionalRenderState().setWireframe(true);

    Подробнее: Отладка.

    Я хочу управлять камерой

    Камера по умолчанию cam является экземпляром класса Camera.

    Подробнее: com.jme3.renderer.Camera

    Как заставить камеру двигаться?

    SimpleApplication активирует flyCam (экземпляр FlyByCamera) по умолчанию. flyCam заставляет камеру перемещаться с помощью мыши и клавиш WASD. Вы можете отключить flyCam следующим образом:

    flyCam.setEnabled(false);

    Как переключаться между видом от третьего лица и первого лица?

    Вы можете активировать FlyBy Cam как камеру от первого лица.

    flyCam.setEnabled(true);

    Подробнее: Hello Collision.
    Примеры кода: com.jme3.input.FlyByCamera

    Вы также можете создать камеру преследования третьего лица.

    flyCam.setEnabled(false);
    chaseCam = new ChaseCamera(cam, spatial, inputManager);

    Подробнее: com.jme3.input.ChaseCamera
    Примеры кода: jme3test/input/TestChaseCamera.java.

    Как увеличить скорость камеры?

    flyCam.setMoveSpeed(50f);

    Действия, взаимодействия, физика


    Как я могу реализовать игровую логику/игровую механику?

    Используйте Control-ы для то что бы задвать поведения типов Spatial-ов. Используйте Application States для реализации глобального поведения, для группы подмножеств обработчиков вводимых данных или GUI экранов и.т.п. Используйте циклы simpleUpdate() и update() для тестов и взаимодействий. Используйте Cinematics для объектов дистанционного управления в сценах.

    Подробнее: Hello Loop, Цикл Обновления, Пользовательский Control, состояния приложений, Кинематика

    Как я могу позволить игрокам взаимодействовать с помощью клавиатуры?

    Используйте com.jme3.input.KeyInput и Input Listener(Слушатель Ввода).

    Подробнее: Hello Input, Обработка Ввода

    Как я могу позволить игрокам взаимодействовать, кликом?

    Игроки обычно кликом мыши, подбирают предметы, открывают двери, стреляют оружием и.т.п. Используйте Input Listener(Слушатель Ввода), чтобы реагировать на клик мыши, а затем осуществлять бросание луча от игрока; если он пересекается с ограничивающим объемом spatial, то этот spatial будет выбранной целью. Ниже приведенные ссылки содержат образцы кода с «выбором зафиксированного перекрестия» и «выбором свободного курсора мыши».

    Подробнее: Hello Picking, Выбор мышью, Столкновение и пересечение, Обработка Ввода, com.jme3.bounding., com.jme3.math.Ray.java, com.jme3.collision.CollisionResults.java.
    Примеры кода: TestRayCollision.java

    Как мне анимировать персонажи?

    Создайте анимированную модель OgreMesh с костями в 3D редакторе сетки (например, Blender).

    Подробнее: com.jme3.animation., Hello Animation, Анимация, Уроки анимации в Blender
    Примеры кода: Анимации

    Как удержать игроков от падения сквозь полы и хождения через стены?

    Используйте обнаружение столкновений. Наиболее распространенное решение — использовать интеграцию физики jme, jBullet.

    Подробнее: Hello Collision, Физика, com.jme3.bullet., CapsuleCollisionShape и CompoundCollisionShape, CharacterControl и RigidBodyControl.

    Как сделать шары/колеса/итп отскакивающими и катящимися?

    Добавьте control-ы физики в Spatials и дайте им сферические или цилиндрические ограничивающие объемы.

    Подробнее: Hello Physics, Физика, com.jme3.bounding., com.jme3.bullet.collisions, com.jme3.bullet.control.RigidBodyControl.java
    Примеры кода: TestSimplePhysics.java, Больше образцов физики

    Как производить отладку странного поведение физики?

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

    bulletAppState.getPhysicsSpace().enableDebug(assetManager);

    Как сделать ходячего персонажа?

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

    Подробнее: CharacterControl
    Примеры кода: TestQ3.java (от первого лица), TestPhysicsCharacter.java (от третьего лица)

    Как мне сделать управляемое транспортное средство?

    Используйте VehicleControl, который поддерживает поведение подвески.

    Подробнее: Транспортные средства, com.jme3.bullet., VehicleControl
    Примеры кода: TestFancyCar.java, (Нажимайте клавиши HUJK для управления, пробел, чтобы прыгать.)

    Могут ли объекты качаться, как маятники, цепи, канатные дороги?

    Используйте шарниры и суставы PhysControl.

    Подробнее: Шарниры и суставы, [com.jme3.bullet.joints.], TestPhysicsHingeJoint.java (нажмите клавиши HK, чтобы повернуть, пробел для качания.)


    Отображаемый по умолчанию GUI


    Что это за статистистика FPS/Objects/Vertices/Triangles(FPS/Объекты/Вершины/Треугольники)?

    В левом нижнем углу каждой стандартной BasicGame вы видите «Статистику» и FPS (кадры в секунду). Эти сведенья предоставляют вам дополнительную информацию на этапе разработки. Например, если вы заметили, что количество объектов увеличивается, а FPS уменьшается, то вы знаете, что ваш код присоединяет слишком много объектов и не отсоединяет их в достаточном количестве итд (может быть, вы используете бесконечный цикл?).

    Подробнее: StatsView(Статистика)

    Как мне убрать статистику FPS/Objects?

    В методе simpleInitApp() приложения вызовите:

    setDisplayFps(false); // скрыть FPS
    setDisplayStatView(false); // скрыть статистику

    Как отображать количество очков, здоровье, мини-карту, иконки состояния?

    Прикрепите текст и изображения к ортогональному guiNode, чтобы создать heads-up display (HUD).

    Подробнее: HUD, com.jme3.font., com.jme3.ui.Picture.java, guiNode.attachChild()
    Примеры кода: TestOrtho.java, TestBitmapFont.java

    Как отображать кнопки и элементы управления UI?

    Вы можете отображать кнопки, позволяющие игроку переключаться между игрой, экраном настроек и экранами счёта. Для кнопок и других более продвинутых элементов UI, jME поддерживает библиотеку Nifty GUI.

    Подробнее: Nifty GUI
    Примеры кода: TestNiftyGui.java

    Как отобразить экран загрузки?

    Вместо того, чтобы иметь застывший экран во время загрузки игр, вы можете иметь экран загрузки во время загрузки.

    Подробнее: Экран Загрузки


    Nifty GUI


    При добавлении элементов управления (кнопок и.т.п.) Я получаю NoSuchElementException!

    Убедитесь, что вы добавили ссылку в свой XML, на файл описывающий элементы управления: Это значение по умолчанию:

    <useControls filename="nifty-default-controls.xml"/>

    Где я могу найти пример кода Java классов и XML Nifty GUI?

    https://github.com/nifty-gui/nifty-gui/tree/1.4/nifty-examples/src/main

    Есть ли Java Doc для Nifty GUI?

    Nifty GUI Javadoc


    Я хочу создать мир со звуками, эффектами и ландшафтом


    Как проигрывать звуки и шумы?

    Используйте AudioRenderer, Listener и AudioNode из com.jme3.audio..

    Подробнее: Hello Audio, Audio
    Примеры кода: Аудио

    Как сделать огонь, дым, взрывы, рои насекомых, магические заклинания?

    Для эффекта роя насекомых, вы используете излучатели частиц.

    Подробнее: Hello Effects, Излучатели частиц, Свечение и Отблеск, Обзор эффектов, com.jme3.effect.EmitterSphereShape.java, com.jme3.effect.ParticleEmitter.java
    Примеры кода: TestExplosionEffect.java, TestMovingParticle.java, TestSoftParticle.java

    Как сделать воду, волны, отражения?

    Используйте специальную постобработку визуализации(рендеринга) из com.jme3.water..

    Подробнее: Вода, Постобработка воды
    Примеры кода: TestSimpleWater.java, TestSceneWater.java, TestPostWaterLake.java, TestPostWater.java

    Как сделать туман, свечение, размытие, рассеяние света?

    Используйте специальную постобработку визуализации(рендеринга) из com.jme3.post..

    Подробнее: Обзор эффектов

    Как сгенерировать ландшафт?

    Используйте com.jme3.terrain.. JMonkeyEngine также предоставляет вам для этого плагин Terrain Editor(Редактор ландшафта).

    Подробнее: Hello Terrain, Ландшафт, Редактор ландшафта
    Примеры кода: TerrainTest.java

    Как сделать небо?

    Примеры кода: TestSkyLoading.java

    rootNode.attachChild(SkyFactory.createSky( assetManager,
           "Textures/Sky/Bright/BrightSky.dds", false));
    skyGeo.setQueueBucket(Bucket.Sky)

    Подробнее: Небо


    Я хочу получить доступ к свойствам основной программно-аппаратной части(back-end)


    Как считать возможности видеокарты?

    Если ваша игра активно использует функции, которые старые видеокарты не поддерживают, вы можете Считать Возможности Видеокарты в самом начале перед началом app, и затем решить, как продолжать.

    Collection<com.jme3.renderer.Caps> caps = renderer.getCaps();
    Logger.getLogger(HelloJME3.class.getName()).log(Level.INFO, "Capabilities: {0}", caps.toString());

    Как запустить jMonkeyEngine 3 с OpenGL1?

    В вашей игре добавьте

    settings.setRenderer(AppSettings.LWJGL_OPENGL1)

    к AppSettings (см. подробности там).
    Для самого jMonkeyEngine SDK выберите Сервис ▸ Параметры ▸ OpenGL и поставьте галочку для OpenGL1.

    Как я могу оптимизировать расчет Графа Сцены?

    Вы можете группировать(batch) все геометрии в сцене (или под-узлы), которая остается статической.

    jme3tools.optimize.GeometryBatchFactory.optimize(rootNode);

    Группирование означает, что все геометрии с одним и тем же Материалом объединяются в одну сетку. Эта оптимизация действует только в том случае, если вы используете только несколько (примерно до 32) материалов. Окупаемость заключается в том, что группирование экономит некоторое количество времени, когда игра инициализируется.

    Как запретить пользователям распаковывать мой JAR?

    Добавьте obfuscator в сценарий Ant. SDK поставляется с базовым сценарием obfuscation, который можно включить в настройках проекта.


    Я хочу сделать математику


    Что означает addLocal()/multLocal() и.т.п.?

    Многие математические функции (mult(), add(), subtract() и.т.п.) Являются локальными и нелокальными (multLocal(), addLocal(), subtractLocal() и.т.д.).

    1. Нелокальный означает, что создается новый независимый объект (аналогично clone()) в качестве возвращаемого значения. Используйте нелокальные методы, если вы хотите продолжать использовать старое значение объекта, который вы вызываете методами.
      • Пример 1: Quaternion q1 = q2.mult(q3);
        • Возвращает результат в качестве нового Кватерниона q1.
        • Используемые объекты q2 и q3 остаются такими же, какими они и были, и их можно использовать повторно.
      • Пример 2: v.mult(b).add(b); 😄
        • Осторожно: Это вычисляет результат который должен использоваться, а если вы на самом деле его не используете, то возвращаемое значение отбрасывается!
    2. Локальный означает, что новые объекты не создаются, вместо этого изменяется вызывающий объект. Используйте это, если вы уверены, что вам больше не нужно старое значение вызываемого объекта.
      • Пример 1: q2.multLocal(q3)
        • Вычисляет q2*q3 без создания временных объектов.
        • Результат сохраняется в вызывающем объекте q2. Старое значение q2 потеряно.
        • Объект q3 остается таким же, каким он и был.
      • Пример 2: v.multLocal(a).addLocal(b);
        • Вычисляет ожидаемый результат без создания временных объектов.
        • Результат сохраняется в вызывающем объекте v. Старое значение v потеряно.
        • Объекты a и b остаются такими же, какими они и были.

    В чем разница между Глобальными(World) и Локальными(Local) координатами?

    Мировые координаты Spatial — это его настоящие координаты в 3D-сцене (это похоже на GPS координаты). Локальные координаты Spatial — это его координаты относительно родительского Spatial (это подобно высказыванию «Я на десять метров от входа»).

    Как преобразовывать Градусы в Радианы?

    Умножить значение в градусах на FastMath.DEG_TO_RAD, чтобы преобразовать его в радианы.


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

    Хотя мы рекомендуем jMonkeyEngine SDK для разработки JME3 игр, но вы можете использовать любую среду IDE (интегрированную среду разработки), такую как NetBeans или Eclipse, и даже свободно работать из командной строки. Вот общий независимый от IDE урок по «началу работы».

    В этом примере показано, как настроить и запустить простое приложение (HelloJME3), которое зависит от библиотек jMonkeyEngine3.

    Структура папок будет выглядеть следующим образом:

    jme3/
    jme3/lib
    jme3/src
    ...
    HelloJME3/
    HelloJME3/lib
    HelloJME3/assets
    HelloJME3/src
    ...

    Установка JME3 Фреймворка

    Чтобы установить версию jme3 для разработки, загрузите последнюю стабильную версию, распакуйте папку в каталог с название jme3. Названия файлов здесь всего лишь для примера, но они всегда будут чем-то вроде jME3.x-stable.

    mkdir jme3
    cd jme3
    unzip jME3.1-stable.zip

    Кроме того, вы можете собирать JME3 из исходников. (Рекомендуется для разработчиков JME3.)

    svn checkout https://jmonkeyengine.googlecode.com/svn/branches/3.0final/engine jme3
    cd jme3
    ant run
    cd ..

    Если вы видите, что Test Chooser приложения теперь открыто, значит сборка прошла успешно.

    Используйте просто ant вместо ant run для соборки библиотек без запуска демонстраций.

    Пример структуры папок проекта

    Сначала мы создаем структуру папок и пакетов исходников для вашего игрового проекта. Обратите внимание, что папка игрового проекта HelloJME3 находится на том же уровне, что и ваша jme3. В этом примере мы создаем пакет Java, который мы назвали hello в папке исходников.

    mkdir HelloJME3
    mkdir HelloJME3/src
    mkdir HelloJME3/src/hello

    Библиотеки

    Затем вы копируете необходимые JAR библиотеки из загруженных в свой проект. Вам нужно выполнять этот набор шагов каждый раз при скачивании новой сборки JME3. Подробное описание отдельных файлов jar см. в этом списке.

    mkdir HelloJME3/build
    mkdir HelloJME3/lib
    cp jme3/lib/*.* HelloJME3/lib

    Если вы собрали JME3 из исходников, значит пути копирования разные:

    mkdir HelloJME3/build
    mkdir HelloJME3/lib
    cp jme3/dist/*.* HelloJME3/lib

    Пример кода

    Чтобы протестировать вашу настройку, создайте файл HelloJME3/src/hello/HelloJME3.java с помощью любого текстового редактора, и вставьте следующий пример кода и сохраните.

    package hello;
    
    import com.jme3.app.SimpleApplication;
    import com.jme3.material.Material;
    import com.jme3.math.Vector3f;
    import com.jme3.scene.Geometry;
    import com.jme3.scene.shape.Box;
    import com.jme3.math.ColorRGBA;
    
    public class HelloJME3 extends SimpleApplication {
    
        public static void main(String[] args){
            HelloJME3 app = new HelloJME3();
            app.start();
        }
    
        @Override
        public void simpleInitApp() {
            Box b = new Box(Vector3f.ZERO, 1, 1, 1);
            Geometry geom = new Geometry("Box", b);
            Material mat = new Material(assetManager,
              "Common/MatDefs/Misc/Unshaded.j3md");
            mat.setColor("Color", ColorRGBA.Blue);
            geom.setMaterial(mat);
            rootNode.attachChild(geom);
        }
    }

    Сборка и Запуск

    Мы соберем образец приложения в папке сборки…

    cd HelloJME3
    javac -d build -cp "lib/eventbus-1.4.jar:lib/j-ogg-oggd.jar:lib/j-ogg-vorbisd.jar:lib/jME3-lwjgl-
    natives.jar:lib/jbullet.jar:lib/jinput.jar:lib/lwjgl.jar:lib/stack-alloc.jar:lib/vecmath.jar:lib/xmlpull-xpp3-
    1.1.4c.jar:lib/jME3-blender.jar:lib/jME3-core.jar:lib/jME3-desktop.jar:lib/jME3-jogg.jar:lib/jME3-plugins.jar:lib/jME3-
    terrain.jar:lib/jME3-testdata.jar:lib/jME3-niftygui.jar:lib/nifty-default-controls.jar:lib/nifty-examples.jar:lib/nifty-style-
    black.jar:lib/nifty.jar:." src/hello/HelloJME3.java

    … и запустим его.

    cd build
    java -cp "../lib/eventbus-1.4.jar:../lib/j-ogg-oggd.jar:../lib/j-ogg-vorbisd.jar:../lib/jME3-lwjgl-
    natives.jar:../lib/jbullet.jar:../lib/jinput.jar:../lib/lwjgl.jar:../lib/stack-alloc.jar:../lib/vecmath.jar:../lib/xmlpull-xpp3-
    1.1.4c.jar:../lib/jME3-blender.jar:../lib/jME3-core.jar:../lib/jME3-desktop.jar:../lib/jME3-jogg.jar:../lib/jME3-
    plugins.jar:../lib/jME3-terrain.jar:../lib/jME3-testdata.jar:../lib/jME3-niftygui.jar:../lib/nifty-default-
    controls.jar:../lib/nifty-examples.jar:../lib/nifty-style-black.jar:../lib/nifty.jar:." hello/HelloJME3
    Если вы используете Windows, разделитель classpath имеет значение \ вместо /

    Если появится диалоговое окно настроек, подтвердите настройки по умолчанию. Теперь вы должны увидеть простое окно с 3D кубом. Используйте мышь и клавиши WASD для перемещения. Оно работает!

    Рекомендуемая структура папок Asset

    Для мультимедийных файлов, моделей и других игровых ресурсов мы рекомендуем создать следующую структуру проекта:

    cd HelloJME3
    mkdir assets
    mkdir assets/Interface
    mkdir assets/Materials
    mkdir assets/MatDefs
    mkdir assets/Models
    mkdir assets/Scenes
    mkdir assets/Shaders
    mkdir assets/Sounds
    mkdir assets/Textures

    Эта структура папок позволит AssassManager идущему по умолчанию в SimpleApplication загружать медиафайлы из вашей папки assets, как в этом примере:

    import com.jme3.scene.Spatial;
    ...
      Spatial elephant = assetManager.loadModel("Models/Elephant/Elephant.meshxml");
      rootNode.attachChild(elephant);
    ...

    Вы узнаете больше об asset manager и о том, как его настроить позже. А пока не стесняйтесь структурировать свои игровые ресурсы (изображения, текстуры, модели) в дальнейшие подкаталоги, например, как в этом примере в папке assets/models/Elephant, находится модель elephant.mesh.xml и ее материалы.

    Следующий шаг

    Теперь следуйте урокам и напишите свою первую игру jMonkeyEngine.


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

    На этой странице описывается, как вы можете обернуть любую jar библиотеку в плагин, который пользователь jMonkeyEngine SDK может загрузить, установить, а затем использовать содержащуюся библиотеку в своих собственных игровых проектах.

    Убедитесь, что ваш SDK настроен для разработки плагинов, как описано здесь.

    Создание проекта плагина (в jMonkeyEngine SDK):

    • Создайте новый Набор модулей (или используйте существующий)
    • Откройте пакет, щелкните [ПК мыши] папку Модули и выберите Добавить новый.
    • Где Имя проекта введите название строчными буквами и без пробелов, например так my-library
    • Убедитесь что Расположение проекта внутри папки этого набора модулей нажмите [Далее]
    • Введите базовый java пакет для вашего плагина в Кодовое имя например так com.mycompany.plugins.mylibrary
    • Введите Отображаемое имя модуля для вашего плагина, например так My Library
    • Нажмите [Готово]

    Добавление библиотеки:

    • Щелкните [ПК мыши] проект Модуля и выберите Новый ▸ Другое
    • В разделе Разработка модулей выберите шаблон Дескриптор библиотеки Java SE и нажмите [Далее].
    • Если у вас еще нет внешней библиотеки, зарегистрированной в jMonkeyEngine SDK, нажмите [Управление библиотеками] и выполните следующие действия:
      • Нажмите [Создать библиотеку], введите имя библиотеки и нажмите [ОК].
      • На вкладке Путь к классам нажмите [Добавить файл JAR/Папку] и выберите файл(ы) jar, необходимый для библиотеки
      • На вкладке Документация JavaDoc нажмите [Добавить архив ZIP или Папку] и добавьте javadoc для библиотеки (архив или папку)
      • На вкладке Исходные файлы вы можете добавить jar файл или папки, содержащий исходные файлы библиотеки, если они доступны
      • Нажмите [OK]
    • Выберите внешнюю библиотеку из списка и нажмите [Далее].
    • Введите имя для библиотеки (используется имя файла в качестве описания файла)
    • Введите отображаемое имя для библиотеки (это имя, которое пользователь видит позже в своем списке)
    • Нажмите [OK]

    Вы увидите новый файл MyLibrary.xml который создастся в базовом пакете плагинов и связан с файлом layer.xml. Кроме того, jar файл и sources/javadoc копируются в папку release в корне проекта. В основном так, вы можете настроить номер версии, файл лицензии (должен быть помещен в корневую папку модуля) и многое другое через Свойства модуля.

    Обратите внимание, что файлы в папке release не обновляются автоматически при изменении библиотеки, вам необходимо вручную упаковать и заменить jar и zip файлы. Смотрите расширение сценария сборки в приведенной ниже ссылке о том, как вы можете сделать сценарий сборки модуля автоматическим.

    После того, как вы закончите, вы можете внести плагин в центр обновления вкладов jMonkeyEngine SDK.


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

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

    ProjectAssetManager

    Все объекты AssetDataObjects и SceneExplorerNodes позволяют получить доступ к ProjectAssetManager проекта, из которого они были загружены.

    ProjectAssetManager pm = node.getLookup().lookup(ProjectAssetManager.class)

    ProjectAssetManager по большей части является обычным DesktopAssetManager для каждого проекта с добавленной функциональностью:

    • Доступ к файлу FileObject в папке assets проекта для загрузки и сохранения данных
    • Преобразование полных путей файлов в пути относительных игровых ресурсов и наоборот
    • Получение списков всех текстур, материалов и.т.п. в проекте
    • И более удобный вещи.. :)

    AssetDataObject

    Большинство «файлов», с которыми вы сталкиваетесь в SDK, поступают в виде объектов AssetDataObjects. Все узлы, с которыми вы сталкиваетесь, содержат объект AssetDataObject, из которого они были загружены. Он обеспечивает не только доступ к FileObject конкретного файла, но и объект AssetData, который позволяет получить доступ к конкретным свойствам и данным jME. Объект AssetData также позволяет загружать объект через jME3 assetManager. Он доступен через поиск Узла или объекта AssetDataObject:

    assetDataObject.getLookup().lookup(AssetData.class)

    Новые типы файлов Asset

    Когда вы добавляете новый тип файла для формата модели или другой тип файлов игровых ресурсов, который может быть загружен в jME3, вы можете начать с использования шаблона нового типа файла (Создать файл ▸ Разработка модулей ▸ Тип файла). Измените объект DataObject, чтобы расширить AssetDataObject (общий), SpatialAssetDataObject (некоторый тип модели) или BinaryModelDataObject (в основном j3o сохраняемый файл). И, возможно, переопределите методы loadAsset и saveAsset, которые используются объектом AssetData, чтобы вернуть правильный AssetKey тип (необходимый для работы импорта свойств).

    public class BlenderDataObject extends SpatialAssetDataObject {
        public BlenderDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException {
            super(pf, loader);
        }
    }

    Класс AssetManagerConfigurator может быть создан, чтобы настроить assetManager проектов и импортера модели для использования нового типа игрового ресурса:

    @org.openide.util.lookup.ServiceProvider(service = AssetManagerConfigurator.class)
    public class BlenderAssetManagerConfigurator implements AssetManagerConfigurator {
        public void prepareManager(AssetManager manager) {
            manager.registerLoader(com.jme3.scene.plugins.blender.BlenderModelLoader.class, "blend");
        }
    }

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

    Добавление типов Узлов в SceneExplorer

    Если ваш плагин приносит свои собственные объекты в SceneGraph, вы все равно можете с ними работать как с любым другим элементом SceneExplorer, включая их специальные свойства.

    Если вы хотите поддерживать специальные свойства ваших объектов, которые не обнаруживаются SDK автоматически, вам придется создать свой собственный класс, который расширяет org.openide.nodes.Node и реализует интерфейс com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode. Затем вы регистрируете этот класс, добавляя

    @org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class)

    над телом вашего класса. То есть, все ваш Spatial-тип будет автоматически использоваться и отображаться в SceneExplorer. Убедитесь, что вы зарегистрировали jar с используемыми классами в настройках плагина под «wrapped libraries», иначе среда IDE не сможет получить доступ к этим классам.

    AbstractSceneExplorerNode предлагает некоторые другие полезные функции, которые вы можете добавить, например, автоматическое создание корректно заданных свойств и.т.п. JmeSpatial, например, основывается на нем. Простой пример SceneExplorerNode для объекта, расширяющего Spatial, будет JmeGeometry (см. Ниже). Редакторы для специальных типов переменных могут быть добавлены с помощью интерфейса SceneExplorerPropertyEditor, который также может быть зарегистрирован как ServiceProvider.

    SceneExplorerNode может использоваться для объектов типа Spatial и Control.

    • Добавьте в свой проект «Nodes API» и «Lookup API», если вы хотите использовать этот

    Пример Spatial

    @org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class)
    public class JmeGeometry extends JmeSpatial {
    
        private static Image smallImage =
                ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/geometry.gif");
        private Geometry geom;
    
        public JmeGeometry() {
        }
    
        public JmeGeometry(Geometry spatial, SceneExplorerChildren children) {
            super(spatial, children);
            getLookupContents().add(spatial);
            this.geom = spatial;
            setName(spatial.getName());
        }
    
        @Override
        public Image getIcon(int type) {
            return smallImage;
        }
    
        @Override
        public Image getOpenedIcon(int type) {
            return smallImage;
        }
    
        @Override
        protected Sheet createSheet() {
            Sheet sheet = super.createSheet();
            Sheet.Set set = Sheet.createPropertiesSet();
            set.setDisplayName("Geometry");
            set.setName(Geometry.class.getName());
            Geometry obj = geom;//getLookup().lookup(Geometry.class);
            if (obj == null) {
                return sheet;
            }
    
            set.put(makeProperty(obj, int.class, "getLodLevel", "setLodLevel", "Lod Level"));
            set.put(makeProperty(obj, Material.class, "getMaterial", "setMaterial", "Material"));
            set.put(makeProperty(obj, Mesh.class, "getMesh", "Mesh"));
    
            sheet.put(set);
            return sheet;
    
        }
    
        public Class getExplorerObjectClass() {
            return Geometry.class;
        }
    
        public Class getExplorerNodeClass() {
            return JmeGeometry.class;
        }
    
        public org.openide.nodes.Node[] createNodes(Object key, Object key2, boolean readOnly) {
            SceneExplorerChildren children=new SceneExplorerChildren((com.jme3.scene.Spatial)key);
            children.setReadOnly(readOnly);
            return new org.openide.nodes.Node[]{new JmeGeometry((Geometry) key, children).setReadOnly(readOnly)};
        }
    }

    Пример Control

    @org.openide.util.lookup.ServiceProvider(service=SceneExplorerNode.class)
    public class JmeGhostControl extends AbstractSceneExplorerNode {
    
        private static Image smallImage =
                ImageUtilities.loadImage("com/jme3/gde/core/sceneexplorer/nodes/icons/ghostcontrol.gif");
        private GhostControl control;
    
        public JmeGhostControl() {
        }
    
        public JmeGhostControl(GhostControl control, DataObject dataObject) {
            super(dataObject);
            getLookupContents().add(this);
            getLookupContents().add(control);
            this.control = control;
            setName("GhostControl");
        }
    
        @Override
        public Image getIcon(int type) {
            return smallImage;
        }
    
        @Override
        public Image getOpenedIcon(int type) {
            return smallImage;
        }
    
        protected SystemAction[] createActions() {
            return new SystemAction[]{
                        //                    SystemAction.get(CopyAction.class),
                        //                    SystemAction.get(CutAction.class),
                        //                    SystemAction.get(PasteAction.class),
                        SystemAction.get(DeleteAction.class)
                    };
        }
    
        @Override
        public boolean canDestroy() {
            return !readOnly;
        }
    
        @Override
        public void destroy() throws IOException {
            super.destroy();
            final Spatial spat=getParentNode().getLookup().lookup(Spatial.class);
            try {
                SceneApplication.getApplication().enqueue(new Callable<Void>() {
    
                    public Void call() throws Exception {
                        spat.removeControl(control);
                        return null;
                    }
                }).get();
                ((AbstractSceneExplorerNode)getParentNode()).refresh(true);
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            } catch (ExecutionException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    
        @Override
        protected Sheet createSheet() {
            Sheet sheet = super.createSheet();
            Sheet.Set set = Sheet.createPropertiesSet();
            set.setDisplayName("GhostControl");
            set.setName(GhostControl.class.getName());
            GhostControl obj = control;//getLookup().lookup(Spatial.class);
            if (obj == null) {
                return sheet;
            }
    
            set.put(makeProperty(obj, Vector3f.class, "getPhysicsLocation", "setPhysicsLocation", "Physics Location"));
            set.put(makeProperty(obj, Quaternion.class, "getPhysicsRotation", "setPhysicsRotation", "Physics Rotation"));
    
            set.put(makeProperty(obj, CollisionShape.class, "getCollisionShape", "setCollisionShape", "Collision Shape"));
            set.put(makeProperty(obj, int.class, "getCollisionGroup", "setCollisionGroup", "Collision Group"));
            set.put(makeProperty(obj, int.class, "getCollideWithGroups", "setCollideWithGroups", "Collide With Groups"));
    
            sheet.put(set);
            return sheet;
    
        }
    
        public Class getExplorerObjectClass() {
            return GhostControl.class;
        }
    
        public Class getExplorerNodeClass() {
            return JmeGhostControl.class;
        }
    
        public org.openide.nodes.Node[] createNodes(Object key, DataObject key2, boolean cookie) {
            return new org.openide.nodes.Node[]{new JmeGhostControl((GhostControl) key, key2).setReadOnly(cookie)};
        }
    }

    Добавление элементов в меню добавления и инструменты

    Чтобы добавить Spatials, Contols и для общих инструментов, вы можете создавать абстрактные классы, которые вы можете использовать для расширения опций. Отменить/Повторить обрабатывается абстрактным классом. AbstractNewSpatial*Wizard*Action позволяет показать мастер AWT перед созданием Spatial. Вы также можете просто реализовать базовый класс ServiceProvider и вернуть любой тип действия (например, мастер), в этом случае вам придется обрабатывать потоки самостоятельно!

    Обратите внимание, что классы, которые вы создаете одноэлементны, которые используются на нескольких узлах, и вы не должны хранить любые данные в локальных переменных!

    Чтобы добавить новый Инструмент(Tool), создайте новый AbstractToolAction:

    @org.openide.util.lookup.ServiceProvider(service = ToolAction.class)
    public class GenerateTangentsTool extends AbstractToolAction {
    
        public GenerateTangentsTool() {
            name = "Generate Tangents";
        }
    
        @Override
        protected Object doApplyTool(AbstractSceneExplorerNode rootNode) {
            Geometry geom = rootNode.getLookup().lookup(Geometry.class);
            Mesh mesh = geom.getMesh();
            if (mesh != null) {
                TangentBinormalGenerator.generate(mesh);
            }
            return geom;
        }
    
        @Override
        protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) {
            Geometry geom = rootNode.getLookup().lookup(Geometry.class);
            Mesh mesh = geom.getMesh();
            if (mesh != null) {
                mesh.clearBuffer(Type.Tangent);
            }
        }
    
        public Class<?> getNodeClass() {
            return JmeGeometry.class;
        }
    
    }

    Для нового Spatial или Control используйте AbstractNewSpatialAction

    @org.openide.util.lookup.ServiceProvider(service = NewSpatialAction.class)
    public class NewSpecialSpatialAction extends AbstractNewSpatialAction {
    
        public NewSpecialSpatialAction() {
            name = "Spatial";
        }
    
        @Override
        protected Spatial doCreateSpatial(Node parent) {
            Spatial spatial=new Node();
            return spatial;
        }
    }

    или AbstractNewControlAction:

    @org.openide.util.lookup.ServiceProvider(service = NewControlAction.class)
    public class NewRigidBodyAction extends AbstractNewControlAction {
    
        public NewRigidBodyAction() {
            name = "Static RigidBody";
        }
    
        @Override
        protected Control doCreateControl(Spatial spatial) {
            RigidBodyControl control = spatial.getControl(RigidBodyControl.class);
            if (control != null) {
                spatial.removeControl(control);
            }
            Node parent = spatial.getParent();
            spatial.removeFromParent();
            control = new RigidBodyControl(0);
            if (parent != null) {
                parent.attachChild(spatial);
            }
            return control;
        }
    }

    Добавление с помощью мастера

    Вы можете создать новый мастер с помощью шаблона мастера в SDK (Создать Файл ▸ Разработка модулей ▸ Мастер). Действие, созданное шаблоном, может быть легко изменено на добавления Control или Spatial или для применения Инструмента(Tool). Обратите внимание, что здесь мы расширяем действие AbstractNewSpatial*Wizard*.

    Хорошим примером является «Мастер Добавления SkyBox»:

    @org.openide.util.lookup.ServiceProvider(service = NewSpatialAction.class)
    public class AddSkyboxAction extends AbstractNewSpatialWizardAction {
    
        private WizardDescriptor.Panel[] panels;
    
        public AddSkyboxAction() {
            name = "Skybox..";
        }
    
        @Override
        protected Object showWizard(org.openide.nodes.Node node) {
            WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels());
            wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
            wizardDescriptor.setTitle("Skybox Wizard");
            Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
            dialog.setVisible(true);
            dialog.toFront();
            boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION;
            if (!cancelled) {
                return wizardDescriptor;
            }
            return null;
        }
    
        @Override
        protected Spatial doCreateSpatial(Node parent, Object properties) {
            if (properties != null) {
                return generateSkybox((WizardDescriptor) properties);
            }
            return null;
        }
    
        private Spatial generateSkybox(WizardDescriptor wiz) {
            if ((Boolean) wiz.getProperty("multipleTextures")) {
                Texture south = (Texture) wiz.getProperty("textureSouth");
                Texture north = (Texture) wiz.getProperty("textureNorth");
                Texture east = (Texture) wiz.getProperty("textureEast");
                Texture west = (Texture) wiz.getProperty("textureWest");
                Texture top = (Texture) wiz.getProperty("textureTop");
                Texture bottom = (Texture) wiz.getProperty("textureBottom");
                Vector3f normalScale = (Vector3f) wiz.getProperty("normalScale");
                return SkyFactory.createSky(pm, west, east, north, south, top, bottom, normalScale);
            } else {
                Texture textureSingle = (Texture) wiz.getProperty("textureSingle");
                Vector3f normalScale = (Vector3f) wiz.getProperty("normalScale");
                boolean useSpheremap = (Boolean) wiz.getProperty("useSpheremap");
                return SkyFactory.createSky(pm, textureSingle, normalScale, useSpheremap);
            }
        }
    
        /**
         * Инициализируем панели, представляющих отдельные шаги мастера, и 
         * задаём различные свойства, влияющие на внешний вид мастера.
         */
        private WizardDescriptor.Panel[] getPanels() {
            if (panels == null) {
                panels = new WizardDescriptor.Panel[]{
                            new SkyboxWizardPanel1(),
                            new SkyboxWizardPanel2()
                        };
                String[] steps = new String[panels.length];
                for (int i = 0; i < panels.length; i++) {
                    Component c = panels[i].getComponent();
                    // Название шага по умолчанию к названию компонента панели.
                    // В основном полезно для получения названия выбранной цели в
                    // списке шагов.
                    steps[i] = c.getName();
                    if (c instanceof JComponent) { // предположим, что компоненты Swing
                        JComponent jc = (JComponent) c;
                        // Зададим номер шага компонента
                        // TODO при использовании org.openide.dialogs >= 7.8, может использовать WizardDescriptor.PROP_*:
                        jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i));
                        // Зададим название шага для панели
                        jc.putClientProperty("WizardPanel_contentData", steps);
                        // Включим создание подзаголовка на каждом шаге
                        jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE);
                        // Покажем шаги с левой стороны с фоновым изображением
                        jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE);
                        // Включим нумерацию всех шагов
                        jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE);
                    }
                }
            }
            return panels;
        }
    }
    Абстрактные spatial и control, реализуют действия отмены/повтора автоматически, для ToolActions, и вы должны реализовать их самостоятельно.

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

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