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

Я должен проектировать функциональная рубик куб как часть моей домашней работы. Я не использую 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);

CubIndici11 должен всегда содержать куб, который находится в центре лица 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 — координаты и индексы после вращения объектов. (Матрица не была затронута)
Post Rotatie Matrice — после вращения матрицы, а также. Если вы сравните индексы «pre rotatie» с «post rotatie matrice», вы заметите поворот на 90 градусов.

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

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

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

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

2

Решение

Формула вращения 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]);
}
}

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

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]