Проблемы с вращением граней кубика Рубика с использованием opengl в C++

Я должен разработать функциональный кубик Рубика как часть моей домашней работы. Я не использую OpenGL напрямую, но фреймворк, который был предоставлен. (Все функции, которые не принадлежат openGL и не имеют тела, перечисленного здесь, будут считаться правильными)

Функциональные возможности: все грани необходимо поворачивать, если они выбраны нажатием клавиши. Весь куб должен вращаться.

Вращение всего куба правильное и не составляет предмета этого вопроса.

Чтобы сделать это, я создал кубик Рубика из 27 кубиков меньшего размера (размер куба равен 3) и, в то же время, трехмерный массив. Реплика куба, содержащая индексы маленьких кубиков. Чтобы лучше понять это:

если изначально одно лицо было:

0 1 2
3 4 5
6 7 8 

после поворота должно быть:

6 3 0
7 4 1
8 5 2

Я могу вращать кубы относительно оси X или Y неограниченное количество раз, и это работает отлично. Однако, если я комбинирую вращения (чередование вращений X с вращениями Y случайным образом), возникают случаи, когда куб деформируется. Поскольку это происходит непоследовательно, мне трудно найти причину.

Вот как я создаю куб:

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++;
        }

Функция drawCube() эффективно рисует куб размером 4 с центром, расположенным в начале координат. CubIndici - это трехмерный массив, который я использую для хранения позиций куба.

Это функция, которую я использую для поворота матрицы в 3D-массиве. (Я дважды проверил его, поэтому он должен быть правильным, но, возможно, я что-то упустил).

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

3D-массив CubIndici является глобальным, поэтому мне нужен параметр оси, чтобы определить, какой тип поворота выполнять (относительно X, Y или Z).

при нажатии клавиши w я должен повернуть (пока жестко) лицо вокруг оси 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 всегда должен содержать куб, который находится в центре лица CubIndici [*] [*] 1.

Так же,

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

для вращения по оси Y.

1.57079633 - радиальный эквивалент 90 градусов

Для лучшего понимания я добавлю подробное отображение поворота левой грани по оси X и верхней вниз по оси Y.

IMG

Первый блок координат - это начальная грань куба. (Матрица индекса CubIndici не изменена)

pre rotatie - координаты и индексы для каждого из кубов лица. post rotatie - координаты и индексы после вращения объектов. (Матрица не была затронута) после поворота матрицы - после вращения матрицы также. Если вы сравните индексы "pre rotatie" с "post rotatie matrice", вы заметите поворот на 90 градусов.

Это первое вращение (поверните левую грань вокруг X), и оно совершенно правильно.

Однако при следующем повороте кубы, которые должны содержаться в верхней нижней части (а также в левой), должны составлять 2,5,8. Тем не менее, они появляются как 2,5,6. Если вы посмотрите на первый "post rotatie matrice", то 2,5,8 действительно являются верхним рядом.

Это проблема, которая деформирует куб, и я не знаю, что его вызывает.

Если что-то неясно, пожалуйста, дайте мне знать, и я отредактирую пост или отвечу на комментарий!

1 ответ

Формула вращения PI/2 по часовой стрелке для ячейки в положении <x;y> в кусочке куба есть:

  x' = 2 - y
  y' = x

аналогично для вращения против часовой стрелки:

  x' = y
  y' = 2 - x

но это ротации, и вы хотите сделать модификацию ваших массивов на месте. Мы можем заменить вращение комбинацией двух зеркальных симметрий.

по часовой стрелке:

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

и против часовой стрелки - противоположный состав этих функций.

Учитывая эти формулы, вы можете написать свою функцию вращения следующим образом:

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

Вы должны быть в состоянии реализовать другие оси оттуда.

Другие вопросы по тегам