Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistySkewb.java @ 7dc57f89

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 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
public class TwistySkewb extends TwistyObject
42
{
43
  private static final int FACES_PER_CUBIT =6;
44

    
45
  // the four rotation axis of a RubikSkewb. Must be normalized.
46
  static final Static3D[] ROT_AXIS = new Static3D[]
47
         {
48
           new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),
49
           new Static3D(+SQ3/3,+SQ3/3,-SQ3/3),
50
           new Static3D(+SQ3/3,-SQ3/3,+SQ3/3),
51
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
52
         };
53

    
54
  private static final int[] FACE_COLORS = new int[]
55
         {
56
           COLOR_YELLOW, COLOR_WHITE,
57
           COLOR_BLUE  , COLOR_GREEN,
58
           COLOR_RED   , COLOR_ORANGE
59
         };
60

    
61
  // All legal rotation quats of a RubikSkewb
62
  private static final Static4D[] QUATS = new Static4D[]
63
         {
64
           new Static4D(  0.0f,  0.0f,  0.0f,  1.0f ),
65
           new Static4D(  1.0f,  0.0f,  0.0f,  0.0f ),
66
           new Static4D(  0.0f,  1.0f,  0.0f,  0.0f ),
67
           new Static4D(  0.0f,  0.0f,  1.0f,  0.0f ),
68

    
69
           new Static4D(  0.5f,  0.5f,  0.5f,  0.5f ),
70
           new Static4D(  0.5f,  0.5f,  0.5f, -0.5f ),
71
           new Static4D(  0.5f,  0.5f, -0.5f,  0.5f ),
72
           new Static4D(  0.5f,  0.5f, -0.5f, -0.5f ),
73
           new Static4D(  0.5f, -0.5f,  0.5f,  0.5f ),
74
           new Static4D(  0.5f, -0.5f,  0.5f, -0.5f ),
75
           new Static4D(  0.5f, -0.5f, -0.5f,  0.5f ),
76
           new Static4D(  0.5f, -0.5f, -0.5f, -0.5f )
77
         };
78

    
79
  private static final int[][] mCornerMap =
80
         {
81
           {  4, 2, 0, 18,18,18 },
82
           {  2, 5, 0, 18,18,18 },
83
           {  3, 4, 0, 18,18,18 },
84
           {  5, 3, 0, 18,18,18 },
85
           {  1, 2, 4, 18,18,18 },
86
           {  5, 2, 1, 18,18,18 },
87
           {  4, 3, 1, 18,18,18 },
88
           {  1, 3, 5, 18,18,18 },
89
         };
90

    
91
  private static final int[][] mEdgeMap =
92
         {
93
           { 10, 8, 18,18,18,18 },
94
           {  6,10, 18,18,18,18 },
95
           { 10, 9, 18,18,18,18 },
96
           {  7,10, 18,18,18,18 },
97
           {  8, 6, 18,18,18,18 },
98
           {  9, 6, 18,18,18,18 },
99
           {  9, 7, 18,18,18,18 },
100
           {  8, 7, 18,18,18,18 },
101
           { 11, 8, 18,18,18,18 },
102
           {  6,11, 18,18,18,18 },
103
           { 11, 9, 18,18,18,18 },
104
           {  7,11, 18,18,18,18 }
105
         };
106

    
107
  private static final int[][] mCenterMap =
108
         {
109
           { 12, 18,18,18,18,18 },
110
           { 13, 18,18,18,18,18 },
111
           { 14, 18,18,18,18,18 },
112
           { 15, 18,18,18,18,18 },
113
           { 16, 18,18,18,18,18 },
114
           { 17, 18,18,18,18,18 },
115
         };
116

    
117
  private static final double[][] VERTICES_CORNER = new double[][]
