Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество
Главная
    Документация jMonkeyEngine
        jMonkeyEngine Уроки и Документация
            jMonkeyEngine3: Привет мир, Обучающая Серия
                jMonkeyEngine 3 Урок (2) — Hello Node

jMonkeyEngine 3 Урок (2) — Hello Node

Опубликованно: 25.01.2016, 19:58
Последняя редакция, Andry: 25.09.2017 21:13

Предыдущий: Hello SimpleApplication, Следующий: Hello Assets.

В этом уроке мы рассмотрим создание 3D сцены.

При создании 3D-игры:

  1. Вы создаете некоторые графические объекты такие, как игроки, здания и так далее.
  2. Вы добавляете объекты в сцену.
  3. Вы перемещаете, изменяете размер, поворачиваете, настраиваете цвет и оживляете их.

Вы узнаете, что граф сцены представляет собой 3D мир и почему корневой (родительский) узел (rootNode) важен. Вы узнаете, как создавать простые объекты, как им давать пользовательские данные (такие как состояние здоровья), и как «трансформировать» их; двигать, масштабировать и вращать. Вы поймете разницу между двумя типами “Spatials” в графе сцены: Узлами и Геометриями.

Пример кода:

package jme3test.helloworld;

import com.jme3.app.SimpleApplication;
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.shape.Box;

/** Пример 2 – как использовать узлы в качестве рычага, для управления объектами на сцене.
 * Вы можете вращать, переводить и масштабировать объекты, манипулируя их родительскими узлами.
 * Особенность корневого узла: только то, что прикрепленно к нему, появляется на сцене. */
public class HelloNode extends SimpleApplication {

    public static void main(String[] args){
        HelloNode app = new HelloNode();
        app.start();
    }

    @Override
    public void simpleInitApp() {

        /** Создание синего коуба с координатами (1,-1,1) */
        Box box1 = new Box(1,1,1);
        Geometry blue = new Geometry("Box", box1);
        blue.setLocalTranslation(new Vector3f(1,-1,1));
        Material mat1 = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat1.setColor("Color", ColorRGBA.Blue);
        blue.setMaterial(mat1);

        /** Создание красного куба прямо над синим (1,3,1) */
        Box box2 = new Box(1,1,1); 
        Geometry red = new Geometry("Box", box2);
        red.setLocalTranslation(new Vector3f(1,3,1));
        Material mat2 = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat2.setColor("Color", ColorRGBA.Red);
        red.setMaterial(mat2);

        /** Создать стержневой узел в (0,0,0) и прикрепить его к корневому узлу. */
        Node pivot = new Node("pivot");
        rootNode.attachChild(pivot); // поместить этот узел на сцену
        /** Прикрепить два куба к этому узлу. (Который идентичен корневому.) */
        pivot.attachChild(blue);
        pivot.attachChild(red);
        /** Поверните наш новый узел: заметьте, оба куба поворачиваются! */
        pivot.rotate(.4f,.4f,0f);
    }
}

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


Понимание терминологии

В этом уроке вы узнаете некоторые новые термины: 

Что вы хотите сделать Как вы скажете на языке JME3
Скомпоновать 3D сцену Заполнить граф сцены
Создать объекты сцены Создать Spatials (например, создать Геометрию)
Сделать объект видимым на сцене Присоединить Spatial к родительскому узлу (rootNode)
Сделать объект исчезающим со сцены Отсоединить Spatial от rootNode
Расположение/движение, повернуть или изменить размер объекта Переместить или вращать, или масштабировать объект = трансформация (преобразование) объекта

Каждое JME3 приложение имеет корневой узел (rootNode). Ваша игра автоматически наследует объект – корневой узел (rootNode) от базового приложения (SimpleApplication). Все прикрепленное к корневому узлу является частью графа сцены. Элементы графа сцены – Spatial (пространственные или те, кто занимает какое-то пространство).

  • Spatial содержит местоположение, вращение и масштаб(размер) объекта.
  • Spatial может быть загружен, изменен и сохранен.
  • Есть два вида Spatial: Узлы и Геометрии.
  Геометрия Узел
Видимость: Геометрия является видимым объектом сцены Узел является невидимым «рычагом» для объектов сцены.
Цель: Геометрии сохраняют внешний вид объекта. Узел группирует Геометрии и другие Узлы вместе.
Примеры: Коробка, сфера, игрок, здание, кусочек местности, транспортного средства, ракет, агенты ИИ, и.т.д … Корневой узел(rootNode), напольный узел, группирующий несколько территорий, пользовательский узел, связывающий пассажира и автомобиль, игрока и оружие, аудио узел(audio node).

Понимание кода

