Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistySquare1.java @ f20119c6

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 TwistySquare1 extends TwistyObject
42
{
43
  private static final float COS15 = (SQ6+SQ2)/4;
44
  private static final float SIN15 = (SQ6-SQ2)/4;
45
  private static final float     X = 3*(2-SQ3)/2;
46

    
47
  static final Static3D[] ROT_AXIS = new Static3D[]
48
    {
49
      new Static3D(0,1,0),
50
      new Static3D(COS15,0,SIN15)
51
    };
52

    
53
  private static final int[] BASIC_ANGLE = new int[] { 12,2 };
54

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

    
62
  private static final Static4D[] QUATS = new Static4D[]
63
    {
64
      new Static4D(  0.0f,  0.0f,  0.0f,  1.0f ),
65
      new Static4D(  0.0f, SIN15,  0.0f, COS15 ),
66
      new Static4D(  0.0f,  0.5f,  0.0f, SQ3/2 ),
67
      new Static4D(  0.0f, SQ2/2,  0.0f, SQ2/2 ),
68
      new Static4D(  0.0f, SQ3/2,  0.0f,  0.5f ),
69
      new Static4D(  0.0f, COS15,  0.0f, SIN15 ),
70
      new Static4D(  0.0f,  1.0f,  0.0f,  0.0f ),
71
      new Static4D(  0.0f, COS15,  0.0f,-SIN15 ),
72
      new Static4D(  0.0f, SQ3/2,  0.0f, -0.5f ),
73
      new Static4D(  0.0f, SQ2/2,  0.0f,-SQ2/2 ),
74
      new Static4D(  0.0f,  0.5f,  0.0f,-SQ3/2 ),
75
      new Static4D(  0.0f, SIN15,  0.0f,-COS15 ),
76

    
77
      new Static4D(  1.0f,  0.0f,  0.0f,  0.0f ),
78
      new Static4D( COS15,  0.0f, SIN15,  0.0f ),
79
      new Static4D( SQ3/2,  0.0f,  0.5f,  0.0f ),
80
      new Static4D( SQ2/2,  0.0f, SQ2/2,  0.0f ),
81
      new Static4D(  0.5f,  0.0f, SQ3/2,  0.0f ),
82
      new Static4D( SIN15,  0.0f, COS15,  0.0f ),
83
      new Static4D(  0.0f,  0.0f,  1.0f,  0.0f ),
84
      new Static4D(-SIN15,  0.0f, COS15,  0.0f ),
85
      new Static4D( -0.5f,  0.0f, SQ3/2,  0.0f ),
86
      new Static4D(-SQ2/2,  0.0f, SQ2/2,  0.0f ),
87
      new Static4D(-SQ3/2,  0.0f,  0.5f,  0.0f ),
88
      new Static4D(-COS15,  0.0f, SIN15,  0.0f )
89
    };
90

    
91
  private static final int[] QUAT_NUMBER = new int[]
92
    {
93
      0, 6,
94
      0, 9, 6, 3, 18, 15, 12, 21,
95
      0, 9, 6, 3, 15, 12, 21, 18
96
    };
97

    
98
  // centers of the 2 middles + 8 edges + 8 corners
99
  private static final float[][] CENTERS = new float[][]
100
    {
101
      { 1.5f, 0.0f, 0.0f },
102
      {-1.5f, 0.0f, 0.0f },
103

    
104
      { 0.0f, 1.0f, 1.5f },
105
      { 1.5f, 1.0f, 0.0f },
106
      { 0.0f, 1.0f,-1.5f },
107
      {-1.5f, 1.0f, 0.0f },
108
      { 0.0f,-1.0f, 1.5f },
109
      { 1.5f,-1.0f, 0.0f },
110
      { 0.0f,-1.0f,-1.5f },
111
      {-1.5f,-1.0f, 0.0f },
112

    
113
      { 1.0f, 1.0f, 2.0f, 2.0f, 1.0f, 1.0f },
114
      { 1.0f, 1.0f,-2.0f, 2.0f, 1.0f,-1.0f },
115
      {-1.0f, 1.0f,-2.0f,-2.0f, 1.0f,-1.0f },
116
      {-1.0f, 1.0f, 2.0f,-2.0f, 1.0f, 1.0f },
117
      { 1.0f,-1.0f, 2.0f, 2.0f,-1.0f, 1.0f },
118
      { 1.0f,-1.0f,-2.0f, 2.0f,-1.0f,-1.0f },
119
      {-1.0f,-1.0f,-2.0f,-2.0f,-1.0f,-1.0f },
120
      {-1.0f,-1.0f, 2.0f,-2.0f,-1.0f, 1.0f }
121
    };
122

    
123
  private static final double[][] VERTICES_MIDDLE = new double[][]
124
    {
125
      { -1.5-X, 0.5, 1.5 },
126
      {    0.0, 0.5, 1.5 },
127
      {    0.0, 0.5,-1.5 },
128
      { -1.5+X, 0.5,-1.5 },
129
      { -1.5-X,-0.5, 1.5 },
130
      {    0.0,-0.5, 1.5 },
131
      {    0.0,-0.5,-1.5 },
132
      { -1.5+X,-0.5,-1.5 }
133
    };
134

    
135
  private static final int[][] VERT_INDEXES_MIDDLE = new int[][]
136
    {
137
      {0,1,2,3},   // counterclockwise!
138
      {4,5,6,7},
139
      {4,5,1,0},
140
      {5,6,2,1},
141
      {6,7,3,2},
142
      {7,4,0,3}
143
    };
144

    
145
  private static final double[][] VERTICES_EDGE = new double[][]
146
    {
147
      { -X, 0.5, 0.0 },
148
      { +X, 0.5, 0.0 },
149
      {0.0, 0.5,-1.5 },
150
      { -X,-0.5, 0.0 },
151
      { +X,-0.5, 0.0 },
152
      {0.0,-0.5,-1.5 },
153
    };
154

    
155
  private static final int[][] VERT_INDEXES_EDGE = new int[][]
156
    {
157
      {0,1,2},   // counterclockwise!
158
      {3,4,5},
159
      {3,4,1,0},
160
      {4,5,2,1},
161
      {5,3,0,2}
162
    };
163

    
164
  private static final double[][] VERTICES_CORNER = new double[][]
165
    {
166
      { X-1.5, 0.5,  0.0 },
167
      {   0.0, 0.5,  0.0 },
168
      {   0.0, 0.5,X-1.5 },
169
      {  -1.5, 0.5, -1.5 },
170
      { X-1.5,-0.5,  0.0 },
171
      {   0.0,-0.5,  0.0 },
172
      {   0.0,-0.5,X-1.5 },
173
      {  -1.5,-0.5, -1.5 }
174
    };
175

    
176
  private static final int[][] VERT_INDEXES_CORNER = new int[][]
177
    {
178
      {0,1,2,3},   // counterclockwise!
179
      {4,5,6,7},
180
      {4,5,1,0},
181
      {5,6,2,1},
182
      {7,4,0,3},
183
      {6,7,3,2}
184
    };
185

    
186
  private static final float[][] STICKERS = new float[][]
187
    {
188
      { -0.5f, -0.26289170f, 0.5f, -0.26289170f, 0.5f, 0.26289170f, -0.5f, 0.26289170f }, // middle front
189
      { -0.5f, -0.16666667f, 0.5f, -0.16666667f, 0.5f, 0.16666667f, -0.5f, 0.16666667f }, // middle right
190
      { -0.5f, -0.45534182f, 0.5f, -0.45534182f, 0.5f, 0.45534182f, -0.5f, 0.45534182f }, // middle back
191
      { -0.20096192f, -0.25f, 0.20096192f, -0.25f, 0.0f, 0.5f },                          // edge top
192
      { -0.40192384f, -0.5f, 0.40192384f, -0.5f, 0.40192384f, 0.5f, -0.40192384f, 0.5f }, // edge face
193
      { -0.2637079f, -0.38185397f, 0.38185397f, -0.38185397f, 0.38185397f, 0.2637079f, -0.5f, 0.5f } // corner top
194
    };
195

    
196
  private static final int NUM_ST = STICKERS.length;
197

    
198
  private static final int[][] mStickerType = new int[][]
199
    {
200
      {  NUM_ST,NUM_ST,0,     1,     2,NUM_ST },
201
      {       3,NUM_ST,4,NUM_ST,NUM_ST,NUM_ST },
202
      {       5,NUM_ST,2,     2,NUM_ST,NUM_ST }
203
    };
204

    
205
  // YELLOW 0 WHITE 1 BLUE 2 GREEN 3 RED 4 ORANGE 5
206
  private static final int[][] mStickerColor = new int[][]
207
    {
208
      { 0, 0, 4, 0, 5, 0 },
209
      { 0, 0, 5, 1, 4, 0 },
210

    
211
      { 2, 0, 4, 0, 0, 0 },
212
      { 2, 0, 0, 0, 0, 0 },
213
      { 2, 0, 5, 0, 0, 0 },
214
      { 2, 0, 1, 0, 0, 0 },
215
      { 3, 0, 4, 0, 0, 0 },
216
      { 3, 0, 0, 0, 0, 0 },
217
      { 3, 0, 5, 0, 0, 0 },
218
      { 3, 0, 1, 0, 0, 0 },
219

    
220
      { 2, 0, 4, 0, 0, 0 },
221
      { 2, 0, 0, 5, 0, 0 },
222
      { 2, 0, 5, 1, 0, 0 },
223
      { 2, 0, 1, 4, 0, 0 },
224
      { 3, 0, 0, 4, 0, 0 },
225
      { 3, 0, 5, 0, 0, 0 },
226
      { 3, 0, 1, 5, 0, 0 },
227
      { 3, 0, 4, 1, 0, 0 },
228
    };
229

    
230
  private static MeshBase[] mMeshes;
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233

    
234
  TwistySquare1(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
235
                DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
236
    {
237
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.SQU1, res, scrWidth);
238
    }
239

    
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

    
242
  private Static4D getQuat(int cubit)
243
    {
244
    return QUATS[QUAT_NUMBER[cubit]];
245
    }
246

    
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248

    
249
  MeshBase createCubitMesh(int cubit, int numLayers)
250
    {
251
    if( mMeshes==null )
252
      {
253
      FactoryCubit factory = FactoryCubit.getInstance();
254
      factory.clear();
255
      mMeshes = new MeshBase[3];
256
      }
257

    
258
    MeshBase mesh;
259

    
260
    if( cubit<2 )
261
      {
262
      if( mMeshes[0]==null )
263
        {
264
        float[][] bands= new float[][]
265
          {
266
             {0.040f,35,0.8f,1.0f,5,2,1},
267
             {0.020f,35,0.8f,1.0f,5,2,1},
268
             {0.001f,35,0.8f,1.0f,5,2,1}
269
          };
270
        int[] bandIndexes   = new int[] { 2,2,1,1,0,2 };
271
        float[][] corners   = new float[][] { {0.04f,0.05f} };
272
        int[] cornerIndexes = new int[] { 0,0,0,0,0,0,0,0 };
273
        float[][] centers   = new float[][] { { -0.75f, 0.0f, 0.0f} };
274
        int[] centerIndexes = new int[] { 0,0,0,0,0,0,0,0 };
275

    
276
        FactoryCubit factory = FactoryCubit.getInstance();
277
        factory.createNewFaceTransform(VERTICES_MIDDLE,VERT_INDEXES_MIDDLE);
278
        mMeshes[0] = factory.createRoundedSolid(VERTICES_MIDDLE, VERT_INDEXES_MIDDLE,
279
                                                bands, bandIndexes,
280
                                                corners, cornerIndexes,
281
                                                centers, centerIndexes,
282
                                                getNumCubitFaces() );
283
        }
284
      mesh = mMeshes[0].copy(true);
285
      }
286
    else if( cubit<10 )
287
      {
288
      if( mMeshes[1]==null )
289
        {
290
        float[][] bands= new float[][]
291
          {
292
            {0.038f,35,0.5f,0.9f, 5,2,1},
293
            {0.001f,35,0.5f,0.9f, 5,2,1}
294
          };
295
        int[] bandIndexes   = new int[] { 0,1,0,1,1 };
296
        float[][] corners   = new float[][] { {0.05f,0.20f} };
297
        int[] cornerIndexes = new int[] { 0,0,-1,0,0,-1 };
298
        float[][] centers   = new float[][] { { 0.0f, 0.0f,-0.5f} };
299
        int[] centerIndexes = new int[] { 0,0,-1,0,0,-1 };
300

    
301
        FactoryCubit factory = FactoryCubit.getInstance();
302
        factory.createNewFaceTransform(VERTICES_EDGE,VERT_INDEXES_EDGE);
303
        mMeshes[1] = factory.createRoundedSolid(VERTICES_EDGE, VERT_INDEXES_EDGE,
304
                                                bands, bandIndexes,
305
                                                corners, cornerIndexes,
306
                                                centers, centerIndexes,
307
                                                getNumCubitFaces() );
308
        }
309
      mesh = mMeshes[1].copy(true);
310
      }
311
    else
312
      {
313
      if( mMeshes[2]==null )
314
        {
315
        float[][] bands= new float[][]
316
          {
317
            {0.038f,35,0.9f,1.0f, 5,2,1},
318
            {0.001f,35,0.9f,1.0f, 5,2,1}
319
          };
320
        int[] bandIndexes   = new int[] { 0,1,0,0,1,1 };
321
        float[][] corners   = new float[][] { {0.07f,0.20f} };
322
        int[] cornerIndexes = new int[] { 0,0,0,-1,0,0,0,-1 };
323
        float[][] centers   = new float[][] { { -0.5f, 0.0f,-0.5f} };
324
        int[] centerIndexes = new int[] { -1,0,-1,-1,-1,0,-1,-1 };
325

    
326
        FactoryCubit factory = FactoryCubit.getInstance();
327
        factory.createNewFaceTransform(VERTICES_CORNER,VERT_INDEXES_CORNER);
328
        mMeshes[2] = factory.createRoundedSolid(VERTICES_CORNER, VERT_INDEXES_CORNER,
329
                                                bands, bandIndexes,
330
                                                corners, cornerIndexes,
331
                                                centers, centerIndexes,
332
                                                getNumCubitFaces() );
333
        }
334
      mesh = mMeshes[2].copy(true);
335
      }
336

    
337
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
338
    mesh.apply(quat,0xffffffff,0);
339

    
340
    return mesh;
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
346
    {
347
    int COLORS = FACE_COLORS.length;
348
    int stickerType = face/COLORS;
349
    float R,S;
350

    
351
    switch(stickerType)
352
      {
353
      case 0:  R = 0.06f; S = 0.05f; break;
354
      case 1:  R = 0.04f; S = 0.04f; break;
355
      case 2:  R = 0.11f; S = 0.09f; break;
356
      case 3:  R = 0.03f; S = 0.05f; break;
357
      case 4:  R = 0.11f; S = 0.08f; break;
358
      case 5:  R = 0.08f; S = 0.08f; break;
359
      default: R = 0.00f; S = 0.00f; break;
360
      }
361

    
362
    FactorySticker factory = FactorySticker.getInstance();
363
    factory.drawRoundedPolygon(canvas, paint, left, top, STICKERS[stickerType], S, FACE_COLORS[face%COLORS], R);
364
    }
365

    
366
///////////////////////////////////////////////////////////////////////////////////////////////////
367

    
368
  float[][] getCubitPositions(int numLayers)
369
    {
370
    return CENTERS;
371
    }
372

    
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374

    
375
  Static4D[] getQuats()
376
    {
377
    return QUATS;
378
    }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

    
382
  boolean shouldResetTextureMaps()
383
    {
384
    return false;
385
    }
386

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

    
389
  int getNumFaces()
390
    {
391
    return FACE_COLORS.length;
392
    }
393

    
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395

    
396
  int getNumStickerTypes(int numLayers)
397
    {
398
    return STICKERS.length;
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  int getNumCubitFaces()
404
    {
405
    return 6;
406
    }
407

    
408
///////////////////////////////////////////////////////////////////////////////////////////////////
409

    
410
  float getScreenRatio()
411
    {
412
    return 0.5f;
413
    }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
  int getFaceColor(int cubit, int cubitface, int numLayers)
418
    {
419
    int type;
420

    
421
         if( cubit< 2 ) type = 0;
422
    else if( cubit<10 ) type = 1;
423
    else                type = 2;
424

    
425
    return mStickerType[type][cubitface]*FACE_COLORS.length + mStickerColor[cubit][cubitface];
426
    }
427

    
428
///////////////////////////////////////////////////////////////////////////////////////////////////
429

    
430
  float returnMultiplier()
431
    {
432
    return 1.0f;
433
    }
434

    
435
///////////////////////////////////////////////////////////////////////////////////////////////////
436

    
437
  float[][] getCuts(int numLayers)
438
    {
439
    return new float[][] { {-0.5f,+0.5f}, {0.0f} };
440
    }
441

    
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443
// this implements the fact that corner cubits have multiple 'centers' and this means the cubit
444
// might span more than one layer along a given axis - i.e. that this is a bandaged puzzle.
445

    
446
  int computeBitmapFromRow(int rowBitmap, int axis)
447
    {
448
    int bitmap, initBitmap=0;
449

    
450
    while( initBitmap!=rowBitmap )
451
      {
452
      initBitmap = rowBitmap;
453

    
454
      for(int cubit=0; cubit<NUM_CUBITS; cubit++)
455
        {
456
        bitmap = CUBITS[cubit].mRotationRow[axis];
457
        if( (rowBitmap & bitmap) != 0 ) rowBitmap |= bitmap;
458
        }
459
      }
460

    
461
    return rowBitmap;
462
    }
463

    
464
///////////////////////////////////////////////////////////////////////////////////////////////////
465
// PUBLIC API
466

    
467
  public Static3D[] getRotationAxis()
468
    {
469
    return ROT_AXIS;
470
    }
471

    
472
///////////////////////////////////////////////////////////////////////////////////////////////////
473

    
474
  public int[] getBasicAngle()
475
    {
476
    return BASIC_ANGLE;
477
    }
478

    
479
///////////////////////////////////////////////////////////////////////////////////////////////////
480
// TODO
481

    
482
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
483
    {
484
    if( num==0 )
485
      {
486
      scramble[num][0] = rnd.nextInt(NUM_AXIS);
487
      }
488
    else
489
      {
490
      int newVector = rnd.nextInt(NUM_AXIS-1);
491
      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
492
      }
493

    
494
    scramble[num][1] = rnd.nextFloat()<=0.5f ? 0 : 1;
495

    
496
    switch( rnd.nextInt(4) )
497
      {
498
      case 0: scramble[num][2] = -2; break;
499
      case 1: scramble[num][2] = -1; break;
500
      case 2: scramble[num][2] =  1; break;
501
      case 3: scramble[num][2] =  2; break;
502
      }
503
    }
504

    
505
///////////////////////////////////////////////////////////////////////////////////////////////////
506

    
507
  public boolean isSolved()
508
    {
509
    int index = CUBITS[0].mQuatIndex;
510

    
511
    for(int i=1; i<NUM_CUBITS; i++)
512
      {
513
      if( CUBITS[i].mQuatIndex != index ) return false;
514
      }
515

    
516
    return true;
517
    }
518

    
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520
// only needed for solvers - there are no Square solvers ATM)
521

    
522
  public String retObjectString()
523
    {
524
    return "";
525
    }
526

    
527
///////////////////////////////////////////////////////////////////////////////////////////////////
528

    
529
  public int getObjectName(int numLayers)
530
    {
531
    return R.string.squa1;
532
    }
533

    
534
///////////////////////////////////////////////////////////////////////////////////////////////////
535

    
536
  public int getInventor(int numLayers)
537
    {
538
    return R.string.squa1_inventor;
539
    }
540

    
541
///////////////////////////////////////////////////////////////////////////////////////////////////
542

    
543
  public int getComplexity(int numLayers)
544
    {
545
    return 9;
546
    }
547
}
(36-36/37)