Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistySquare2.java @ c7c83fb7

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 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.objects;
21

    
22
import android.content.res.Resources;
23
import android.graphics.Canvas;
24
import android.graphics.Paint;
25

    
26
import org.distorted.helpers.FactoryCubit;
27
import org.distorted.helpers.FactorySticker;
28
import org.distorted.library.effect.MatrixEffectQuaternion;
29
import org.distorted.library.main.DistortedEffects;
30
import org.distorted.library.main.DistortedTexture;
31
import org.distorted.library.mesh.MeshBase;
32
import org.distorted.library.mesh.MeshSquare;
33
import org.distorted.library.type.Static3D;
34
import org.distorted.library.type.Static4D;
35
import org.distorted.main.R;
36

    
37
import java.util.Random;
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

    
41
class TwistySquare2 extends TwistySquare
42
{
43
  private static final float Y = 0.75f + X/2;
44
  private static final float Z = 0.75f - X/2;
45

    
46
  private static final int[] QUAT_NUMBER = new int[]
47
    {
48
      0, 6,
49
      0, 9, 6, 3, 18, 15, 12, 21,
50
      0, 9, 6, 3, 0, 9, 6, 3,
51
      15, 12, 21, 18, 15, 12, 21, 18
52
    };
53

    
54
  // centers of the 2 middles + 8 edges + 8 left corners + 8 right corners
55
  private static final float[][] CENTERS = new float[][]
56
    {
57
      { 1.5f, 0.0f, 0.0f },
58
      {-1.5f, 0.0f, 0.0f },
59

    
60
      { 0.0f, 1.0f, 1.5f },
61
      { 1.5f, 1.0f, 0.0f },
62
      { 0.0f, 1.0f,-1.5f },
63
      {-1.5f, 1.0f, 0.0f },
64
      { 0.0f,-1.0f, 1.5f },
65
      { 1.5f,-1.0f, 0.0f },
66
      { 0.0f,-1.0f,-1.5f },
67
      {-1.5f,-1.0f, 0.0f },
68

    
69
      {    Y, 1.0f, 1.5f },
70
      { 1.5f, 1.0f,   -Y },
71
      {   -Y, 1.0f,-1.5f },
72
      {-1.5f, 1.0f,    Y },
73
      {    Y,-1.0f, 1.5f },
74
      { 1.5f,-1.0f,   -Y },
75
      {   -Y,-1.0f,-1.5f },
76
      {-1.5f,-1.0f,    Y },
77

    
78
      { 1.5f, 1.0f,    Y },
79
      {    Y, 1.0f,-1.5f },
80
      {-1.5f, 1.0f,   -Y },
81
      {   -Y, 1.0f, 1.5f },
82
      { 1.5f,-1.0f,    Y },
83
      {    Y,-1.0f,-1.5f },
84
      {-1.5f,-1.0f,   -Y },
85
      {   -Y,-1.0f, 1.5f },
86
    };
87

    
88
  private static final double[][] VERTICES_CORNER = new double[][]
89
    {
90
      { X-1.5+Z, 0.5,  0.0 },
91
      {       Z, 0.5,  0.0 },
92
      {  -1.5+Z, 0.5, -1.5 },
93
      { X-1.5+Z,-0.5,  0.0 },
94
      {       Z,-0.5,  0.0 },
95
      {  -1.5+Z,-0.5, -1.5 }
96
    };
97

    
98
  private static final int[][] VERT_INDEXES_CORNER = new int[][]
99
    {
100
      {0,1,2},   // counterclockwise!
101
      {5,4,3},
102
      {3,4,1,0},
103
      {4,5,2,1},
104
      {5,3,0,2}
105
    };
106

    
107
  private static final float[][] STICKERS = new float[][]
108
    {
109
      { -0.5f, -0.26289170f, 0.5f, -0.26289170f, 0.5f, 0.26289170f, -0.5f, 0.26289170f }, // middle front
110
      { -0.5f, -0.16666667f, 0.5f, -0.16666667f, 0.5f, 0.16666667f, -0.5f, 0.16666667f }, // middle right
111
      { -0.5f, -0.45534182f, 0.5f, -0.45534182f, 0.5f, 0.45534182f, -0.5f, 0.45534182f }, // middle back
112
      { -0.20096192f, -0.25f, 0.20096192f, -0.25f, 0.0f, 0.5f },                          // edge top
113
      { -0.40192384f, -0.5f, 0.40192384f, -0.5f, 0.40192384f, 0.5f, -0.40192384f, 0.5f }, // edge face
114
      { -0.11602539f, -0.25f, 0.4330127f, -0.25f, -0.3169873f, 0.5f }                     // corner top
115
    };
116

    
117
  private static final int NUM_ST = STICKERS.length;
118

    
119
  private static final int[][] mStickerType = new int[][]
120
    {
121
      {  NUM_ST,NUM_ST,0,     1,     2,NUM_ST },
122
      {       3,NUM_ST,4,NUM_ST,NUM_ST,NUM_ST },
123
      {       5,NUM_ST,2,NUM_ST,NUM_ST,NUM_ST },
124
      {  NUM_ST,     5,2,NUM_ST,NUM_ST,NUM_ST }
125
    };
126

    
127
  // YELLOW 0 WHITE 1 BLUE 2 GREEN 3 RED 4 ORANGE 5
128
  private static final int[][] mStickerColor = new int[][]
129
    {
130
      { 0, 0, 4, 0, 5, 0 }, // 0
131
      { 0, 0, 5, 1, 4, 0 },
132

    
133
      { 2, 0, 4, 0, 0, 0 }, // 2
134
      { 2, 0, 0, 0, 0, 0 },
135
      { 2, 0, 5, 0, 0, 0 },
136
      { 2, 0, 1, 0, 0, 0 },
137
      { 3, 0, 4, 0, 0, 0 },
138
      { 3, 0, 0, 0, 0, 0 },
139
      { 3, 0, 5, 0, 0, 0 },
140
      { 3, 0, 1, 0, 0, 0 },
141

    
142
      { 2, 0, 4, 0, 0, 0 }, // 10
143
      { 2, 0, 0, 0, 0, 0 },
144
      { 2, 0, 5, 0, 0, 0 },
145
      { 2, 0, 1, 0, 0, 0 },
146
      { 0, 3, 4, 0, 0, 0 },
147
      { 0, 3, 0, 0, 0, 0 },
148
      { 0, 3, 5, 0, 0, 0 },
149
      { 0, 3, 1, 0, 0, 0 },
150

    
151
      { 0, 2, 0, 0, 0, 0 }, // 18
152
      { 0, 2, 5, 0, 0, 0 },
153
      { 0, 2, 1, 0, 0, 0 },
154
      { 0, 2, 4, 0, 0, 0 },
155
      { 3, 0, 0, 0, 0, 0 },
156
      { 3, 0, 5, 0, 0, 0 },
157
      { 3, 0, 1, 0, 0, 0 },
158
      { 3, 0, 4, 0, 0, 0 },
159
    };
160

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

    
163
  TwistySquare2(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
164
                DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
165
    {
166
    super(size, quat, texture, mesh, effects, moves, ObjectList.SQU2, res, scrWidth);
167
    }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

    
171
  private Static4D getQuat(int cubit)
172
    {
173
    return QUATS[QUAT_NUMBER[cubit]];
174
    }
175

    
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177

    
178
  MeshBase createCornerCubitMesh()
179
    {
180
    if( mMeshes[3]==null )
181
      {
182
      float[][] bands= new float[][]
183
        {
184
          {0.030f,35,0.9f,1.0f, 5,2,1},
185
          {0.001f,35,0.9f,1.0f, 5,2,1}
186
        };
187
      int[] bandIndexes   = new int[] { 0,0,0,1,1 };
188
      float[][] corners   = new float[][] { {0.05f,0.13f} };
189
      int[] cornerIndexes = new int[] { 0,0,-1,0,0,-1 };
190
      float[][] centers   = new float[][] { { 0.0f, 0.0f,-0.5f} };
191
      int[] centerIndexes = new int[] { 0,0,-1,0,0,-1 };
192

    
193
      FactoryCubit factory = FactoryCubit.getInstance();
194
      factory.createNewFaceTransform(VERTICES_CORNER,VERT_INDEXES_CORNER);
195
      mMeshes[3] = factory.createRoundedSolid(VERTICES_CORNER, VERT_INDEXES_CORNER,
196
                                              bands, bandIndexes,
197
                                              corners, cornerIndexes,
198
                                              centers, centerIndexes,
199
                                              getNumCubitFaces() );
200
      }
201
    return mMeshes[3].copy(true);
202
    }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

    
206
  MeshBase createCubitMesh(int cubit, int numLayers)
207
    {
208
    if( mMeshes==null )
209
      {
210
      FactoryCubit factory = FactoryCubit.getInstance();
211
      factory.clear();
212
      mMeshes = new MeshBase[4];
213
      }
214

    
215
    MeshBase mesh;
216

    
217
         if( cubit< 2 ) mesh = createMiddleCubitMesh();
218
    else if( cubit<10 ) mesh = createEdgeCubitMesh();
219
    else                mesh = createCornerCubitMesh();
220

    
221
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
222
    mesh.apply(quat,0xffffffff,0);
223

    
224
    return mesh;
225
    }
226

    
227
///////////////////////////////////////////////////////////////////////////////////////////////////
228

    
229
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
230
    {
231
    int COLORS = FACE_COLORS.length;
232
    int stickerType = face/COLORS;
233
    float R,S;
234

    
235
    switch(stickerType)
236
      {
237
      case 0:  R = 0.060f; S = 0.05f; break;
238
      case 1:  R = 0.040f; S = 0.04f; break;
239
      case 2:  R = 0.110f; S = 0.09f; break;
240
      case 3:  R = 0.030f; S = 0.05f; break;
241
      case 4:  R = 0.110f; S = 0.08f; break;
242
      case 5:  R = 0.025f; S = 0.06f; break;
243
      default: R = 0.000f; S = 0.00f; break;
244
      }
245

    
246
    FactorySticker factory = FactorySticker.getInstance();
247
    factory.drawRoundedPolygon(canvas, paint, left, top, STICKERS[stickerType], S, FACE_COLORS[face%COLORS], R);
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  float[][] getCubitPositions(int numLayers)
253
    {
254
    return CENTERS;
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  int getNumStickerTypes(int numLayers)
260
    {
261
    return STICKERS.length;
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

    
266
  int getFaceColor(int cubit, int cubitface, int numLayers)
267
    {
268
    int type;
269

    
270
         if( cubit< 2             ) type = 0;
271
    else if( cubit<10             ) type = 1;
272
    else if( cubit>13 && cubit<22 ) type = 3;
273
    else                            type = 2;
274

    
275
    return mStickerType[type][cubitface]*FACE_COLORS.length + mStickerColor[cubit][cubitface];
276
    }
277

    
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279
// PUBLIC API
280

    
281
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
282
    {
283
    int layer, nextAngle;
284

    
285
    if( curr==0 ) mLastRot = rnd.nextInt(4);
286

    
287
    switch(mLastRot)
288
      {
289
      case LAST_SL: layer = rnd.nextInt(2);
290
                    nextAngle = rnd.nextInt(12)-6;
291

    
292
                    if( nextAngle==0 )
293
                      {
294
                      layer = 1-layer;
295
                      nextAngle = (2*rnd.nextInt(2)-1)*(rnd.nextInt(5)+1);
296
                      }
297

    
298
                    scramble[curr][0] = 0;
299
                    scramble[curr][1] = 2*layer;
300
                    scramble[curr][2] = nextAngle;
301
                    mLastRot = layer==0 ? LAST_LO : LAST_UP;
302
                    break;
303
      case LAST_LO:
304
      case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
305
                    nextAngle = rnd.nextInt(12)-6;
306

    
307
                    if( nextAngle!=0 )
308
                      {
309
                      scramble[curr][0] = 0;
310
                      scramble[curr][1] = 2*layer;
311
                      scramble[curr][2] = nextAngle;
312
                      mLastRot = LAST_UL;
313
                      }
314
                    else
315
                      {
316
                      scramble[curr][0] = 1;
317
                      scramble[curr][1] = rnd.nextInt(2);
318
                      scramble[curr][2] = 1;
319
                      mLastRot = LAST_SL;
320
                      }
321
                    break;
322
      case LAST_UL: scramble[curr][0] = 1;
323
                    scramble[curr][1] = rnd.nextInt(2);
324
                    scramble[curr][2] = 1;
325
                    mLastRot = LAST_SL;
326
                    break;
327
      }
328
    }
329

    
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331
// Square-2 is solved iff
332
// a) all of its cubits are rotated with the same quat
333
// b) its two 'middle' cubits are rotated with the same quat, the 6 'front' and 6 'back'
334
// edges and corners with this quat multiplied by QUATS[18] (i.e. those are upside down)
335
// and all the 12 left and right edges and corners also with the same quat multiplied by
336
// QUATS[12] - i.e. also upside down.
337

    
338
  public boolean isSolved()
339
    {
340
    int index = CUBITS[0].mQuatIndex;
341

    
342
    if( CUBITS[1].mQuatIndex!=index ) return false;
343

    
344
    int indexX = mulQuat(index,12);  // QUATS[12] = 180deg (1,0,0)
345
    int indexZ = mulQuat(index,18);  // QUATS[18] = 180deg (0,0,1)
346

    
347
    for(int i=2; i<18; i+=2)
348
      {
349
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexZ ) return false;
350
      }
351
    for(int i=3; i<18; i+=2)
352
      {
353
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexX ) return false;
354
      }
355
    for(int i=18; i<NUM_CUBITS; i+=2)
356
      {
357
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexX ) return false;
358
      }
359
    for(int i=19; i<NUM_CUBITS; i+=2)
360
      {
361
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexZ ) return false;
362
      }
363

    
364
    return true;
365
    }
366

    
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368

    
369
  public int getObjectName(int numLayers)
370
    {
371
    return R.string.squa2;
372
    }
373

    
374
///////////////////////////////////////////////////////////////////////////////////////////////////
375

    
376
  public int getInventor(int numLayers)
377
    {
378
    return R.string.squa2_inventor;
379
    }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
  public int getComplexity(int numLayers)
384
    {
385
    return 7;
386
    }
387
}
(40-40/41)