This page has been translated automatically.
Основы UNIGINE
1. Введение
2. Виртуальные миры и работа с ними
3. Подготовка 3D моделей
4. Материалы
5. Камеры и освещение
7. Создание кат-сцен и запись видео
8. Подготовка проекта к релизу
9. Физика
10. Основы оптимизации
11. ПРОЕКТ2: Шутер от первого лица
12. ПРОЕКТ3: Аркадная гонка по пересеченной местности от 3-го лица
13. ПРОЕКТ4: VR приложение с простым взаимодействием

Перемещение и вращение объектов

The objects existing in the virtual world are often moving somewhere and rotating, in general, transforming. Each node has a transformation matrix that encodes its position, rotation, and scale in the world. If a node is a child of another node (part of its hierarchy), it has a transformation matrix associated with the parent (local). This is why the Node class has two different properties: Transform and WorldTransform, which handle local and world transformation matrices respectively.Существующие в виртуальном мире объекты то и дело куда-то движутся, поворачиваются – в общем – трансформируются. Каждая нода имеет матрицу трансформации, которая кодирует ее положение, поворот и масштаб в мире. Если нода является дочерней для другой ноды (входит в ее иерархию), она имеет матрицу преобразования, связанную с родительской (локальную). Вот почему класс Node имеет разные свойства: Transform и WorldTransform, которые работают с локальными и мировыми матрицами трансформации соответственно.

The following code shows how basic node transformations are performed:Следующий код показывает, как выполняются базовые преобразования нод:

Исходный код (C++)
// добавляем нужные пространства имен
using namespace Unigine;
using namespace Unigine::Math;

// перемещение ноды на X, Y, Z единиц вдоль соответствующих осей
node->setWorldPosition(node->getWorldPosition() + Vec3(X, Y, Z));

// перемещение ноды на 1 единицу по оси Y
node->worldTranslate(0.0f, 1.0f, 0.0f);

// поворот ноды вокруг оси (X, Y, Z) на угол Alpha
node->setWorldRotation(node->getWorldRotation() * quat(Vec3(X, Y, Z), Alpha));

// поворот ноды вокруг осей X, Y и Z на соответствующие углы (angle_X, angle_Y, angle_Z)
node->setWorldRotation(node->getWorldRotation() * quat(angle_X, angle_Y, angle_Z));

// поворот ноды на 45 градусов вокруг оси Z
node->worldRotate(0.0f, 0.0f, 45.0f);

// поворот ноды с использованием вектора direction (направление) и вектора, показывающего вверх
node->setWorldDirection(vec3(0.5f, 0.5f, 0.0f), vec3_up, AXIS_Y);

// установка масштаба ноды в Scale_X, Scale_Y, Scale_Z по соответствующим осям
node->setWorldScale(vec3(Scale_X, Scale_Y, Scale_Z));

// установка новой матрицы трансформации для увеличения масштаба ноды в 2 раза по всем осям,
// поворота на 45 градусов вокруг оси Z и перемещения на 1 единицу по всем осям
Mat4 transform = Mat4(translate(vec3(1.0f, 1.0f, 1.0f)) * rotate(quat(0.0f, 0.0f, 1.0f, 45.0f)) * scale(vec3(2.0f)));

// установка матрицы трансформации ноды относительно ее родителя
node->setTransform(transform);

// установка матрицы трансформации ноды относительно глобального начала координат
node->setWorldTransform(transform);

Practice
Практика#