118
          {
119
              {-0.5f, 0.0f, 0.0f},
120
              { 0.0f,-0.5f, 0.0f},
121
              { 0.0f, 0.0f,-0.5f},
122
              {-0.5f,-0.5f,-0.5f},
123
              { 0.0f, 0.0f, 0.0f}
124
          };
125

    
126
  private static final int[][] VERT_INDEXES_CORNER = new int[][]
127
          {
128
              {0,1,4},
129
              {2,0,4},
130
              {1,2,4},
131
              {3,1,0},
132
              {3,2,1},
133
              {3,0,2}
134
          };
135

    
136
  private static final double[][] VERTICES_EDGE = new double[][]
137
          {
138
             {-0.5, 0.0, 0.0},
139
             { 0.5, 0.0, 0.0},
140
             { 0.0,-0.5, 0.0},
141
             { 0.0, 0.0,-0.5}
142
          };
143

    
144
  private static final int[][] VERT_INDEXES_EDGE = new int[][]
145
          {
146
             {2,1,0},   // counterclockwise!
147
             {3,0,1},
148
             {2,3,1},
149
             {3,2,0},
150
          };
151

    
152
  private static final double[][] VERTICES_FACE = new double[][]
153
          {
154
             {-0.5f, 0.0f, 0.0f },
155
             { 0.0f,-0.5f, 0.0f },
156
             { 0.5f, 0.0f, 0.0f },
157
             { 0.0f, 0.5f, 0.0f },
158
             { 0.0f, 0.0f,-0.5f }
159
          };
160

    
161
  private static final int[][] VERT_INDEXES_FACE = new int[][]
162
          {
163
             {0,1,2,3},
164
             {4,1,0},
165
             {4,2,1},
166
             {4,3,2},
167
             {4,0,3}
168
          };
169

    
170

    
171
  private static final float[][] STICKERS = new float[][]
172
          {
173
             { -0.5f,   0.25f, 0.25f,  -0.5f, 0.25f, 0.25f  },
174
             {  0.0f, -1.0f/3, 0.50f, 1.0f/6, -0.5f, 1.0f/6 },
175
             { -0.5f,    0.0f, 0.00f,  -0.5f, 0.50f, 0.0f, 0.0f, 0.5f }
176
          };
