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. Device Orientation
Mission NodeSDK 6.2PawntopologyProject Included

Device Orientation

The terminology used in this article is most likely a subject to change Locations Unlike any other gaming console, the layout of WOWCube screens does not hav...

Examples / SDK 6.2 / Pawn / topology

The terminology used in this article is most likely a subject to change

Locations

Unlike any other gaming console, the layout of WOWCube screens does not have specific sides in the sense of device orientation in space. There is no particular face of a cube that always faces up, nor the faces that always face the other direction that is constant.

That what defines which face is top and which face is bottom is the way you hold the cube. Take the cube differently and the face that once was top will occur at the back, while the face that was facing at you becomes the top one.

CubiOS operating system keeps an eye on changes of device orientation in space. It knows which face is currenly facing up and provides an API for retrieving of this information.

In terms of WOWCube topology API, space orientation of a face of device is called an ORIENTATION as an orientation of a particular face relative to the center of WOWCube device, a pivot point all modules twist around.

Orientation of a face may be one of the following vaules:

Device Orientation
PAWN
1const TOPOLOGY_orientation:
2{
3 ORIENTATION_UP = 0,
4 ORIENTATION_DOWN,
5 ORIENTATION_FRONT,
6 ORIENTATION_BACK,
7 ORIENTATION_LEFT,
8 ORIENTATION_RIGHT,
9 ORIENTATION_MAX,
10};
11
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

locations

It is important to remember that we can only talk about unambiguous detection of top and bottom faces at particular moment of time. While the top and the bottom is always known because it is defined by the gravity of our planet, side faces of the WOWCube are the matter of perspecive, literarly. Of course, CubiOS always assigns location values to the side faces, but will the face that has ORIENTATION_FRONT value be actually facing at you depends on how you hold the cube.

Faces, facelets and places

As we know, each face of a WOWCube contains four screens; each screen belongs to a module with a unique index that never changes.

Also, due to the way WOWCube modules are structurally connected, the alignment of each screen is different - they are rotated relatively to each other by 90, 180 and 270 degrees.

So in order to be able to render text and images on a signle face with multiple screens in controlled way, special "coordinate system" is needed; we got to be able to know

  • does a given module have a screen that belongs to the face?
  • where that screen is relatively to other screens of the same face?
  • should we rotate a visual before presenting it in order to align it with neighbouring screens?

To answer these questions, the WOWCube topology API provides two parameters associated with each screen. They are called a facelet and a place.

A FACELET is a static address of the screen. It is a pair of module ID (from 0 to 7) the screen index (from 0 to 2). Module ID determined during the cube startup and based on the module hardware ID and how big it is comparing with other modules in a system. Screen number corresponds to the order number of the display on a bus. Therefore, a facelet represents physical "coordinates" of the particular screen and guaranteed to be immutable.

facelets

A PLACE is a dynamic address of the screen. It is a pair of face index and the screen position on that face. Faces always have the same relationship one to each other. Basically their numbers always correspond to the screen numbers of a master module (module with ID 0) and its diagonal counterpart. Positions on the face are always enumerated in the same order. Positions order based on the orientation mode (see documentation)

places

So having an ID of current module and knowing which face we want to render the visual on we can do the following:

  • Find facelets for each screen of the module and check whether they belong to a face we want
  • For the screen that belongs to required face, find its place to know where exactly on the face this screen is located

But let's not forget there is another quite important step that must be done before we have everything needed to render a visual properly.

As mentioned above, WOWCube modules are connected the way so their screens are rotated relatively to each other. So in order to render an image on the whole face, it is not enough to cut it in four pieces and put them on the right screens, but it is also essential to know the rotation angles of each image.

Look at the picture below. This is what would you see if you just render the same image on all four screens that belong to the face:

no_rotation

Clearly, event if everything else is right, if each image is put at its own correct place at the face, the result is still wrong. And that, as it was pointed out earlier, is due to the way WOWCube modules are connected all together.

So the rotation must be applied to at least three images of four and here is what it should look in result:

with_rotation

The WOWCube topology API has a function that allows to determine required screen content rotation angle for a givem facelet:

