Project

General

Profile

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

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

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

    
24
import org.distorted.helpers.ObjectShape;
25
import org.distorted.helpers.ObjectSticker;
26
import org.distorted.library.main.DistortedEffects;
27
import org.distorted.library.main.DistortedTexture;
28
import org.distorted.library.mesh.MeshSquare;
29
import org.distorted.library.type.Static3D;
30
import org.distorted.library.type.Static4D;
31
import org.distorted.main.R;
32

    
33
import java.util.Random;
34

    
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36

    
37
public class TwistyHelicopter extends TwistyObject
38
{
39
  private static final int FACES_PER_CUBIT =6;
40

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

    
52
  private static final int[] BASIC_ANGLE = new int[] { 2,2,2,2,2,2 };
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 HELICOPTER (same as the Cube!)
62
  private static final Static4D[] QUATS = new Static4D[]
63
         {
64
           new Static4D( 0.00f,  0.00f,  0.00f,  1.00f ),
65
           new Static4D( 1.00f,  0.00f,  0.00f,  0.00f ),
66
           new Static4D( 0.00f,  1.00f,  0.00f,  0.00f ),
67
           new Static4D( 0.00f,  0.00f,  1.00f,  0.00f ),
68

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

    
82
           new Static4D( 0.50f,  0.50f,  0.50f,  0.50f ),
83
           new Static4D( 0.50f,  0.50f,  0.50f, -0.50f ),
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
         };
91

    
92
  private static final float DIST_CORNER = 0.50f;
93
  private static final float DIST_CENTER = 0.50f;
94
  private static final float XY_CENTER   = DIST_CORNER/3;
95

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

    
108
             {   DIST_CENTER,     XY_CENTER,     XY_CENTER },
109
             {   DIST_CENTER,     XY_CENTER,    -XY_CENTER },
110
             {   DIST_CENTER,    -XY_CENTER,     XY_CENTER },
111
             {   DIST_CENTER,    -XY_CENTER,    -XY_CENTER },
112

    
113
             {  -DIST_CENTER,     XY_CENTER,     XY_CENTER },
114
             {  -DIST_CENTER,     XY_CENTER,    -XY_CENTER },
115
             {  -DIST_CENTER,    -XY_CENTER,     XY_CENTER },
116
             {  -DIST_CENTER,    -XY_CENTER,    -XY_CENTER },
117

    
118
             {   XY_CENTER  ,   DIST_CENTER,     XY_CENTER },
119
             {   XY_CENTER  ,   DIST_CENTER,    -XY_CENTER },
120
             {  -XY_CENTER  ,   DIST_CENTER,     XY_CENTER },
121
             {  -XY_CENTER  ,   DIST_CENTER,    -XY_CENTER },
122

    
123
             {   XY_CENTER  ,  -DIST_CENTER,     XY_CENTER },
124
             {   XY_CENTER  ,  -DIST_CENTER,    -XY_CENTER },
125
             {  -XY_CENTER  ,  -DIST_CENTER,     XY_CENTER },
126
             {  -XY_CENTER  ,  -DIST_CENTER,    -XY_CENTER },
127

    
128
             {   XY_CENTER  ,     XY_CENTER,   DIST_CENTER },
129
             {   XY_CENTER  ,    -XY_CENTER,   DIST_CENTER },
130
             {  -XY_CENTER  ,     XY_CENTER,   DIST_CENTER },
131
             {  -XY_CENTER  ,    -XY_CENTER,   DIST_CENTER },
132

    
133
             {   XY_CENTER  ,     XY_CENTER,  -DIST_CENTER },
134
             {   XY_CENTER  ,    -XY_CENTER,  -DIST_CENTER },
135
             {  -XY_CENTER  ,     XY_CENTER,  -DIST_CENTER },
136
             {  -XY_CENTER  ,    -XY_CENTER,  -DIST_CENTER },
137
         };
138

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

    
151
           { 0 , 6,6,6,6,6 },
152
           { 0 , 6,6,6,6,6 },
153
           { 0 , 6,6,6,6,6 },
154
           { 0 , 6,6,6,6,6 },
155

    
156
           { 1 , 6,6,6,6,6 },
157
           { 1 , 6,6,6,6,6 },
158
           { 1 , 6,6,6,6,6 },
159
           { 1 , 6,6,6,6,6 },
