Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyHelicopter.java @ 0919eba7

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 TwistyHelicopter extends TwistyObject
42
{
43
  private static final int FACES_PER_CUBIT =6;
44

    
45
  // the six rotation axis of a Helicopter. Must be normalized.
46
  static final Static3D[] ROT_AXIS = new Static3D[]
47
         {
48
           new Static3D(     0, +SQ2/2, -SQ2/2),
49
           new Static3D(     0, -SQ2/2, -SQ2/2),
50
           new Static3D(+SQ2/2,      0, -SQ2/2),
51
           new Static3D(-SQ2/2,      0, -SQ2/2),
52
           new Static3D(+SQ2/2, -SQ2/2,      0),
53
           new Static3D(-SQ2/2, -SQ2/2,      0)
54
         };
55

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

    
63
  // All legal rotation quats of a HELICOPTER (same as the Cube!)
64
  private static final Static4D[] QUATS = new Static4D[]
65
         {
66
           new Static4D( 0.00f,  0.00f,  0.00f,  1.00f ),
67
           new Static4D( 1.00f,  0.00f,  0.00f,  0.00f ),
68
           new Static4D( 0.00f,  1.00f,  0.00f,  0.00f ),
69
           new Static4D( 0.00f,  0.00f,  1.00f,  0.00f ),
70

    
71
           new Static4D( SQ2/2,  SQ2/2,  0.00f,  0.00f ),
72
           new Static4D( SQ2/2, -SQ2/2,  0.00f,  0.00f ),
73
           new Static4D( SQ2/2,  0.00f,  SQ2/2,  0.00f ),
74
           new Static4D( SQ2/2,  0.00f, -SQ2/2,  0.00f ),
75
           new Static4D( SQ2/2,  0.00f,  0.00f,  SQ2/2 ),
76
           new Static4D( SQ2/2,  0.00f,  0.00f, -SQ2/2 ),
77
           new Static4D( 0.00f,  SQ2/2,  SQ2/2,  0.00f ),
78
           new Static4D( 0.00f,  SQ2/2, -SQ2/2,  0.00f ),
79
           new Static4D( 0.00f,  SQ2/2,  0.00f,  SQ2/2 ),
80
           new Static4D( 0.00f,  SQ2/2,  0.00f, -SQ2/2 ),
81
           new Static4D( 0.00f,  0.00f,  SQ2/2,  SQ2/2 ),
82
           new Static4D( 0.00f,  0.00f,  SQ2/2, -SQ2/2 ),
83

    
84
           new Static4D( 0.50f,  0.50f,  0.50f,  0.50f ),
85
           new Static4D( 0.50f,  0.50f,  0.50f, -0.50f ),
86
           new Static4D( 0.50f,  0.50f, -0.50f,  0.50f ),
87
           new Static4D( 0.50f,  0.50f, -0.50f, -0.50f ),
88
           new Static4D( 0.50f, -0.50f,  0.50f,  0.50f ),
89
           new Static4D( 0.50f, -0.50f,  0.50f, -0.50f ),
90
           new Static4D( 0.50f, -0.50f, -0.50f,  0.50f ),
91
           new Static4D( 0.50f, -0.50f, -0.50f, -0.50f )
92
         };
93

    
94
  private static final float DIST_CORNER = 0.50f;
95
  private static final float DIST_CENTER = 0.50f;
96
  private static final float XY_CENTER   = DIST_CORNER/3;
97

    
98
  // centers of the 8 corners + 6*4 face triangles ( i.e. of the all 32 cubits)
99
  private static final float[][] CENTERS = new float[][]
100
         {
101
             {   DIST_CORNER,   DIST_CORNER,   DIST_CORNER },
102
             {   DIST_CORNER,   DIST_CORNER,  -DIST_CORNER },
103
             {   DIST_CORNER,  -DIST_CORNER,   DIST_CORNER },
104
             {   DIST_CORNER,  -DIST_CORNER,  -DIST_CORNER },
105
             {  -DIST_CORNER,   DIST_CORNER,   DIST_CORNER },
106
             {  -DIST_CORNER,   DIST_CORNER,  -DIST_CORNER },
107
             {  -DIST_CORNER,  -DIST_CORNER,   DIST_CORNER },
108
             {  -DIST_CORNER,  -DIST_CORNER,  -DIST_CORNER },
109

    
110
             {   DIST_CENTER,     XY_CENTER,     XY_CENTER },
111
             {   DIST_CENTER,     XY_CENTER,    -XY_CENTER },
112
             {   DIST_CENTER,    -XY_CENTER,     XY_CENTER },
113
             {   DIST_CENTER,    -XY_CENTER,    -XY_CENTER },
114

    
115
             {  -DIST_CENTER,     XY_CENTER,     XY_CENTER },
116
             {  -DIST_CENTER,     XY_CENTER,    -XY_CENTER },
117
             {  -DIST_CENTER,    -XY_CENTER,     XY_CENTER },
118
             {  -DIST_CENTER,    -XY_CENTER,    -XY_CENTER },
119

    
120
             {   XY_CENTER  ,   DIST_CENTER,     XY_CENTER },
121
             {   XY_CENTER  ,   DIST_CENTER,    -XY_CENTER },
122
             {  -XY_CENTER  ,   DIST_CENTER,     XY_CENTER },
123
             {  -XY_CENTER  ,   DIST_CENTER,    -XY_CENTER },
124

    
125
             {   XY_CENTER  ,  -DIST_CENTER,     XY_CENTER },
126
             {   XY_CENTER  ,  -DIST_CENTER,    -XY_CENTER },
127
             {  -XY_CENTER  ,  -DIST_CENTER,     XY_CENTER },
128
             {  -XY_CENTER  ,  -DIST_CENTER,    -XY_CENTER },
129

    
130
             {   XY_CENTER  ,     XY_CENTER,   DIST_CENTER },
131
             {   XY_CENTER  ,    -XY_CENTER,   DIST_CENTER },
132
             {  -XY_CENTER  ,     XY_CENTER,   DIST_CENTER },
133
             {  -XY_CENTER  ,    -XY_CENTER,   DIST_CENTER },
134

    
135
             {   XY_CENTER  ,     XY_CENTER,  -DIST_CENTER },
136
             {   XY_CENTER  ,    -XY_CENTER,  -DIST_CENTER },
137
             {  -XY_CENTER  ,     XY_CENTER,  -DIST_CENTER },
138
             {  -XY_CENTER  ,    -XY_CENTER,  -DIST_CENTER },
139
         };
140

    
141
  // Colors of the faces of cubits. Each cubit has 6 faces
142
  private static final int[][] mFaceMap = new int[][]
143
         {
144
           { 4,2,0, 6,6,6 },
145
           { 0,2,5, 6,6,6 },
146
           { 4,0,3, 6,6,6 },
147
           { 5,3,0, 6,6,6 },
148
           { 1,2,4, 6,6,6 },
149
           { 5,2,1, 6,6,6 },
150
           { 4,3,1, 6,6,6 },
151
           { 1,3,5, 6,6,6 },
152

    
153
           { 0 , 6,6,6,6,6 },
154
           { 0 , 6,6,6,6,6 },
155
           { 0 , 6,6,6,6,6 },
156
           { 0 , 6,6,6,6,6 },
157

    
158
           { 1 , 6,6,6,6,6 },
159
           { 1 , 6,6,6,6,6 },
160
           { 1 , 6,6,6,6,6 },
161
           { 1 , 6,6,6,6,6 },
162

    
163
           { 2 , 6,6,6,6,6 },
164
           { 2 , 6,6,6,6,6 },
165
           { 2 , 6,6,6,6,6 },
166
           { 2 , 6,6,6,6,6 },
167

    
168
           { 3 , 6,6,6,6,6 },
169
           { 3 , 6,6,6,6,6 },
170
           { 3 , 6,6,6,6,6 },
171
           { 3 , 6,6,6,6,6 },
172

    
173
           { 4 , 6,6,6,6,6 },
174
           { 4 , 6,6,6,6,6 },
175
           { 4 , 6,6,6,6,6 },
176
           { 4 , 6,6,6,6,6 },
177

    
178
           { 5 , 6,6,6,6,6 },
179
           { 5 , 6,6,6,6,6 },
180
           { 5 , 6,6,6,6,6 },
181
           { 5 , 6,6,6,6,6 },
182
         };
183

    
184
  private static final int[] QUAT_INDICES =
185
      { 0,13,14,1,12,2,3,7,20,6,13,17,7,23,18,12,22,10,8,16,11,21,19,9,3,15,14,0,5,2,1,4 };
186

    
187
  private static final double[][] VERTICES_CORNER = new double[][]
188
          {
189
            {-0.50f, 0.00f, 0.00f},
190
            { 0.00f,-0.50f, 0.00f},
191
            { 0.00f, 0.00f,-0.50f},
192
            {-0.25f,-0.25f,-0.25f},
193
            { 0.00f, 0.00f, 0.00f}
194
          };
195

    
196
  private static final int[][] VERT_INDEXES_CORNER = new int[][]
197
          {
198
            {0,1,4},
199
            {2,0,4},
200
            {1,2,4},
201
            {3,1,0},
202
            {3,2,1},
203
            {3,0,2}
204
          };
205

    
206
  private static final float E = 0.1666666f;
207

    
208
  private static final double[][] VERTICES_FACE = new double[][]
209
          {
210
            { 0.00f +E, 0.00f +E, 0.00f },
211
            { 0.50f +E, 0.00f +E, 0.00f },
212
            { 0.00f +E, 0.50f +E, 0.00f },
213
            { 0.25f +E, 0.25f +E,-0.25f },
214
          };
215

    
216
  private static final int[][] VERT_INDEXES_FACE = new int[][]
217
          {
218
            { 0,1,2 },
219
            { 2,1,3 },
220
            { 0,1,3 },
221
            { 2,0,3 }
222
          };
223

    
224
  private static final float[][] STICKERS = new float[][]
225
          {
226
            { -0.5f, 0.25f, 0.25f, -0.5f, 0.25f, 0.25f }
227
          };
228

    
229
  private static MeshBase[] mMeshes;
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

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

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  double[][] getVertices(int cubitType)
242
    {
243
    if( cubitType==0 ) return VERTICES_CORNER;
244
    if( cubitType==1 ) return VERTICES_FACE;
245
    return null;
246
    }
247

    
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

    
250
  int[][] getVertIndexes(int cubitType)
251
    {
252
    if( cubitType==0 ) return VERT_INDEXES_CORNER;
253
    if( cubitType==1 ) return VERT_INDEXES_FACE;
254
    return null;
255
    }
256

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

    
259
  int getNumCubitTypes(int numLayers)
260
    {
261
    return 2;
262
    }
263

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

    
266
  float getScreenRatio()
267
    {
268
    return 1.6f;
269
    }
270

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

    
273
  Static4D[] getQuats()
274
    {
275
    return QUATS;
276
    }
277

    
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279

    
280
  boolean shouldResetTextureMaps()
281
    {
282
    return false;
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

    
287
  int getNumFaces()
288
    {
289
    return FACE_COLORS.length;
290
    }
291

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

    
294
  int getNumStickerTypes(int numLayers)
295
    {
296
    return 1;
297
    }
298

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

    
301
  float[] getCuts(int size)
302
    {
303
    float[] cuts = new float[2];
304

    
305
    cuts[0] = -SQ2/4;
306
    cuts[1] = +SQ2/4;
307

    
308
    return cuts;
309
    }
310

    
311
///////////////////////////////////////////////////////////////////////////////////////////////////
312

    
313
  int getNumCubitFaces()
314
    {
315
    return FACES_PER_CUBIT;
316
    }
317

    
318
///////////////////////////////////////////////////////////////////////////////////////////////////
319

    
320
  float[][] getCubitPositions(int size)
321
    {
322
    return CENTERS;
323
    }
324

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

    
327
  MeshBase createCubitMesh(int cubit, int numLayers)
328
    {
329
    if( mMeshes==null )
330
      {
331
      FactoryCubit factory = FactoryCubit.getInstance();
332
      factory.clear();
333
      mMeshes = new MeshBase[2];
334
      }
335

    
336
    MeshBase mesh;
337

    
338
    if( cubit<8 )
339
      {
340
      if( mMeshes[0]==null )
341
        {
342
        float[][] bands= new float[][]
343
          {
344
             {0.028f,35,0.16f,0.7f,7,3,3},
345
             {0.000f, 0,1.00f,0.0f,3,1,5}
346
          };
347
        int[] bandIndexes   = new int[] { 0,0,0,1,1,1 };
348
        float[][] corners   = new float[][] { {0.08f,0.15f}, {0.08f,0.20f} };
349
        int[] cornerIndexes = new int[] { 1,1,1,0,0 };
350
        float[][] centers   = new float[][] { {-0.25f, -0.25f, -0.25f} };
351
        int[] centerIndexes = new int[] { 0,0,0,-1,0 };
352

    
353
        FactoryCubit factory = FactoryCubit.getInstance();
354
        factory.createNewFaceTransform(VERTICES_CORNER,VERT_INDEXES_CORNER);
355
        mMeshes[0] = factory.createRoundedSolid(VERTICES_CORNER, VERT_INDEXES_CORNER,
356
                                                bands, bandIndexes,
357
                                                corners, cornerIndexes,
358
                                                centers, centerIndexes,
359
                                                getNumCubitFaces() );
360
        }
361
      mesh = mMeshes[0].copy(true);
362
      }
363
    else
364
      {
365
      if( mMeshes[1]==null ) mMeshes[1] = FactoryCubit.getInstance().createHelicopterFaceMesh();
366
        /*
367
        {
368
        float[][] bands= new float[][]
369
          {
370
             {0.028f,35,0.16f,0.7f,7,3,3},
371
             {0.000f, 0,1.00f,0.0f,3,1,3}
372
          };
373
        int[] bandIndexes   = new int[] { 0,1,1,1 };
374
        float[][] corners   = new float[][] { {0.06f,0.15f}, {0.06f,0.20f} };
375
        int[] cornerIndexes = new int[] { 0,1,1,-1 };
376
        float[][] centers   = new float[][] { {-1.0f/12, -1.0f/12, -1.0f/4} };
377
        int[] centerIndexes = new int[] { 0,0,0,-1 };
378

    
379
        FactoryCubit factory = FactoryCubit.getInstance();
380
        factory.createNewFaceTransform(VERTICES_FACE,VERT_INDEXES_FACE);
381
        mMeshes[1] = factory.createRoundedSolid(VERTICES_FACE, VERT_INDEXES_FACE,
382
                                                bands, bandIndexes,
383
                                                corners, cornerIndexes,
384
                                                centers, centerIndexes,
385
                                                getNumCubitFaces() );
386
        }
387

    
388
         */
389
      mesh = mMeshes[1].copy(true);
390
      }
391

    
392
    int index = QUAT_INDICES[cubit];
393
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[index], new Static3D(0,0,0) );
394
    mesh.apply(quat,0xffffffff,0);
395

    
396
    return mesh;
397
    }
398

    
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400

    
401
  int getFaceColor(int cubit, int cubitface, int size)
402
    {
403
    return mFaceMap[cubit][cubitface];
404
    }
405

    
406
///////////////////////////////////////////////////////////////////////////////////////////////////
407

    
408
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
409
    {
410
    float R = 0.023f;
411
    float S = 0.035f;
412
    float E = 0.5f;
413
    float[] vertices = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
414

    
415
    FactorySticker factory = FactorySticker.getInstance();
416
    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face], R);
