Moving and Rotating an Object
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.
The following code shows how basic node transformations are performed:
// injecting Unigine namespace to the global namespace
using namespace Unigine;
using namespace Unigine::Math;
// move the node by X, Y, Z units along the corresponding axes
node->setWorldPosition(node->getWorldPosition() + Vec3(X, Y, Z));
// move the node by one unit along the Y axis
node->worldTranslate(0.0f, 1.0f, 0.0f);
// rotate the node around the axis (X, Y, Z) by the Alpha angle
node->setWorldRotation(node->getWorldRotation() * quat(Vec3(X, Y, Z), Alpha));
// rotate the node around X, Y, and Z axes by the corresponding angle (angle_X, angle_Y, angle_Z)
node->setWorldRotation(node->getWorldRotation() * quat(angle_X, angle_Y, angle_Z));
// rotate the node by 45 degrees along the Z axis
node->worldRotate(0.0f, 0.0f, 45.0f);
// orient the node using a direction vector and a vector pointing upwards
node->setWorldDirection(vec3(0.5f, 0.5f, 0.0f), vec3_up, AXIS_Y);
// setting node scale to Scale_X, Scale_Y, Scale_Z along the corresponding axes
node->setWorldScale(vec3(Scale_X, Scale_Y, Scale_Z));
// setting new transformation matrix to scale the node 2 times along all axes, rotate it by 45 degrees around the Z-axis and move it by 1 unit along all axes
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)));
// setting node transformation matrix relative to its parent
node->setTransform(transform);
// setting node transformation matrix relative to the world origin
node->setWorldTransform(transform);
Practice#
Let's add a fan to our scene and try to breathe life into it:
- 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.
-
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.
-
Now, let's write a component that will rotate its blades. Create a new component, name it Fan and write the following code:
#pragma once #include <UnigineComponentSystem.h> class Fan : public Unigine::ComponentBase { public: // declare constructor and destructor for our class and define the name of the property to be associated with the component. // The Fan.prop file containing all parameters listed below will be generated in your project's data folder after running the app for the first time COMPONENT_DEFINE(Fan, ComponentBase); // declaration and initialization of component parameters PROP_PARAM(Node, fan_node, nullptr); // fan blades node to be rotated PROP_PARAM(Float, speed, 720.0f); // rotation speed // registering methods to be called at the corresponding stages of the world logic (methods are declared in the protected-section below) COMPONENT_UPDATE(update); protected: // declaration of methods to be called at the corresponding stages of the world logic void update(); };
#include "Fan.h" // registering the Fan component REGISTER_COMPONENT(Fan); // injecting necessary namespaces using namespace Unigine; using namespace Math; // component's update method to be called each frame void Fan::update() { // if the fan blades node is not assigned, nothing happens if (!fan_node) return; // rotate the node with the specified speed fan_node->rotate(0, speed, 0); }
-
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.
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.
- 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.
- 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.
-
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.
-
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.