160

    
161
           { 2 , 6,6,6,6,6 },
162
           { 2 , 6,6,6,6,6 },
163
           { 2 , 6,6,6,6,6 },
164
           { 2 , 6,6,6,6,6 },
165

    
166
           { 3 , 6,6,6,6,6 },
167
           { 3 , 6,6,6,6,6 },
168
           { 3 , 6,6,6,6,6 },
169
           { 3 , 6,6,6,6,6 },
170

    
171
           { 4 , 6,6,6,6,6 },
172
           { 4 , 6,6,6,6,6 },
173
           { 4 , 6,6,6,6,6 },
174
           { 4 , 6,6,6,6,6 },
175

    
176
           { 5 , 6,6,6,6,6 },
177
           { 5 , 6,6,6,6,6 },
178
           { 5 , 6,6,6,6,6 },
179
           { 5 , 6,6,6,6,6 },
180
         };
181

    
182
  private static final int[] QUAT_INDICES =
183
      { 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 };
184

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

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

    
204
  private static final float E = 0.1666666f;
205

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

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

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

    
227
  private static final ObjectSticker[] mStickers;
228

    
229
  static
230
    {
231
    float radius = 0.03f;
232
    float stroke = 0.05f;
233
    float[] radii = new float[] {radius,radius,radius};
234
    mStickers = new ObjectSticker[STICKERS.length];
235
    mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke);
236
    }