Что происходит в этом фрагменте кода? Вы используете метод simpleInitApp(), который был введен в первом уроке, чтобы инициализировать сцену.

  1. Вы создаете первую Геометрию куб.
    • Создаёте фигуру куба(Box) с размером (1, 1, 1), что создаст куб в 2*2*2 условных единиц измерения.
    • Располагаете куб в (1, -1, 1), используя метод setLocalTranslation().
    • Оборачиваете фигуру куба в Геометриею.
    • Создаёте синий материал.
    • Применяете материал к Геометрии куба.
    •     Box box1 = new Box(1,1,1);
          Geometry blue = new Geometry("Box", box1);
          blue.setLocalTranslation(new Vector3f(1,-1,1));
          Material mat1 = new Material(assetManager,"Common/MatDefs/Misc/Unshaded.j3md");
          mat1.setColor("Color", ColorRGBA.Blue);
          blue.setMaterial(mat1);
      
  2. Вы создаете вторую Геометрию куба.
    • Создаёте вторую фигуру куба(Box) с тем же размером.
    • Располагаете второй куб в (1, 3, 1). Это прямо над первым кубом, с промежутком в 2 единицы мира между ними.
    • Оборачиваете фигуру куба в Геометриею.
    • Создаёте красный материал.
    • Применяете материал к Геометрии куба.
    •     Box box2 = new Box(1,1,1);
          Geometry red = new Geometry("Box", box2);
          red.setLocalTranslation(new Vector3f(1,3,1));
          Material mat2 = new Material(assetManager,
            "Common/MatDefs/Misc/Unshaded.j3md");
          mat2.setColor("Color", ColorRGBA.Red);
          red.setMaterial(mat2);
      
  3. Создаёте стержневой узел.
    • Называете стержневой узел pivot.
    • По умолчанию узел расположен на (0,0,0).
    • Прикрепляете узел к корневому узлу.
    • Узел не имеет видимых проявлений на сцене.
    •     Node pivot = new Node("pivot");
          rootNode.attachChild(pivot);
      

      Если вы запустите приложение только с кодом до этого места, сцена окажется пустой. Это потому, что узел является невидимым, и вы еще не присоединили никаких видимых Геометрий к rootNode.

  4. Присоедините два куба к стержневому узлу.
            pivot.attachChild(blue);
            pivot.attachChild(red);
    

    Если вы запустите приложение только с кодом до этого места, вы увидите два куба: красный куб прямо над синим кубом.

  5. Поверните стержневой узел.
            pivot.rotate( 0.4f , 0.4f , 0.0f );
    

    Если вы запустите приложение теперь, то вы увидите два куба друг над другом — и наклоненных под одним и тем же углом.


Что такое стержневой узел (Pivot Node)?

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

  • В этом примере, вы сгруппировали две Геометрии путем присоединения их к одному узлу вращения. Вы используете стержневой  узел в качестве рычага, чтобы повернуть две Геометрии вместе вокруг одного общего центра. Вращающийся стержневой узел вращает все подключенные Геометрии за один шаг. Ось узла является центром вращения. Перед присоединением других Геометрий, убедитесь, что стержневой узел расположен в точке (0,0,0). Преобразование родительского узла преобразует всех подключенных к нему потомков Spatials. Вы будете часто использовать этот метод в играх, когда вы перемещаете Spatials кругом. 
    Примеры: автомобиль и его водитель движутся вместе; планета с ее луной вращаются вокруг солнца.
  • Противоположный вариант: если вы не создадите стержневой узел и попробуете преобразовать Геометрии, то каждое изменение нужно делать относительно каждой Геометрии (ее центра).
    Например: если непосредственно вращать каждый кубик (используя команды red.rotate(0.1f , 0.2f , 0.3f); и blue.rotate(0.5f , 0.0f , 0.25f);) то каждый куб будет вращаться индивидуально вокруг своего центра. Это похоже на планеты, вращающиеся вокруг своего центра.

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

Задача…? Решение!
Создание Spatial Создать фигуру сетки (Mesh), оберните ее в Геометрию, и назначьте ей материал. Например:

Box mesh = new Box(Vector3f.ZERO, 1, 1, 1); // по умолчанию куб
Geometry thing = new Geometry("thing", mesh);
Material mat = new Material(assetManager, 
   "Common/MatDefs/Misc/ShowNormals.j3md");
thing.setMaterial(mat);

 

Чтобы объекты появились на сцене Прикрепите Spatial к корневому узлу rootNode, или к любому узлу, который прикреплен к корневому узлу:

rootNode.attachChild(thing);

 

Удаление объектов со сцены Отсоедините Spatial от корневого узла или другого узла, который прикреплен к корневому узлу:

rootNode.detachChild(thing);
rootNode.detachAllChildren();
 

Найти объект на сцене по его имени или ID, или по его положению в иерархии родитель-потомок.

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

Spatial thing = rootNode.getChild("thing");
Spatial twentyThird = rootNode.getChild(22);
Spatial parent = myNode.getParent();
Указать, что должно быть загружено при старте Все что вы инициализируете и прикрепляете к корневому узлу rootNode в методе базового приложения simpleInitApp() является частью сцены при старте игры.

Как мне перемещать Spatials?

Есть три типа 3D преобразования: Перемещение(Translation), Масштабирование(Scaling) и Вращение(Rotation).

