2

I have to design functional rubik cube as part of my homework. I am not using openGL directly, but a framework that was provided. ( All functions that do not belong to openGL and do not have their body listed here will be presumed correct)

Functionalities: all faces need to be rotated if selected by pressing a key. The whole cube must rotate.

The rotation of the whole cube is correct and does not make the subject of this question.

In order to do this, I created the rubik cube from 27 smaller cubes(cube size is 3) and, at the same time, a tridimensional array. A replica of the cube that contains small cubes indexes. In order to better understand this :

if initially one face was:

0 1 2
3 4 5
6 7 8 

after a rotation it should be:

6 3 0
7 4 1
8 5 2

I can rotate the cubes relative to axis X or Y an indefinite number of times and it works perfectly. However, if I combine the rotations( alternate X rotations with Y rotations in a random way) there appear cases when the cube deforms. As this happens inconsistently, it is difficult for me to find the cause.

This is how I am creating the cube :

int count = 0;

for (int i = -1; i < 2; i++)
    for(int j = -1; j < 2; j++)
        for(int k = -1; k < 2; k++)  {
            RubikCube.push_back(drawCube());
            RubikCube.at(count)->translate(4*i,4*j,4*k);
            CubIndici[j+1][k+1][i+1] = count;

            count++;
        }

The function drawCube() effectively draws a cube of size 4 with the center positioned in origin. CubIndici is the 3D array that I use to store the positions of the cube.

This is the function that I am using to rotate a matrix in the 3D array. (I have double checked it so it should be correct, but perhaps I am missing something).

void rotateMatrix(int face_index, int axis) {
    if (axis == 0 ) 
    {
            for ( int i = 0; i < 3; i++)
                for( int j = i; j < 3; j++) 
                 {
                      swap(&CubIndici[i][j][face_index],&CubIndici[j][i][face_index]);
                 }
            for (int i = 0; i < 3; i++)
                for(int  j = i; j < 3; j++) 
                 {
                     swap(&CubIndici[i][j][face_index],&CubIndici[2-i][j][face_index]);
                 }
    }

        if (axis == 1 ) 
    {
            for ( int i = 0; i < 3; i++)
                for( int j = i; j < 3; j++) 
                 {
                      swap(&CubIndici[face_index][i][j],&CubIndici[face_index][j][i]);
                 }
            for (int i = 0; i < 3; i++)
                for(int  j = i; j < 3; j++) 
                 {
                     swap(&CubIndici[face_index][i][j],&CubIndici[face_index][2-i][j]);
                 }
    }
}

The CubIndici 3d array is global, so I need the axis parameter to determine what kind of rotation to performe( relative to X, Y or Z)

on pressing w key I should rotate a( hardcoded, for now) face around axis X

for (int i = 0; i < 3; i++)
                for(int j = 0; j < 3; j++)
                    RubikCube.at(CubIndici[i][j][1])->rotateXRelativeToPoint(
                                          RubikCube.at(CubIndici[1][1][1])->axiscenter, 1.57079633);
            rotateMatrix(1,0);

CubIndici11 should always contain the cube that is in the center of the face CubIndici[*][*]1.

Similarly,

        for (int i = 0; i < 3; i++)
            for(int j = 0; j < 3; j++)
                RubikCube.at(CubIndici[2][i][j])->rotateYRelativeToPoint(
                                          RubikCube.at(CubIndici[2][1][1])->axiscenter, 1.57079633);
        rotateMatrix(2,1);

for rotating on axis Y.

1.57079633 is the radian equivalent of 90 degrees

For a better understanding I add the detailed display of rotating the left face on X axis and the top down one on Y axis.

img

The first block of coordinates is the initial cube face. ( The CubIndici index matrix is unmodified)

pre rotatie - coordinates and indexes for each of the cubes of the face. post rotatie - coordiantes and indexes after rotating the objects. ( The matrix was not touched ) post rotatie matrice - after rotating the matrix aswell. If you compare the indexes of "pre rotatie" with "post rotatie matrice" you will notice 90 degrees turn.