237

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239

    
240
  TwistyHelicopter(int size, Static4D quat, DistortedTexture texture,
241
                   MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
242
    {
243
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.HELI, res, scrWidth);
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247

    
248
  float getScreenRatio()
249
    {
250
    return 1.6f;
251
    }
252

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

    
255
  Static4D[] getQuats()
256
    {
257
    return QUATS;
258
    }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261

    
262
  boolean shouldResetTextureMaps()
263
    {
264
    return false;
265
    }
266

    
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268

    
269
  int getNumFaces()
270
    {
271
    return FACE_COLORS.length;
272
    }
273

    
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275

    
276
  int getNumStickerTypes(int numLayers)
277
    {
278
    return STICKERS.length;
279
    }
280

    
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

    
283
  float[][] getCuts(int size)
284
    {
285
    float[] cut = new float[] { -SQ2/4, +SQ2/4 };
286
    return new float[][] { cut,cut,cut,cut,cut,cut };
287
    }
288

    
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290

    
291
  int getNumCubitFaces()
292
    {
293
    return FACES_PER_CUBIT;
294
    }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297

    
298
  float[][] getCubitPositions(int size)
299
    {
300
    return CENTERS;
301
    }
302

    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304

    
305
  ObjectShape getObjectShape(int cubit, int numLayers)
306
    {
307
    int variant = getCubitVariant(cubit,numLayers);
308

    
309
    if( variant==0 )
310
      {
311
      float[][] bands     = new float[][] { {0.028f,35,0.16f,0.7f,7,3,3}, {0.000f, 0,1.00f,0.0f,3,1,5} };
312
      int[] bandIndices   = new int[] { 0,0,0,1,1,1 };
313
      float[][] corners   = new float[][] { {0.08f,0.15f}, {0.08f,0.20f} };
314
      int[] cornerIndices = new int[] { 1,1,1,0,0 };
315
      float[][] centers   = new float[][] { {-0.25f, -0.25f, -0.25f} };
316
      int[] centerIndices = new int[] { 0,0,0,-1,0 };
317
      return new ObjectShape(VERTICES_CORNER,VERT_INDEXES_CORNER,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
318
      }
319
    else
320
      {
321
      float[][] bands     = new float[][] { {0.028f,35,0.16f,0.7f,7,3,3}, {0.000f, 0,1.00f,0.0f,3,1,3} };
322
      int[] bandIndices   = new int[] { 0,1,1,1 };
323
      float[][] corners   = new float[][] { {0.06f,0.15f}, {0.06f,0.20f} };
324
      int[] cornerIndices = new int[] { 0,1,1,-1 };
325
      float[][] centers   = new float[][] { {-1.0f/12, -1.0f/12, -1.0f/4} };
326
      int[] centerIndices = new int[] { 0,0,0,-1 };
327
      return new ObjectShape(VERTICES_FACE,VERT_INDEXES_FACE,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
328
      }
329
    }
330

    
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332

    
333
  Static4D getQuat(int cubit, int numLayers)
334
    {
335
    return QUATS[QUAT_INDICES[cubit]];
336
    }
337

    
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339

    
340
  int getNumCubitVariants(int numLayers)
341
    {
342
    return 2;
343
    }
344

    
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346

    
347
  int getCubitVariant(int cubit, int numLayers)
348
    {
349
    return cubit<8 ? 0:1;
350
    }
351

    
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353

    
354
  int getFaceColor(int cubit, int cubitface, int size)
355
    {
356
    return mFaceMap[cubit][cubitface];
357
    }
358

    
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

    
361
  int getColor(int face)
362
    {
363
    return FACE_COLORS[face];
364
    }
365

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

    
368
  ObjectSticker retSticker(int face)
369
    {
370
    return mStickers[face/NUM_FACES];
371
    }
372

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

    
375
  float returnMultiplier()
376
    {
377
    return 2.0f;
378
    }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381
// PUBLIC API
382

    
383
  public Static3D[] getRotationAxis()
384
    {
385
    return ROT_AXIS;
386
    }
387

    
388
///////////////////////////////////////////////////////////////////////////////////////////////////
389

    
390
  public int[] getBasicAngle()
391
    {
392
    return BASIC_ANGLE;
393
    }
394

    
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396

    
397
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
398
    {
399
    if( curr==0 )
400
      {
401
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
402
      }
403
    else
404
      {
405
      int newVector = rnd.nextInt(NUM_AXIS -2);
406

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

    
420
    scramble[curr][1] = rnd.nextFloat()<=0.5f ? 0 : 2;
421

    
422
    switch( rnd.nextInt(2) )
423
      {
424
      case 0: scramble[curr][2] = -1; break;
425
      case 1: scramble[curr][2] =  1; break;
426
      }
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430
// The Helicopter is solved if and only if:
431
//
432
// 1) all of its corner cubits are rotated with the same quat
433
// 2) all its face cubits are rotated with the same quat like the corner ones,
434
//    and optionally they also might be turned by a multiple of 90 degrees along
435
//    a vector perpendicular to the face they lie on.
436
//
437
// i.e.
438
// cubits  8, 9,10,11,12,13,14,15 - might be extra QUAT 1,8,9
439
// cubits 16,17,18,19,20,21,22,23 - might be extra QUAT 2,12,13
440
// cubits 24,25,26,27,28,29,30,31 - might be extra QUAT 3,14,15
441

    
442
  public boolean isSolved()
443
    {
444
    int q = CUBITS[0].mQuatIndex;
445

    
446
    if ( CUBITS[1].mQuatIndex == q &&
447
         CUBITS[2].mQuatIndex == q &&
448
         CUBITS[3].mQuatIndex == q &&
449
         CUBITS[4].mQuatIndex == q &&
450
         CUBITS[5].mQuatIndex == q &&
451
         CUBITS[6].mQuatIndex == q &&
452
         CUBITS[7].mQuatIndex == q  )
453
      {
454
      int q1 = mulQuat(q,1);
455
      int q2 = mulQuat(q,8);
456
      int q3 = mulQuat(q,9);
457

    
458
      for(int index=8; index<16; index++)
459
        {
460
        int qIndex = CUBITS[index].mQuatIndex;
461
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
462
        }
463

    
464
      q1 = mulQuat(q, 2);
465
      q2 = mulQuat(q,12);
466
      q3 = mulQuat(q,13);
467

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

    
474
      q1 = mulQuat(q, 3);
475
      q2 = mulQuat(q,14);
476
      q3 = mulQuat(q,15);
477

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

    
484
      return true;
485
      }
486

    
487
    return false;
488
    }
489

    
490
///////////////////////////////////////////////////////////////////////////////////////////////////
491

    
492
  public int getObjectName(int numLayers)
493
    {
494
    return R.string.heli3;
495
    }
496

    
497
///////////////////////////////////////////////////////////////////////////////////////////////////
498

    
499
  public int getInventor(int numLayers)
500
    {
501
    return R.string.heli3_inventor;
502
    }
503

    
504
///////////////////////////////////////////////////////////////////////////////////////////////////
505

    
506
  public int getComplexity(int numLayers)
507
    {
508
    return 8;
509
    }
510
}
(27-27/41)