Я должен проектировать функциональная рубик куб как часть моей домашней работы. Я не использую 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.
Первый блок координат — это начальная грань куба. (Матрица индекса 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 действительно являются верхним рядом.
Это проблема, которая деформирует куб, и я не знаю, что его вызывает.
Если что-то неясно, пожалуйста, дайте мне знать, и я отредактирую пост или ответ на комментарий
Формула вращения 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]);
}
}
Вы должны быть в состоянии реализовать другие оси оттуда.
Других решений пока нет …