简体   繁体   中英

Issues with rotating rubik cube faces using opengl in C++

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);

CubIndici 1 1 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!

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM