Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyHelicopter.java @ cb137f36

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
import org.distorted.main.RubikSurfaceView;
37

    
38
import java.util.Random;
39

    
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41

    
42
public class TwistyHelicopter extends TwistyObject
43
{
44
  private static final int FACES_PER_CUBIT =6;
45

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

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

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

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

    
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
           new Static4D( 0.50f, -0.50f, -0.50f, -0.50f )
93
         };
94

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

    
99
  // centers of the 8 corners + 6*4 face triangles ( i.e. of the all 32 cubits)
100
  private static final float[][] CENTERS = new float[][]
101
         {
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
             {  -DIST_CORNER,  -DIST_CORNER,  -DIST_CORNER },
110

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

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

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

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

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

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

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

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

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

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

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

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

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

    
185
  private static final int[] QUAT_INDICES =
186
      { 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 };
187

    
188
  private final double[][] VERTICES_CORNER = new double[][]
189
          {
190
            // TODO
191
          };
192

    
193
  private final int[][] VERT_INDEXES_CORNER = new int[][]
194
          {
195
            // TODO
196
          };
197

    
198
  private final double[][] VERTICES_FACE = new double[][]
199
          {
200
            // TODO
201
          };
202

    
203
  private final int[][] VERT_INDEXES_FACE = new int[][]
204
          {
205
            // TODO
206
          };
207

    
208
  private static MeshBase mCornerMesh, mFaceMesh;
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

    
212
  TwistyHelicopter(int size, Static4D quat, DistortedTexture texture,
213
                   MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
214
    {
215
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.HELI, res, scrWidth);
216
    }
217

    
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219

    
220
  double[][] getVertices(int cubitType)
221
    {
222
     if( cubitType==0 )  // Corner
223
      {
224
      return VERTICES_CORNER;
225
      }
226
    if( cubitType==1 )  // Face
227
      {
228
      return VERTICES_FACE;
229
      }
230

    
231
    return null;
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
  int[][] getVertIndexes(int cubitType)
237
    {
238
    if( cubitType==0 )  // Corner
239
      {
240
      return VERT_INDEXES_CORNER;
241
      }
242
    if( cubitType==1 )  // Face
243
      {
244
      return VERT_INDEXES_FACE;
245
      }
246

    
247
    return null;
248
    }
249

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

    
252
  int getNumCubitTypes(int numLayers)
253
    {
254
    return 1;
255
    }
256

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

    
259
  float getScreenRatio()
260
    {
261
    return 1.6f;
262
    }
263

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

    
266
  Static4D[] getQuats()
267
    {
268
    return QUATS;
269
    }
270

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

    
273
  boolean shouldResetTextureMaps()
274
    {
275
    return false;
276
    }
277

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

    
280
  int getNumFaces()
281
    {
282
    return FACE_COLORS.length;
283
    }
284

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

    
287
  int getNumStickerTypes(int numLayers)
288
    {
289
    return 1;
290
    }
291

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

    
294
  float[] getCuts(int size)
295
    {
296
    float[] cuts = new float[2];
297

    
298
    cuts[0] = -SQ2/4;
299
    cuts[1] = +SQ2/4;
300

    
301
    return cuts;
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  int getNumCubitFaces()
307
    {
308
    return FACES_PER_CUBIT;
309
    }
310

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

    
313
  float[][] getCubitPositions(int size)
314
    {
315
    return CENTERS;
316
    }
317

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

    
320
  MeshBase createCubitMesh(int cubit, int numLayers)
321
    {
322
    MeshBase mesh;
323

    
324
    if( cubit<8 )
325
      {
326
      if( mCornerMesh==null ) mCornerMesh = FactoryCubit.getInstance().createHelicopterCornerMesh();
327
      mesh = mCornerMesh.copy(true);
328
      }
329
    else
330
      {
331
      if( mFaceMesh==null ) mFaceMesh = FactoryCubit.getInstance().createHelicopterFaceMesh();
332
      mesh = mFaceMesh.copy(true);
333
      }
334

    
335
    int index = QUAT_INDICES[cubit];
336
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[index], new Static3D(0,0,0) );
337
    mesh.apply(quat,0xffffffff,0);
338

    
339
    return mesh;
340
    }
341

    
342
///////////////////////////////////////////////////////////////////////////////////////////////////
343

    
344
  int getFaceColor(int cubit, int cubitface, int size)
345
    {
346
    return mFaceMap[cubit][cubitface];
347
    }
348

    
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350

    
351
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
352
    {
353
    float R = 0.023f;
354
    float S = 0.035f;
355
    float E = 0.5f;
356
    float[] vertices = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
357

    
358
    FactorySticker factory = FactorySticker.getInstance();
359
    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face], R);
360
    }
361

    
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

    
364
  float returnMultiplier()
365
    {
366
    return 2.0f;
367
    }
368

    
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370

    
371
  float[] getRowChances(int numLayers)
372
    {
373
    float[] chances = new float[3];
374

    
375
    chances[0] = 0.5f;
376
    chances[1] = 0.5f;
377
    chances[2] = 1.0f;
378

    
379
    return chances;
380
    }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383
// PUBLIC API
384

    
385
  public Static3D[] getRotationAxis()
386
    {
387
    return ROT_AXIS;
388
    }
389

    
390
///////////////////////////////////////////////////////////////////////////////////////////////////
391

    
392
  public int getBasicAngle()
393
    {
394
    return 2;
395
    }
396

    
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398

    
399
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
400
    {
401
    if( num==0 )
402
      {
403
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
404
      }
405
    else
406
      {
407
      int newVector = rnd.nextInt(ROTATION_AXIS.length-2);
408

    
409
      switch(scramble[num-1][0])
410
        {
411
        case  0:
412
        case  1: scramble[num][0] = newVector+2;
413
                 break;
414
        case  2:
415
        case  3: scramble[num][0] = (newVector==0 || newVector==1) ? newVector:newVector+2;
416
                 break;
417
        default: scramble[num][0] = newVector;
418
                 break;
419
        }
420
      }
421

    
422
    float rowFloat = rnd.nextFloat();
423

    
424
    for(int row=0; row<mRowChances.length; row++)
425
      {
426
      if( rowFloat<=mRowChances[row] )
427
        {
428
        scramble[num][1] = row;
429
        break;
430
        }
431
      }
432

    
433
    switch( rnd.nextInt(2) )
434
      {
435
      case 0: scramble[num][2] = -1; break;
436
      case 1: scramble[num][2] =  1; break;
437
      }
438
    }
439

    
440
///////////////////////////////////////////////////////////////////////////////////////////////////
441
// The Helicopter is solved if and only if:
442
//
443
// 1) all of its corner cubits are rotated with the same quat
444
// 2) all its face cubits are rotated with the same quat like the corner ones,
445
//    and optionally they also might be turned by a multiple of 90 degrees along
446
//    a vector perpendicular to the face they lie on.
447
//
448
// i.e.
449
// cubits  8, 9,10,11,12,13,14,15 - might be extra QUAT 1,8,9
450
// cubits 16,17,18,19,20,21,22,23 - might be extra QUAT 2,12,13
451
// cubits 24,25,26,27,28,29,30,31 - might be extra QUAT 3,14,15
452

    
453
  public boolean isSolved()
454
    {
455
    int q = CUBITS[0].mQuatIndex;
456

    
457
    if ( CUBITS[1].mQuatIndex == q &&
458
         CUBITS[2].mQuatIndex == q &&
459
         CUBITS[3].mQuatIndex == q &&
460
         CUBITS[4].mQuatIndex == q &&
461
         CUBITS[5].mQuatIndex == q &&
462
         CUBITS[6].mQuatIndex == q &&
463
         CUBITS[7].mQuatIndex == q  )
464
      {
465
      int q1 = mulQuat(q,1);
466
      int q2 = mulQuat(q,8);
467
      int q3 = mulQuat(q,9);
468

    
469
      for(int index=8; index<16; index++)
470
        {
471
        int qIndex = CUBITS[index].mQuatIndex;
472
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
473
        }
474

    
475
      q1 = mulQuat(q, 2);
476
      q2 = mulQuat(q,12);
477
      q3 = mulQuat(q,13);
478

    
479
      for(int index=16; index<24; index++)
480
        {
481
        int qIndex = CUBITS[index].mQuatIndex;
482
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
483
        }
484

    
485
      q1 = mulQuat(q, 3);
486
      q2 = mulQuat(q,14);
487
      q3 = mulQuat(q,15);
488

    
489
      for(int index=24; index<32; index++)
490
        {
491
        int qIndex = CUBITS[index].mQuatIndex;
492
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
493
        }
494

    
495
      return true;
496
      }
497

    
498
    return false;
499
    }
500

    
501
///////////////////////////////////////////////////////////////////////////////////////////////////
502
// only needed for solvers - there are no Helicopter solvers ATM)
503

    
504
  public String retObjectString()
505
    {
506
    return "";
507
    }
508

    
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510

    
511
  public int getObjectName(int numLayers)
512
    {
513
    return R.string.heli3;
514
    }
515

    
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517

    
518
  public int getInventor(int numLayers)
519
    {
520
    return R.string.heli3_inventor;
521
    }
522

    
523
///////////////////////////////////////////////////////////////////////////////////////////////////
524

    
525
  public int getComplexity(int numLayers)
526
    {
527
    return 8;
528
    }
529
}
(24-24/33)