WOWCube Docs logo
WOWCube Docs
Mission Control
Section Shortcuts
APIExamplesSourceWOWConnectChangelog
Filters
SDK and language defaults persist in cookies.
SDK version
Navigation Tree
Collapsed by default, focused on the active path.
Made byMcKay Seamons
GitHub
  1. Home
  2. Docs
  3. Examples
  4. Gfx Engine - Orientation
Mission NodeSDK 6.1C++renderingProject Included

Gfx Engine - Orientation

Gfx Engine Orientation Device orientation refers to the physical orientation of a device in space. It can be detected by built in sensors such as acceleromet...

Examples / SDK 6.1 / C++ / rendering

Gfx Engine - Orientation

Device orientation refers to the physical orientation of a device in space. It can be detected by built-in sensors such as accelerometers and gyroscopes.

In programming, device orientation is an important consideration when developing cubeapps. It allows developers to create visuals that adjust to the device's orientation, providing a better user experience.

But what specific changes can the user interface undergo depending on the orientation of the device, especially if that device is a WOWCube?

First of all, we should remember that, unlike all other devices, the WOWCube is a compound device of 8 separate modules, each of which has 3 independent screens. And also that each face of the WOWCube consists of four independent screens belonging to different modules.

Essentially, this means that, by default, the screens of modules are arbitrarily oriented relative to each other, which in turn leads us to the conclusion:

if you just take a sprite and display it on all screens in the same screen coordinate, the final picture will be a set of unaligned sprites rotated differently relative to each other

This means that in order to align the sprites within one side of the WOWCube, some of them need to be rotated by a certain angle. The question of how exactly to calculate this angle is discussed in more detail in the Topology-Device Orientation example. And only when the sprites are correctly rotated relative to each other within the same face, you can start drawing the faces themselves, depending on the orientation of the device in space.

After all, what is orientation?

Orientation is when you know which of the faces is on top and which is on the bottom. Or, in other words, when it is known where the gravity vector is directed.

gravity

GFX Engine supports three orientation control modes:

Gfx Engine - Orientation
CPP
1 TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_MENU
2 TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_GRAVITY
3 TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_SPLASH
4
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Each of these modes, as the name implies, is used by the CubiOS operating system either when rendering specific user interface components, or in general for games and applications that require control of the device's orientation.

In addition, the engine allows you to specify the mode of automatic rotation of graphic objects for alignment, depending on the orientation control mode.

Let's consider the features of each mode separately:

ORIENTATION_MODE_MENU

As the name implies, this mode is used when rendering the cube system menu, as well as for applications that do not require orientation control. In this mode, the control and comparison of the position of the faces with the gravity vector is not performed, and the drawing of the faces does not depend on the position of the cube in space.

ORIENTATION_MODE_GRAVITY

In this mode, the direction of the gravity vector relative to the faces of the cube will be continuously checked and the topology will be rebuilt depending on its direction. In other words, the cube will always "know" what face it has, for example, at the top and how to draw objects on that face.

ORIENTATION_MODE_SPLASH

This mode is a kind of combination of the two previous modes, mainly used for displaying splash screens.

The example

The main purpose of this example is to demonstrate how the relative position of sprites on faces changes depending on the orientation control mode and automatic rotation of objects.

So let's get started...

As always, the application starts by initializing resources in the InitializeResources() function:

Gfx Engine - Orientation
CPP
1void GfxOrientation::InitializeResources()
2{
3 this->modes.push_back({TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_MENU,false,"MENU"});
4 this->modes.push_back({TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_MENU,true,"MENU"});
5 this->modes.push_back({TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_GRAVITY,false,"GRAVITY"});
6 this->modes.push_back({TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_GRAVITY,true,"GRAVITY"});
7 this->modes.push_back({TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_SPLASH,false,"SPLASH"});
8 this->modes.push_back({TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_SPLASH,true,"SPLASH"});
9
10 //Create a Cubios::Gfx::Background object
11 this->Scene.CreateObjectWithID(GfxObjects::myBackground,new Background(0,0,0));
12
13 //Create animated sprite
14 this->Scene.CreateObjectWithID(GfxObjects::mySprite,new AnimatedSprite("torch","png",1,8,Transform(120,120,0)));
15 this->torch = dynamic_cast<AnimatedSprite*>(this->Scene[GfxObjects::mySprite]);
16 this->torch->SetPlaybackSpeed(100);
17 this->torch->SetPlaybackMode(AnimatedSprite::playbackMode_t::Loop);
18
19 //Create a Cubios::Gfx::Text objects
20
21 this->Scene.CreateObjectWithID(GfxObjects::myText1,new Text("TAP",120,20,9,Colors::gold));
22 this->Scene.CreateObjectWithID(GfxObjects::myText2,new Text("TO CHANGE",120,50,9,Colors::gold));
23 this->Scene.CreateObjectWithID(GfxObjects::myText3,new Text("ORIENTATION",120,80,9,Colors::gold));
24 this->Scene.CreateObjectWithID(GfxObjects::myText4,new Text("MODE",120,110,9,Colors::gold));
25
26 this->Scene.CreateObjectWithID(GfxObjects::myText5,new Text("-MODE-",120,160,6,Colors::tomato));
27 this->Scene.CreateObjectWithID(GfxObjects::myText6,new Text("GRAVITY",120,200,6,Colors::silver));
28
29 this->SetTimer(1,250);
30}
31
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Here we fill in the modes array with orientation control values we want to demonstrate, create some objects for visuals and texts and a timer for animated sprite.

