/// <summary> /// Update animation and pending changes. /// </summary> public void Update() { bool pending_changes = _pending_queue.Count() > 0; _animation_is_active = _animation_is_active && pending_changes; _current_time = time; if (pending_changes == false) { return; } ChangeOperation op = _pending_queue.Last(); if (_animation_is_active) { double past_animation_time_s = _current_time - _animation_start_time; if (past_animation_time_s < _animation_time_s) { // get change information int axis_i = (int)op.axis; int row_i = (int)op.row; var cube_i = SubCubeIndices(op.axis, op.row); // update the position model matrix of the affected sub cubes foreach (var i in cube_i) { double angle = Radians(90.0) * (op.direction == RubiksGlobal.TDirection.left ? -1.0 : 1.0); angle *= past_animation_time_s / _animation_time_s; _animation[i] = CreateRotate((float)angle, RubiksGlobal.AxisVector(axis_i)); } // Update the final model matrices of the sub cubes UpdateM44Cubes(); return; } _animation_is_active = false; } else if (pending_changes) { _animation_is_active = true; _animation_start_time = time; return; } _pending_queue.RemoveAt(_pending_queue.Count() - 1); Rotate(op); // Update the final model matrices of the sub cubes UpdateM44Cubes(); }
/// <summary> /// Calculate the rotation of a part of the Rubik's cube. /// Compute the new positions of the sub cubes and calculate the model matrices. /// </summary> /// <param name="op">specifies the change operation</param> void Rotate(ChangeOperation op) { int axis_i = (int)op.axis; int row_i = (int)op.row; var cube_i = SubCubeIndices(op.axis, op.row); // update the position model matrix of the affected sub cubes Matrix4 rot_mat = _c_rot_mat[axis_i * 2 + (op.direction == RubiksGlobal.TDirection.left ? 0 : 1)]; foreach (var i in cube_i) { double angle = Radians(90.0) * (op.direction == RubiksGlobal.TDirection.left ? -1.0 : 1.0); rot_mat = CreateRotate((float)angle, RubiksGlobal.AxisVector(axis_i)); _current_pos[i] = _current_pos[i] * rot_mat; // OpenTK `*`-operator is reversed } // Recalculate the index map of the cubes int[,] indices = { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 2, 1 }, { 2, 2 }, { 1, 2 }, { 0, 2 }, { 0, 1 } }; int[] current_map = (int[])_cube_map.Clone(); for (int i_o = 0; i_o < 8; ++i_o) { int j_n = (op.direction == RubiksGlobal.TDirection.left ? i_o + 6 : i_o + 2) % 8; int[] ao = { 0, 0, 0 }; int[] an = { 0, 0, 0 }; ao[axis_i] = row_i; an[axis_i] = row_i; ao[(axis_i + 1) % 3] = indices[i_o, 0]; an[(axis_i + 1) % 3] = indices[j_n, 0]; ao[(axis_i + 2) % 3] = indices[i_o, 1]; an[(axis_i + 2) % 3] = indices[j_n, 1]; int ci_o = ao[0] + ao[1] * 3 + ao[2] * 9; int ci_n = an[0] + an[1] * 3 + an[2] * 9; _cube_map[ci_n] = current_map[ci_o]; } // reset animation matrices for (int i = 0; i < RubiksGlobal.NoOfCubes; ++i) { _animation[i] = Matrix4.Identity; } }