Движения перемещения Spatials Ось-х Ось-у Ось-z
Укажите новое местоположение в трех измерениях: как далеко это от начала координат оно происходит вправо-вверх-вперед?

Чтобы переместить Spatial в определенные координаты, например, (0,40.2f,-2), используйте:

thing.setLocalTranslation( new Vector3f( 0.0f, 40.2f, -2.0f ) );

Для перемещения Spatial на определенное расстояние, например, выше (y=40.2f) и далее назад (z=-2.0f):

thing.move( 0.0f, 40.2f, -2.0f );	
+ вправо

— влево

+ вверх

— вниз

+ вперед

— назад

Изменение масштаба(размера) Spatial Ось-х Ось-у Ось-z
Укажите коэффициент масштабирования в каждом измерении: длина, высота, ширина. Значение между 0.0f и 1.0f сжимают Spatial, больше, чем 1.0f растягивает его, а 1.0f сохраняет прежний масштаб.
Использование для каждого измерения тех же самых значений, масштабирование получается пропорциональным, а различные значения будут растягивать объект.
Попробуйте масштабировать Spatial с коэффициентом  10.0f – в длину, 0,1f — в высоту и 1.0f в ширину.

thing.scale( 10.0f, 0.1f, 1.0f );	
Ширина Высота Длина
Вращение Spatials Ось-х Ось-у Ось-z
3D вращение немного сложней (узнать подробности здесь). Короче говоря: вы можете вращать вокруг трех осей: Тангаж(Pitch), Рысканье(Yaw), Крен(Roll). Вы можете указывать углы в градусах путем умножения значения градусов с FastMath.DEG_TO_RAD.

Крен объекта на 180° градусов вокруг оси z:

thing.rotate( 0f , 0f , 180*FastMath.DEG_TO_RAD );
Если ваша игровая идея требует серьезного объема вращений, то стоит посмотреть – что такое кватернионы, структура данных которая позволяет объединять и хранить вращения эффективно.
thing.setLocalRotation(
   new Quaternion().fromAngleAxis(180*FastMath.DEG_TO_RAD, new Vector3f(1,0,0)));
Тангаж = Положительное кивание головой. Рысканье = Отрицательное вращение головой.

 

Крен = Движения головой к плечам.

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

Если вы получаете неожиданные результаты, проверьте, возможно, вы сделали следующие распространенные ошибки:

Проблема? Решение!
Созданная Геометрия не появляется на сцене Вы прикрепили ее (узлу, который прикреплен к) к корневому узлу( rootNode)?
Имеется ли у нее материал?
Каково ее перемещение (расположение)?
Возможно, это положение за камерой или закрыто другой Геометрией?
Возможно она слишком мала или огромна чтобы её можно было увидеть?
Это слишком далеко от камеры? (Попробуй cam.setFrustumFar(111111f); видимость увеличится)
Spatial вращается в неожиданном направлении Использовали ли вы значения в радианах или градусах? (Если в градусах, то нужно перемножить с FastMath.DEG_TO_RAD, чтобы преобразовать в радианы)
Вы создали Spatial в начале координат (Vector.ZERO) до начала его движения?
Вы вращаете вокруг предполагаемого стержневого узла или вокруг чего-то еще?
Вы вращали вокруг правой оси?
Геометрия имеет неожиданный цвет или материал. Вы используете повторно материал на другой Геометрии и случайно поменяли свойства? (если так, то сделайте клонирование mat2 = mat.clone(); )

Как добавить пользовательские данные к Spatial?

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

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

Вы можете добавлять пользовательские данные непосредственно к любому узлу или геометрии. Вам не нужно расширять класс Node, чтобы включить переменные! Например, чтобы добавить такие пользовательские данные как идентификационный номер(ID) узла:

pivot.setUserData( "pivot id", 42 );

Чтобы получить идентификационный номер этого узла в другом месте, вы должны использовать:

int id = pivot.getUserData( "pivot id" );

Используя различные строковые ключи (здесь ключи – это id стержни), вы можете получить и установить несколько значений любых данных которые должен переносить Spatial. Когда вы начнете писать свою игру, вы можете добавить значения топлива к узлу автомобиля, значения скорости к узлу самолета или количество золотых монет к узлу игрока и многое другое. Однако, следует отметить, что только пользовательские объекты с интерфейсом Savable могут быть переданы.


Вывод

Вы узнали, что ваша 3D сцена — это граф сцены состоящий из Spatial: видимых Геометрий и невидимых Узлов. Вы можете преобразовывать Spatial, или прикреплять их к узлам и преобразовывать узлы. Вы знаете самый простой способ, как добавить пользовательские свойства объекта (таких как здоровье игрока или скорость авто) в Spatial.

Такие стандартные фигуры, как сферы и кубы быстро надоедают, переходите к следующему уроку, где вы научитесь загружать игровые ресурсы, такие как 3D модели.


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

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

Содержание

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