417
    }
418

    
419
///////////////////////////////////////////////////////////////////////////////////////////////////
420

    
421
  float returnMultiplier()
422
    {
423
    return 2.0f;
424
    }
425

    
426
///////////////////////////////////////////////////////////////////////////////////////////////////
427

    
428
  float[] getRowChances(int numLayers)
429
    {
430
    float[] chances = new float[3];
431

    
432
    chances[0] = 0.5f;
433
    chances[1] = 0.5f;
434
    chances[2] = 1.0f;
435

    
436
    return chances;
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440
// PUBLIC API
441

    
442
  public Static3D[] getRotationAxis()
443
    {
444
    return ROT_AXIS;
445
    }
446

    
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448

    
449
  public int getBasicAngle()
450
    {
451
    return 2;
452
    }
453

    
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455

    
456
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
457
    {
458
    if( num==0 )
459
      {
460
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
461
      }
462
    else
463
      {
464
      int newVector = rnd.nextInt(ROTATION_AXIS.length-2);
465

    
466
      switch(scramble[num-1][0])
467
        {
468
        case  0:
469
        case  1: scramble[num][0] = newVector+2;
470
                 break;
471
        case  2:
472
        case  3: scramble[num][0] = (newVector==0 || newVector==1) ? newVector:newVector+2;
473
                 break;
474
        default: scramble[num][0] = newVector;
475
                 break;
476
        }
477
      }
478

    
479
    float rowFloat = rnd.nextFloat();
480

    
481
    for(int row=0; row<mRowChances.length; row++)
482
      {
483
      if( rowFloat<=mRowChances[row] )
484
        {
485
        scramble[num][1] = row;
486
        break;
487
        }
488
      }
489

    
490
    switch( rnd.nextInt(2) )
491
      {
492
      case 0: scramble[num][2] = -1; break;
493
      case 1: scramble[num][2] =  1; break;
494
      }
495
    }
496

    
497
///////////////////////////////////////////////////////////////////////////////////////////////////
498
// The Helicopter is solved if and only if:
499
//
500
// 1) all of its corner cubits are rotated with the same quat
501
// 2) all its face cubits are rotated with the same quat like the corner ones,
502
//    and optionally they also might be turned by a multiple of 90 degrees along
503
//    a vector perpendicular to the face they lie on.
504
//
505
// i.e.
506
// cubits  8, 9,10,11,12,13,14,15 - might be extra QUAT 1,8,9
507
// cubits 16,17,18,19,20,21,22,23 - might be extra QUAT 2,12,13
508
// cubits 24,25,26,27,28,29,30,31 - might be extra QUAT 3,14,15
509

    
510
  public boolean isSolved()
511
    {
512
    int q = CUBITS[0].mQuatIndex;
513

    
514
    if ( CUBITS[1].mQuatIndex == q &&
515
         CUBITS[2].mQuatIndex == q &&
516
         CUBITS[3].mQuatIndex == q &&
517
         CUBITS[4].mQuatIndex == q &&
518
         CUBITS[5].mQuatIndex == q &&
519
         CUBITS[6].mQuatIndex == q &&
520
         CUBITS[7].mQuatIndex == q  )
521
      {
522
      int q1 = mulQuat(q,1);
523
      int q2 = mulQuat(q,8);
524
      int q3 = mulQuat(q,9);
525

    
526
      for(int index=8; index<16; index++)
527
        {
528
        int qIndex = CUBITS[index].mQuatIndex;
529
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
530
        }
531

    
532
      q1 = mulQuat(q, 2);
533
      q2 = mulQuat(q,12);
534
      q3 = mulQuat(q,13);
535

    
536
      for(int index=16; index<24; index++)
537
        {
538
        int qIndex = CUBITS[index].mQuatIndex;
539
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
540
        }
541

    
542
      q1 = mulQuat(q, 3);
543
      q2 = mulQuat(q,14);
544
      q3 = mulQuat(q,15);
545

    
546
      for(int index=24; index<32; index++)
547
        {
548
        int qIndex = CUBITS[index].mQuatIndex;
549
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
550
        }
551

    
552
      return true;
553
      }
554

    
555
    return false;
556
    }
557

    
558
///////////////////////////////////////////////////////////////////////////////////////////////////
559
// only needed for solvers - there are no Helicopter solvers ATM)
560

    
561
  public String retObjectString()
562
    {
563
    return "";
564
    }
565

    
566
///////////////////////////////////////////////////////////////////////////////////////////////////
567

    
568
  public int getObjectName(int numLayers)
569
    {
570
    return R.string.heli3;
571
    }
572

    
573
///////////////////////////////////////////////////////////////////////////////////////////////////
574

    
575
  public int getInventor(int numLayers)
576
    {
577
    return R.string.heli3_inventor;
578
    }
579

    
580
///////////////////////////////////////////////////////////////////////////////////////////////////
581

    
582
  public int getComplexity(int numLayers)
583
    {
584
    return 8;
585
    }
586
}
(24-24/33)