This is the first rotation ( rotate the left face around X) and it is entirely correct.

On the next rotation however, the cubes that should be contained in the top down face ( as well as in the left one) should be 2,5,8. However, they appear as 2,5,6. If you look at the first "post rotatie matrice" 2,5,8 are indeed the top row.

This is the issue that deforms the cube and I don't know what causes it.

If anything is unclear please let me know and I will edit the post or reply to the comment!

Spektre
  • 49,595
  • 11
  • 110
  • 380
pAndrei
  • 383
  • 6
  • 19
  • you should make a `#define` for your radiant constant (actually, I think there's a bunch of PI related constants in ``). – didierc Nov 09 '12 at 23:04
  • you should also try to reduce redundant code as much as possible (compilers will take care of inlining optimizations for you, if that's what you're concerned about). – didierc Nov 09 '12 at 23:06
  • there's a [swap](http://www.cplusplus.com/reference/algorithm/swap/) template you could use to make the code lighter, clearer, and less error prone. – didierc Nov 09 '12 at 23:10
  • you only have 2 rotations axes? – didierc Nov 09 '12 at 23:11
  • The reason I am not making a define is that I only keep the radiant constant until the whole code works, the rotation will be perfromed smoothly. I have implemented the swap function and now the rotateMatrix is lighter. Yes, for the moment I only have rotations on two axes. – pAndrei Nov 10 '12 at 09:20
  • old but still unanswered ... I do rubik cube like this: [Quaternion rotation do not works as excepted](http://stackoverflow.com/a/39024016/2521214) and handle the rotation problems by checking matrix axises against predefined constant vectors and map the rotations to correct axises accordingly. – Spektre Sep 26 '16 at 10:22

1 Answers1

1

The formula of a PI/2 rotation clockwise for a cell at position <x;y> in a slice of the cube is:

  x' = 2 - y
  y' = x

similarily, for a counter clockwise rotation:

  x' = y
  y' = 2 - x

but these are rotations, and you want to do in-place modification of your arrays. We can replace a rotation by a combination of 2 mirror symmetries.

clockwise:

  <x;y>  ->  <y;x> 
  <x;y>  ->  <2-x;y>

and counter clockwise is the opposite composition of these functions.

Given these formulas, you can write your rotation function like this:

 void rotateMatrix_X_CW(int face_index) {
     int i,j;  
     for ( i = 0; i < 2; i++)
         for( j = i; j < 3; j++) 
         {
             swap(CubIndici[i][j][face_index],CubIndici[2-i][j][face_index]);
         }
     for ( i = 0; i < 2; i++)
         for( j = i; j < 3; j++) 
         {
             swap(CubIndici[i][j][face_index],CubIndici[j][i][face_index]);
         }
 }

 void rotateMatrix_X_CCW(int face_index) {
     int i,j;  
     for ( i = 0; i < 2; i++)
         for( j = i; j < 3; j++) 
         {
             swap(CubIndici[i][j][face_index],CubIndici[j][i][face_index]);
         }
     for ( i = 0; i < 2; i++)
         for( j = i; j < 3; j++) 
         {
             swap(CubIndici[i][j][face_index],CubIndici[2-i][j][face_index]);
         }
 }

You should be able to implement the other axes from there.

didierc
  • 14,572
  • 3
  • 32
  • 52
  • 1
    I have implemented this and it does not solve my issue. In order to better understand what the issue is: if I try to rotate the max right face and the top down one the cube diforms. In other words, the issue occurs when I try to rotate two faces that have 3 cubes in common and they are placed in the form of an L. – pAndrei Nov 10 '12 at 09:23
  • Your rotation isn't correct. Have you tried it? I kept looking for errors until I got to this function, from what I see now in a 3x3 matrix, the 0,2 and the 2,0 are wrongly switched. – pAndrei Nov 11 '12 at 02:32
  • I verified the function, the loop ranges were wrong, and so certain cells of the matrix got swapped twice. It should work now. I think I had the clockwise and counter-cw reversed, so I put both. – didierc Nov 11 '12 at 14:30