We want to make sure that when tapping on one module, the orientation control mode changes on all modules. For this we use the networк:

Gfx Engine - Orientation
CPP
1void GfxOrientation::on_Tap(uint32_t count)
2{
3 if(this->Module==0)
4 {
5 if(this->currentMode<5)
6 {
7 this->currentMode++;
8 }
9 else
10 {
11 this->currentMode = 0;
12 }
13
14 NetworkMessage msg;
15 msg.WriteInt(this->currentMode,4); //4 bits is enough
16
17 //send new mode to all modules
18 this->SendNetworkMessage(1,&msg);
19 }
20}
21
22void GfxOrientation::on_Message(uint32_t type, uint8_t* pkt, u32_t size)
23{
24 NetworkMessage nm(pkt,size);
25
26 if(this->Module!=0)
27 {
28 //Read incoming mode
29 this->currentMode = nm.ReadInt(4);
30 }
31
32}
33
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

As you can see from the source code above, when module 0 registers a tap, the application increments the index of the current orientation control mode and broadcasts it to neighboring modules. Neighboring modules, in turn, get this index and write it to a local variable.

Simple.

So, we have an array with all the orientation control modes and the current index. The only thing left is to apply the mode at this index and demonstrate the result visually.

Let's take a look at the on_Render() function:

Gfx Engine - Orientation
CPP
1void GfxOrientation::on_Render(std::array<Cubios::Screen, 3>& screens)
2{
3 for(auto it = screens.begin(); it != screens.end(); ++it)
4 {
5 //typically, you don't set orientation directly. But for this sample we have to do it.
6 it->SetOrientation(this->modes.at(this->currentMode).mode);
7
8 //Start adding objects to a screen
9 it->Begin(this->modes.at(this->currentMode).mode,this->modes.at(this->currentMode).autorotation);
10
11 //Add animated sprite on the sides of a cube
12 if(it->Direction()!=TOPOLOGY_orientation_t::ORIENTATION_UP && it->Direction()!=TOPOLOGY_orientation_t::ORIENTATION_DOWN)
13 {
14 if(this->Module==0)
15 {
16 it->Add(this->Scene[GfxObjects::myBackground]);
17
18 it->Add(this->Scene[GfxObjects::myText1]);
19 it->Add(this->Scene[GfxObjects::myText2]);
20 it->Add(this->Scene[GfxObjects::myText3]);
21 it->Add(this->Scene[GfxObjects::myText4]);
22
23 if(this->modes.at(this->currentMode).autorotation)
24 dynamic_cast<Text*>(it->Add(this->Scene[GfxObjects::myText5]))->SetContent("AUTOROTATION:ON")
25 ->SetColor(Colors::lime);
26 else
27 dynamic_cast<Text*>(it->Add(this->Scene[GfxObjects::myText5]))->SetContent("AUTOROTATION:OFF")
28 ->SetColor(Colors::tomato);
29
30 dynamic_cast<Text*>(it->Add(this->Scene[GfxObjects::myText6]))->FormatContent("MODE:%s", this->modes.at(this->currentMode).name.c_str());
31 }
32 else
33 {
34 it->Add(this->torch);
35 }
36 }
37 else
38 {
39 //Add background
40 it->Add(this->Scene[GfxObjects::myBackground]);
41 }
42
43 //Finish adding objects
44 it->End();
45 }
46}
47
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

As you can see, there are two places where the orientation control mode setting appears.

First, the mode for each screen is set:

Gfx Engine - Orientation
CPP
1it->SetOrientation(this->modes.at(this->currentMode).mode);
2
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

As a rule, dynamic orientation mode is rarely used in real applications, so calling this function in on_Render() is the exception rather than the rule. However, for this example, it is required.

Next comes the Begin()-End() block.

In GFX Engine, all objects displayed on the screen are added exclusively inside this block. In fact, the main purpose of the Begin() function is to inform the engine that the addition of objects to the screen has begun, and the End() function - that the addition is completed and the engine is ready to draw. But drawing, as we know, depends on the device orientation control mode and automatic rotation, so the Begin() function takes these two parameters as input.

Gfx Engine - Orientation
CPP
1//Start adding objects to a screen
2it->Begin(this->modes.at(this->currentMode).mode,this->modes.at(this->currentMode).autorotation);
3...
4//Finish adding objects
5it->End();
6
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Following further on the code, everything is very simple. We ask the current screen which face it currently belongs to using the Direction() function. If the face is lateral, we display text and sprites on the screen. If not, just fill in the background color.

Context Rail

Project files

GfxOrientation.cpp
project/src/GfxOrientation.cpp
GfxOrientation.h
project/src/GfxOrientation.h
wowcubeapp-build.json
project/wowcubeapp-build.json
Jump Grid

On This Page

Gfx Engine OrientationThe example
Context Rail

Related nodes

info.json
Examples / SDK 6.1 / C++ / rendering / Gfx Engine - Orientation
GfxOrientation.cpp
Examples / SDK 6.1 / C++ / rendering / Gfx Engine - Orientation / project / src
GfxOrientation.h
Examples / SDK 6.1 / C++ / rendering / Gfx Engine - Orientation / project / src
wowcubeapp-build.json
Examples / SDK 6.1 / C++ / rendering / Gfx Engine - Orientation / project
Previous Node
wowcubeapp-build.json
Examples / SDK 6.1 / C++ / rendering / GFX Engine - Text / project
Next Node
info.json
Examples / SDK 6.1 / C++ / rendering / Gfx Engine - Orientation