177

    
178
  private static MeshBase[] mMeshes;
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

    
182
  TwistySkewb(int size, Static4D quat, DistortedTexture texture,
183
              MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
184
    {
185
    super(size, 2*size-2, quat, texture, mesh, effects, moves, ObjectList.SKEW, res, scrWidth);
186
    }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
  double[][] getVertices(int cubitType)
191
    {
192
    if( cubitType==0 ) return VERTICES_CORNER;
193
    if( cubitType==1 ) return VERTICES_EDGE;
194
    if( cubitType==2 ) return VERTICES_FACE;
195
    return null;
196
    }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199

    
200
  int[][] getVertIndexes(int cubitType)
201
    {
202
    if( cubitType==0 ) return VERT_INDEXES_CORNER;
203
    if( cubitType==1 ) return VERT_INDEXES_EDGE;
204
    if( cubitType==2 ) return VERT_INDEXES_FACE;
205
    return null;
206
    }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
  int getNumCubitTypes(int numLayers)
211
    {
212
    return numLayers==2 ? 2 : 3;
213
    }
214

    
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216

    
217
  private int getNumCorners()
218
    {
219
    return 8;
220
    }
221

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

    
224
  private int getNumEdges(int layers)
225
    {
226
    return (layers-2)*12;
227
    }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230

    
231
  private int getNumCentersPerFace(int layers)
232
    {
233
    return ((layers-2)*(layers-2) + (layers-1)*(layers-1));
234
    }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237

    
238
  float getScreenRatio()
239
    {
240
    return 1.0f;
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

    
245
  Static4D[] getQuats()
246
    {
247
    return QUATS;
248
    }
249

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

    
252
  int getNumFaces()
253
    {
254
    return FACE_COLORS.length;
255
    }
256

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

    
259
  boolean shouldResetTextureMaps()
260
    {
261
    return false;
262
    }
263

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

    
266
  int getNumStickerTypes(int numLayers)
267
    {
268
    return 3;
269
    }
270

    
271
///////////////////////////////////////////////////////////////////////////////////////////////////
272

    
273
  float[] getCuts(int numLayers)
274
    {
275
    float[] cuts = new float[numLayers-1];
276

    
277
    switch(numLayers)
278
      {
279
      case 2: cuts[0] = 0;
280
              break;
281
      case 3: cuts[0] = -SQ3/12;
282
              cuts[1] = +SQ3/12;
283
              break;
284
      case 4: cuts[0] = -SQ3/9;
285
              cuts[1] = 0;
286
              cuts[2] = +SQ3/9;
287
              break;
288
      }
289
    return cuts;
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  int getNumCubitFaces()
295
    {
296
    return FACES_PER_CUBIT;
297
    }
298

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
  float[][] getCubitPositions(int numLayers)
302
    {
303
    final float DIST_CORNER = (numLayers-1)*0.50f;
304
    final float DIST_EDGE   = (numLayers-1)*0.50f;
305
    final float DIST_CENTER = (numLayers-1)*0.50f;
306

    
307
    final int numCorners = getNumCorners();
308
    final int numEdges   = getNumEdges(numLayers);
309
    final int numCenters = 6*getNumCentersPerFace(numLayers);
310

    
311
    final float[][] CENTERS = new float[numCorners+numEdges+numCenters][];
312

    
313
    /// CORNERS //////////////////////////////////////////////
314

    
315
    CENTERS[0] = new float[] { DIST_CORNER, DIST_CORNER, DIST_CORNER };
316
    CENTERS[1] = new float[] { DIST_CORNER, DIST_CORNER,-DIST_CORNER };
317
    CENTERS[2] = new float[] { DIST_CORNER,-DIST_CORNER, DIST_CORNER };
318
    CENTERS[3] = new float[] { DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
319
    CENTERS[4] = new float[] {-DIST_CORNER, DIST_CORNER, DIST_CORNER };
320
    CENTERS[5] = new float[] {-DIST_CORNER, DIST_CORNER,-DIST_CORNER };
321
    CENTERS[6] = new float[] {-DIST_CORNER,-DIST_CORNER, DIST_CORNER };
322
    CENTERS[7] = new float[] {-DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
323

    
324
    /// EDGES ///////////////////////////////////////////////
325

    
326
    final float[][]  edgeTable =
327
        {
328
            {0,+DIST_EDGE,+DIST_EDGE},
329
            {+DIST_EDGE,0,+DIST_EDGE},
330
            {0,-DIST_EDGE,+DIST_EDGE},
331
            {-DIST_EDGE,0,+DIST_EDGE},
332
            {+DIST_EDGE,+DIST_EDGE,0},
333
            {+DIST_EDGE,-DIST_EDGE,0},
334
            {-DIST_EDGE,-DIST_EDGE,0},
335
            {-DIST_EDGE,+DIST_EDGE,0},
336
            {0,+DIST_EDGE,-DIST_EDGE},
337
            {+DIST_EDGE,0,-DIST_EDGE},
338
            {0,-DIST_EDGE,-DIST_EDGE},
339
            {-DIST_EDGE,0,-DIST_EDGE}
340
        };
341

    
342
    int index=8;
343

    
344
    for (float[] edges : edgeTable)
345
      {
346
      float c = (3-numLayers)*0.5f;
347

    
348
      for (int j=0; j<numLayers-2; j++, c+=1.0f, index++)
349
        {
350
        CENTERS[index] = new float[] { edges[0]==0 ? c : edges[0] ,
351
                                       edges[1]==0 ? c : edges[1] ,
352
                                       edges[2]==0 ? c : edges[2] };
353
        }
354
      }
355

    
356
    /// CENTERS //////////////////////////////////////////////
357

    
358
    final float X= -1000.0f;
359
    final float Y= -1001.0f;
360

    
361
    final float[][]  centerTable =
362
        {
363
            {+DIST_CENTER,X,Y},
364
            {-DIST_CENTER,X,Y},
365
            {X,+DIST_CENTER,Y},
366
            {X,-DIST_CENTER,Y},
367
            {X,Y,+DIST_CENTER},
368
            {X,Y,-DIST_CENTER}
369
        };
370

    
371
    float x,y, cen0, cen1, cen2;
372

    
373
    for( float[] centers : centerTable )
374
      {
375
      x = (2-numLayers)*0.5f;
376

    
377
      for(int i=0; i<numLayers-1; i++, x+=1.0f)
378
        {
379
        y = (2-numLayers)*0.5f;
380

    
381
        for(int j=0; j<numLayers-1; j++, y+=1.0f, index++)
382
          {
383
               if( centers[0]==Y ) cen0 = y;
384
          else if( centers[0]==X ) cen0 = x;
385
          else                     cen0 = centers[0];
386

    
387
               if( centers[1]==Y ) cen1 = y;
388
          else if( centers[1]==X ) cen1 = x;
389
          else                     cen1 = centers[1];
390

    
391
               if( centers[2]==Y ) cen2 = y;
392
          else if( centers[2]==X ) cen2 = x;
393
          else                     cen2 = centers[2];
394

    
395
          CENTERS[index] = new float[] {cen0,cen1,cen2};
396
          }
397
        }
398

    
399
      x = (3-numLayers)*0.5f;
400

    
401
      for(int i=0; i<numLayers-2; i++, x+=1.0f)
402
        {
403
        y = (3-numLayers)*0.5f;
404

    
405
        for(int j=0; j<numLayers-2; j++, y+=1.0f, index++)
406
          {
407
               if( centers[0]==Y ) cen0 = y;
408
          else if( centers[0]==X ) cen0 = x;
409
          else                     cen0 = centers[0];
410

    
411
               if( centers[1]==Y ) cen1 = y;
412
          else if( centers[1]==X ) cen1 = x;
413
          else                     cen1 = centers[1];
414

    
415
               if( centers[2]==Y ) cen2 = y;
416
          else if( centers[2]==X ) cen2 = x;
417
          else                     cen2 = centers[2];
418

    
419
          CENTERS[index] = new float[] {cen0,cen1,cen2};
420
          }
421
        }
422
      }
423

    
424
    return CENTERS;
425
    }
426

    
427
///////////////////////////////////////////////////////////////////////////////////////////////////
428

    
429
  private Static4D getQuat(int cubit, int numLayers)
430
    {
431
    int numCorners = getNumCorners();
432
    int numEdges   = getNumEdges(numLayers);
433

    
434
    if( cubit<numCorners )
435
      {
436
      switch(cubit)
437
        {
438
        case  0: return QUATS[0];                          //  unit quat
439
        case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
440
        case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
441
        case  3: return QUATS[1];                          // 180 along X
442
        case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
443
        case  5: return QUATS[2];                          // 180 along Y
444
        case  6: return QUATS[3];                          // 180 along Z
445
        case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
446
        }
447
      }
448
    else if( cubit<numCorners+numEdges )
449
      {
450
      int edge = (cubit-numCorners)/(numLayers-2);
451

    
452
      switch(edge)
453
        {
454
        case  0: return QUATS[ 0];
455
        case  1: return QUATS[ 5];
456
        case  2: return QUATS[ 3];
457
        case  3: return QUATS[11];
458
        case  4: return QUATS[ 4];
459
        case  5: return QUATS[ 7];
460
        case  6: return QUATS[ 9];
461
        case  7: return QUATS[10];
462
        case  8: return QUATS[ 2];
463
        case  9: return QUATS[ 8];
464
        case 10: return QUATS[ 1];
465
        case 11: return QUATS[ 6];
466
        }
467
      }
468
    else
469
      {
470
      int center = (cubit-numCorners-numEdges)/getNumCentersPerFace(numLayers);
471

    
472
      switch(center)
473
        {
474
        case 0: return new Static4D(0,-SQ2/2,0,SQ2/2);    // -90 along Y
475
        case 1: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
476
        case 2: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
477
        case 3: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
478
        case 4: return QUATS[0];                          //  unit quaternion
479
        case 5: return QUATS[1];                          // 180 along X
480
        }
481
      }
482

    
483
    return null;
484
    }
485

    
486
///////////////////////////////////////////////////////////////////////////////////////////////////
487

    
488
  MeshBase createCubitMesh(int cubit, int numLayers)
489
    {
490
    if( mMeshes==null )
491
      {
492
      FactoryCubit factory = FactoryCubit.getInstance();
493
      factory.clear();
494
      mMeshes = new MeshBase[3];
495
      }
496

    
497
    MeshBase mesh;
498

    
499
    int numCorners = getNumCorners();
500
    int numEdges   = getNumEdges(numLayers);
501

    
502
    if( cubit<numCorners )
503
      {
504
      if( mMeshes[0]==null )
505
        {
506
        float[][] bands= new float[][]
507
          {
508
             {0.028f,35,0.16f,0.7f,7,3,3},
509
             {0.000f, 0,1.00f,0.0f,3,1,5}
510
          };
511
        int[] bandIndexes   = new int[] { 0,0,0,1,1,1 };
512
        float[][] corners   = new float[][] { {0.08f,0.15f}, {0.08f,0.20f} };
513
        int[] cornerIndexes = new int[] { 1,1,1,0,0 };
514
        float[][] centers   = new float[][] { {-0.25f, -0.25f, -0.25f} };
515
        int[] centerIndexes = new int[] { 0,0,0,-1,0 };
516

    
517
        FactoryCubit factory = FactoryCubit.getInstance();
518
        factory.createNewFaceTransform(VERTICES_CORNER,VERT_INDEXES_CORNER);
519
        mMeshes[0] = factory.createRoundedSolid(VERTICES_CORNER, VERT_INDEXES_CORNER,
520
                                                bands, bandIndexes,
521
                                                corners, cornerIndexes,
522
                                                centers, centerIndexes,
523
                                                getNumCubitFaces() );
524
        //mMeshes[0] = FactoryCubit.getInstance().createSkewbCornerMesh();
525
        }
526
      mesh = mMeshes[0].copy(true);
527
      }
528
    else if( cubit<numCorners+numEdges )
529
      {
530
      if( mMeshes[1]==null )
531
        {
532
        float[][] bands= new float[][]
533
          {
534
             {0.035f,30,0.16f,0.8f,7,2,5},
535
             {0.020f,45,0.16f,0.2f,3,1,2}
536
          };
537
        int[] bandIndexes   = new int[] { 0,0,1,1 };
538
        float[][] corners   = new float[][] { {0.07f,0.20f}, {0.02f,0.30f} };
539
        int[] cornerIndexes = new int[] { 0,0,1,1 };
540
        float[][] centers   = new float[][] { {0.0f, -0.25f, -0.25f} };
541
        int[] centerIndexes = new int[] { 0,0,0,0 };
542

    
543
        FactoryCubit factory = FactoryCubit.getInstance();
544
        factory.createNewFaceTransform(VERTICES_EDGE,VERT_INDEXES_EDGE);
545
        mMeshes[1] = factory.createRoundedSolid(VERTICES_EDGE, VERT_INDEXES_EDGE,
546
                                                bands, bandIndexes,
547
                                                corners, cornerIndexes,
548
                                                centers, centerIndexes,
549
                                                getNumCubitFaces() );
550
        }
551
      mesh = mMeshes[1].copy(true);
552
      }
553
    else
554
      {
555
      if( mMeshes[2]==null )
556
        {
557
        float[][] bands= new float[][]
558
          {
559
             {0.051f,35,SQ2/8,0.9f, 7,3,3},
560
             {0.000f, 0,    1,0.0f, 3,0,0}
561
          };
562
        int[] bandIndexes   = new int[] { 0,1,1,1,1 };
563
        float[][] corners   = new float[][] { {0.06f,0.10f} };
564
        int[] cornerIndexes = new int[] { 0,0,0,0,0 };
565
        float[][] centers   = new float[][] { {0,0,-0.2f} };
566
        int[] centerIndexes = new int[] { 0,0,0,0,-1 };
567

    
568
        FactoryCubit factory = FactoryCubit.getInstance();
569
        factory.createNewFaceTransform(VERTICES_FACE,VERT_INDEXES_FACE);
570
        mMeshes[2] = factory.createRoundedSolid(VERTICES_FACE, VERT_INDEXES_FACE,
571
                                                bands, bandIndexes,
572
                                                corners, cornerIndexes,
573
                                                centers, centerIndexes,
574
                                                getNumCubitFaces() );
575
        }
576
      mesh = mMeshes[2].copy(true);
577
      }
578

    
579
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit,numLayers), new Static3D(0,0,0) );
580
    mesh.apply(quat,0xffffffff,0);
581

    
582
    return mesh;
583
    }
584

    
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586

    
587
  int getFaceColor(int cubit, int cubitface, int numLayers)
588
    {
589
    int numCorners = getNumCorners();
590
    int numEdges   = getNumEdges(numLayers);
591

    
592
    if( cubit<numCorners )
593
      {
594
      return mCornerMap[cubit][cubitface];
595
      }
596
    else if( cubit<numCorners+numEdges )
597
      {
598
      int edge = (cubit-numCorners)/(numLayers-2);
599
      return mEdgeMap[edge][cubitface];
600
      }
601
    else
602
      {
603
      int center = (cubit-numCorners-numEdges)/getNumCentersPerFace(numLayers);
604
      return mCenterMap[center][cubitface];
605
      }
606
    }
607

    
608
///////////////////////////////////////////////////////////////////////////////////////////////////
609

    
610
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
611
    {
612
    int COLORS = FACE_COLORS.length;
613
    float R=0.0f,S=0.0f;
614
    int cubitType = face/COLORS;
615

    
616
    switch(cubitType)
617
      {
618
      case 0: R = 0.025f; S = 0.045f; break;
619
      case 1: R = 0.025f; S = 0.035f; break;
620
      case 2: R = 0.055f; S = 0.035f; break;
621
      }
622

    
623
    FactorySticker factory = FactorySticker.getInstance();
624
    factory.drawRoundedPolygon(canvas, paint, left, top, STICKERS[cubitType], S, FACE_COLORS[face%COLORS], R);
625
    }
626

    
627
///////////////////////////////////////////////////////////////////////////////////////////////////
628

    
629
  float returnMultiplier()
630
    {
631
    return 2.0f;
632
    }
633

    
634
///////////////////////////////////////////////////////////////////////////////////////////////////
635

    
636
  float[] getRowChances(int numLayers)
637
    {
638
    float[] chances = new float[numLayers];
639

    
640
    switch(numLayers)
641
      {
642
      case 2: chances[0] = 0.5f;
643
              chances[1] = 1.0f;
644
              break;
645
      case 3: chances[0] = 0.5f;
646
              chances[1] = 0.5f;
647
              chances[2] = 1.0f;
648
              break;
649
      default:for(int i=0; i<numLayers; i++)
650
                {
651
                chances[i] = (float)(i+1)/numLayers;
652
                }
653
      }
654

    
655
    return chances;
656
    }
657

    
658
///////////////////////////////////////////////////////////////////////////////////////////////////
659
// PUBLIC API
660

    
661
  public Static3D[] getRotationAxis()
662
    {
663
    return ROT_AXIS;
664
    }
665

    
666
///////////////////////////////////////////////////////////////////////////////////////////////////
667

    
668
  public int getBasicAngle()
669
    {
670
    return 3;
671
    }
672

    
673
///////////////////////////////////////////////////////////////////////////////////////////////////
674

    
675
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
676
    {
677
    if( num==0 )
678
      {
679
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
680
      }
681
    else
682
      {
683
      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
684
      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
685
      }
686

    
687
    float rowFloat = rnd.nextFloat();
688

    
689
    for(int row=0; row<mRowChances.length; row++)
690
      {
691
      if( rowFloat<=mRowChances[row] )
692
        {
693
        scramble[num][1] = row;
694
        break;
695
        }
696
      }
697

    
698
    switch( rnd.nextInt(2) )
699
      {
700
      case 0: scramble[num][2] = -1; break;
701
      case 1: scramble[num][2] =  1; break;
702
      }
703
    }
704

    
705
///////////////////////////////////////////////////////////////////////////////////////////////////
706
// The Skewb is solved if and only if:
707
//
708
// 1) all of its corner and edge cubits are rotated with the same quat
709
// 2) all its face cubits are rotated with the same quat like the corner ones,
710
//    and optionally they also might be upside down.
711
//
712
// i.e.
713
// cubits [ 8] and [ 9] - might be extra QUAT[1]
714
// cubits [10] and [11] - might be extra QUAT[2]
715
// cubits [12] and [13] - might be extra QUAT[3]
716

    
717
  public boolean isSolved()
718
    {
719
    int q = CUBITS[0].mQuatIndex;
720

    
721
    int numLayers      = getNumLayers();
722
    int numCorners     = getNumCorners();
723
    int numEdges       = getNumEdges(numLayers);
724
    int cornersAndEdges= numCorners + numEdges;
725
    int centersPerFace = getNumCentersPerFace(numLayers);
726
    int cubit, q1=q;
727

    
728
    for(cubit=0; cubit<cornersAndEdges; cubit++)
729
      {
730
      if( CUBITS[cubit].mQuatIndex != q ) return false;
731
      }
732

    
733
    for(int face=0; face<6; face++)
734
      {
735
      if( face%2==0 ) q1 = mulQuat(q, (face/2)+1);
736

    
737
      for(int center=0; center<centersPerFace; center++)
738
        {
739
        if( CUBITS[cubit].mQuatIndex != q && CUBITS[cubit].mQuatIndex != q1 ) return false;
740
        cubit++;
741
        }
742
      }
743

    
744
    return true;
745
    }
746

    
747
///////////////////////////////////////////////////////////////////////////////////////////////////
748
// only needed for solvers - there are no Skewb solvers ATM)
749

    
750
  public String retObjectString()
751
    {
752
    return "";
753
    }
754

    
755
///////////////////////////////////////////////////////////////////////////////////////////////////
756

    
757
  public int getObjectName(int numLayers)
758
    {
759
    switch(numLayers)
760
      {
761
      case 2: return R.string.skew2;
762
      case 3: return R.string.skew3;
763
      }
764
    return R.string.skew2;
765
    }
766

    
767
///////////////////////////////////////////////////////////////////////////////////////////////////
768

    
769
  public int getInventor(int numLayers)
770
    {
771
    switch(numLayers)
772
      {
773
      case 2: return R.string.skew2_inventor;
774
      case 3: return R.string.skew3_inventor;
775
      }
776
    return R.string.skew2_inventor;
777
    }
778

    
779
///////////////////////////////////////////////////////////////////////////////////////////////////
780

    
781
  public int getComplexity(int numLayers)
782
    {
783
    switch(numLayers)
784
      {
785
      case 2: return 5;
786
      case 3: return 9;
787
      }
788
    return 5;
789
    }
790
}
(33-33/33)