Device Orientation
PAWN
1TOPOLOGY_getAngle(facelet[TOPOLOGY_FACELET], TOPOLOGY_orientation: orientation = ORIENTATION_MENU);
2
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

First parameter of this function is a facelet rotation angle of which must be returned.

Second parameter is the orientation mode. The CubiOS operating system support several modes of enumeration of module screens used for different purposes - for menues and games, for screen savers and visual effects, for internal needs. In most cases it would be ok just to use a default value of ORIENTATION_MENU. However, it is advised that you take a quick look through the API reference documentation for more details on this topic.

The example

Ok, although we have not quite finished with the theoretical part yet, enough with it for now. Let's get our hands on some programming!

To show how to deal with faces, places and facelets and rotations, let's create a cubeapp that simply draws an image on the face of a cube that currently faces up.

As usual, we will start from loading of images. We want one big image be rendered on a top-facing side of a cube, so we would have to take a big image and cut it into four pieces that will be rendered on four screens that belong to one face.

Device Orientation
PAWN
1public ON_Init(id, size, const pkt[])
2{
3 ...
4
5 Images.first = GFX_getAssetId("0.png");
6 Images.second = GFX_getAssetId("1.png");
7 Images.third = GFX_getAssetId("2.png");
8 Images.fourth = GFX_getAssetId("3.png");
9
10 ...
11}
12
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Once the images are loaded, the only thing that is left to do is to render them on the proper screen if the screen belongs to a top face of a cube.

To do that, we will follow very simple steps taken on each call of ON_Render callback:

  • Detect which face of the cube faces UP at the moment
  • Iterate through module screens
  • See if the screen belongs to one of four facelets of the top face
  • If it does, see the index of a facelet and render correspondent image at proper angle.

Pay attention:

For the purpose of better demonstration, the hardcoded angle values are used in the following example instead of TOPOLOGY_getAngle function call.

Feel free to play with these values and/or swap them with a function call to get a better understanding of how thngs work here.

Device Orientation
PAWN
1public ON_Render()
2{
3 new place[TOPOLOGY_PLACE];
4 new facelet[TOPOLOGY_FACELET_INFO];
5 new face = TOPOLOGY_getFace(ORIENTATION_UP);
6
7 for(new screenNumber = 0; screenNumber<3; screenNumber++)
8 {
9 GFX_updateDisplay(screenNumber);
10 GFX_clear(Colors.black);
11
12 for (new screenPositionIndex = 0; screenPositionIndex < TOPOLOGY_POSITIONS_MAX; screenPositionIndex++)
13 {
14 place.face = face;
15 place.position = screenPositionIndex;
16
17 facelet = TOPOLOGY_getFacelet(place);
18
19 if(SELF_ID == facelet.module && screenNumber == facelet.screen)
20 {
21 switch(screenPositionIndex)
22 {
23 case 0: GFX_drawImage([120,120], 0xFF, 0, 180, MIRROR_BLANK, Images.first);
24 case 1: GFX_drawImage([120,120], 0xFF, 0, 90, MIRROR_BLANK, Images.second);
25 case 2: GFX_drawImage([120,120], 0xFF, 0, 0, MIRROR_BLANK, Images.third);
26 case 3: GFX_drawImage([120,120], 0xFF, 0, 270, MIRROR_BLANK, Images.fourth);
27
28 }
29 }
30 }
31
32 GFX_render();
33 }
34}
35
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.
Context Rail

Project files

main.pwn
project/src/main.pwn
wowcubeapp-build.json
project/wowcubeapp-build.json
Jump Grid

On This Page

LocationsFaces, facelets and placesThe example
Context Rail

Related nodes

info.json
Examples / SDK 6.2 / Pawn / topology / Device Orientation
main.pwn
Examples / SDK 6.2 / Pawn / topology / Device Orientation / project / src
wowcubeapp-build.json
Examples / SDK 6.2 / Pawn / topology / Device Orientation / project
Handling Twists
Examples / SDK 6.2 / Pawn / topology
Previous Node
wowcubeapp-build.json
Examples / SDK 6.2 / Pawn / topology / Handling Twists / project
Next Node
info.json
Examples / SDK 6.2 / Pawn / topology / Device Orientation