Project

General

Profile

Download (7.26 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / object / RubikCube.java @ efef689c

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.object;
21

    
22
import android.graphics.Canvas;
23
import android.graphics.Paint;
24

    
25
import org.distorted.library.effect.MatrixEffect;
26
import org.distorted.library.effect.MatrixEffectMove;
27
import org.distorted.library.effect.MatrixEffectRotate;
28
import org.distorted.library.main.DistortedEffects;
29
import org.distorted.library.main.DistortedTexture;
30
import org.distorted.library.mesh.MeshBase;
31
import org.distorted.library.mesh.MeshJoined;
32
import org.distorted.library.mesh.MeshRectangles;
33
import org.distorted.library.type.Static1D;
34
import org.distorted.library.type.Static3D;
35
import org.distorted.library.type.Static4D;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

    
39
class RubikCube extends RubikObject
40
{
41
  // the three rotation axis of a RubikCube
42
  private static final Static3D[] AXIS = new Static3D[]
43
         {
44
           new Static3D(1,0,0),
45
           new Static3D(0,1,0),
46
           new Static3D(0,0,1)
47
         };
48

    
49
  private static final int[] FACE_COLORS = new int[]
50
         {
51
           0xffffff00, 0xffffffff,   // AXIS[0]right (right-YELLOW) AXIS[0]left (left  -WHITE)
52
           0xff0000ff, 0xff00ff00,   // AXIS[1]right (top  -BLUE  ) AXIS[1]left (bottom-GREEN)
53
           0xffff0000, 0xffb5651d    // AXIS[2]right (front-RED   ) AXIS[2]left (back  -BROWN)
54
         };
55

    
56
  // All legal rotation quats of a RubikCube of any size must have all four of their components
57
  // equal to either 0, +-1, +-0.5 or +-sqrt(2)/2.
58
  // Here's how to compute this:
59
  // 1) compute how many rotations there are (RubikCube of any size = 24)
60
  // 2) take the AXIS, angles of rotation (90 in RubikCube's case) compute the basic quaternions
61
  // (i.e. rotations of 1 basic angle along each of the axis) and from there start semi-randomly
62
  // multiplying them and eventually you'll find all (24) legal rotations.
63
  // 3) linear scan through those shows that the only floats in those 24 quats are those 7 given
64
  // below.
65
  private static final float[] LEGALQUATS = new float[]
66
         {
67
           0.0f ,
68
           0.5f ,
69
          -0.5f ,
70
           1.0f ,
71
          -1.0f ,
72
           0.5f*((float)Math.sqrt(2)) ,
73
          -0.5f*((float)Math.sqrt(2))
74
         };
75

    
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

    
78
  RubikCube(int size, Static4D quatCur, Static4D quatAcc, DistortedTexture texture, MeshRectangles mesh, DistortedEffects effects)
79
    {
80
    super(size,quatCur,quatAcc,texture,mesh,effects);
81
    }
82

    
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84

    
85
  int[][] getCubitPositions(int size)
86
    {
87
    int[][] tmp = new int[getNumCubits(size)][3];
88

    
89
    int currentPosition = 0;
90

    
91
    for(int x = 0; x<size; x++)
92
      for(int y = 0; y<size; y++)
93
        for(int z = 0; z<size; z++)
94
          {
95
          if( x==0 || x==size-1 || y==0 || y==size-1 || z==0 || z==size-1 )
96
            {
97
            tmp[currentPosition][0] = x;
98
            tmp[currentPosition][1] = y;
99
            tmp[currentPosition][2] = z;
100

    
101
            currentPosition++;
102
            }
103
          }
104

    
105
    return tmp;
106
    }
107

    
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109
// i.e. size^3 - (size-2)^3 - number of cubits in the outside wall of the Cube (we don't create or
110
// render the inside)
111

    
112
  int getNumCubits(int size)
113
    {
114
    return size>1 ? 6*size*size - 12*size + 8 : 1;
115
    }
116

    
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118

    
119
  float[] getLegalQuats()
120
    {
121
    return LEGALQUATS;
122
    }
123

    
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125

    
126
  int getNumFaces()
127
    {
128
    return FACE_COLORS.length;
129
    }
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
  Static3D[] getRotationAxis()
134
    {
135
    return AXIS;
136
    }
137

    
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139

    
140
  void createFaceTexture(Canvas canvas, Paint paint, int face)
141
    {
142
    final int S = TEXTURE_HEIGHT;
143
    final int R = TEXTURE_HEIGHT/10;
144
    final int M = TEXTURE_HEIGHT/20;
145

    
146
    paint.setColor(FACE_COLORS[face]);
147
    canvas.drawRoundRect( (face*S+M), M, (face*S+M) + (S-2*M), M + (S-2*M), R, R, paint);
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

    
152
  MeshBase createCubitMesh(int vertices)
153
    {
154
    final int MESHES=6;
155

    
156
    Static3D axisY  = new Static3D(0,1,0);
157
    Static3D axisX  = new Static3D(1,0,0);
158
    Static3D center = new Static3D(0,0,0);
159
    Static1D angle  = new Static1D(0);
160

    
161
    MatrixEffect[] effectsY = new MatrixEffect[2];
162
    effectsY[0] = new MatrixEffectMove(new Static3D(0,0,+0.5f));
163
    effectsY[1] = new MatrixEffectRotate( angle, axisY, center );
164

    
165
    MeshBase[] meshes = new MeshRectangles[MESHES];
166
    for(int i=0; i<MESHES; i++) meshes[i] = new MeshRectangles(vertices,vertices);
167

    
168
    angle.set(0);
169
    meshes[4].apply(effectsY);  // front
170
    angle.set(90);
171
    meshes[0].apply(effectsY);  // right
172
    angle.set(180);
173
    meshes[5].apply(effectsY);  // back
174
    angle.set(270);
175
    meshes[1].apply(effectsY);  // left
176

    
177
    MatrixEffect[] effectsX = new MatrixEffect[2];
178
    effectsX[0] = new MatrixEffectMove(new Static3D(0,0,+0.5f));
179
    effectsX[1] = new MatrixEffectRotate( angle, axisX, center );
180

    
181
    angle.set( 90);
182
    meshes[3].apply(effectsX);  // bottom
183
    angle.set(-90);
184
    meshes[2].apply(effectsX);  // top
185

    
186
    return new MeshJoined(meshes);
187
    }
188
}
(2-2/6)