Let's add a fan to our scene and try to breathe life into it:Давайте добавим в сцену вентилятор и попробуем вдохнуть в него жизнь:

  1. Open the archviz/interior/fan folder in the Asset Browser, drag the fan asset fan.fbx to the scene and place it on the table near the bed.Откройте папку archviz/interior/fan в Asset Browser, перетащите ассет вентилятора fan.fbx на сцену и установите его на прикроватном столике.
  2. Open the archviz/interior/fan/materials folder and drag the fan_body_mat_0 material to the fan body, and the fan_propeller_mat_0 material — to the blades.Откройте папку archviz/interior/fan/materials и перетащите материал fan_body_mat_0 на корпус вентилятора, а материал fan_propeller_mat_0 - на лопасти.

  3. Now, let's write a component that will rotate its blades. Create a new component, name it Fan and write the following code:А теперь напишем компонент, который будет вращать его лопасти. Создадим новый компонент, назовем его Fan и напишем следующий код:

    Fan.h
    #pragma once
    #include <UnigineComponentSystem.h>
    class Fan :
    	public Unigine::ComponentBase
    {
    public:
    	// Объявляем конструктор и деструктор для нашего класса, а также задаем имя связанного с компонентом свойства (property). 
    	// Файл Fan.prop со всеми описанными ниже параметрами будет сгенерирован Компонентной системой в папке 'data' вашего проекта при первом запуске приложения
    	COMPONENT_DEFINE(Fan, ComponentBase);
    
    	// объявляем параметры компонента и задаем начальные значения
    	PROP_PARAM(Node, fan_node, nullptr);			// нода пропеллера, которую будем вращать
    	PROP_PARAM(Float, speed, 720.0f);			// скорость вращения
    
    	// регистрация методов, которые будут вызываться на соответствующих этапах жизненного цикла приложения (сами методы объявляются в protected-блоке ниже)
    	COMPONENT_UPDATE(update);
    
    protected:
    	// объявление методов, которые будут вызываться на соответствующих этапах жизненного цикла приложения
    	void update();
    };
    Fan.cpp
    #include "Fan.h"
    #include <UnigineGame.h>
    // Регистрация компонента Fan
    REGISTER_COMPONENT(Fan);
    
    // включаем нужные пространства имен
    using namespace Unigine;
    using namespace Math;
    
    // метод update компонента, вызываемый каждый кадр 
    void Fan::update()
    {
    	// если не назначена нода лопастей, ничего не делаем
    	if (!fan_node)
    		return;
    	// поворачиваем ноду с заданной скоростью
    	fan_node->rotate(0, speed * Game::getIFps(), 0);
    }
  4. Let's save our files and then build and run our application by hitting Ctrl + F5 to make the Component System generate a property to be used to assign our component to nodes. Close the application after running it and switch to UnigineEditor.Сохраним файлы, а затем соберем и запустим приложение нажав Ctrl + F5, чтобы Компонентная система сгенерировала property для связи компонента с нодой. После запуска приложения закроем его и вернемся в UnigineEditor.

    Create NodeDummy, name it fan_rotator, and assign our new generated Fan property to it. Customize the Fan component by dragging the fan_table_propeller node into the Fan Node field and setting the rotation speed of the blades.Создадим ноду NodeDummy, назовем ее fan_rotator, и назначим на нее новое сгенерированное property Fan. Настроим компонент Fan, перетащив ноду fan_table_propeller в поле Fan Node и установив скорость вращения лопастей.

  5. Let's add fan_rotator to the child nodes of fan_table, assign the Toggle component to the fan_table_switch node, and drag the fan_rotator node into the Control Node field.Добавим fan_rotator в дочерние ноды к fan_table, затем на ноду fan_table_switch назначим компонент Toggle и, наконец, перетащим в поле Control Node ноду fan_rotator.
  6. Then we should disable the fan_rotator node, to prevent the code of the component that rotates the fan blades from execution until we turn the switch on.После этого ноду fan_rotator надо отключить, чтобы код компонента, вращающий лопасти, не выполнялся пока мы не включим тумблер.
  7. We're going to rotate the fan_table_propeller node, by default it's Mobility is set to Immovable, so we have to switch it to Dynamic.Мы будем вращать ноду fan_table_propeller, но по умолчанию она статична, параметр Mobility установлен в Immovable, нужно переключить его в Dynamic.

  8. Save the world by hitting Ctrl + S. Switch to SDK Browser and launch our application by clicking the Run button on our project's card to see the result.Сохраним мир, нажав Ctrl + S. Переключимся в SDK Browser и запустим наше приложение, нажав кнопку Run на карточке проекта, чтобы посмотреть результат.

Последнее обновление: 06.11.2024
Build: ()