Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyIvy.java @ 46e6b3f6

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.FactoryCubit;
25
import org.distorted.helpers.ObjectSticker;
26
import org.distorted.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.main.DistortedEffects;
28
import org.distorted.library.main.DistortedTexture;
29
import org.distorted.library.mesh.MeshBase;
30
import org.distorted.library.mesh.MeshSquare;
31
import org.distorted.library.type.Static3D;
32
import org.distorted.library.type.Static4D;
33
import org.distorted.main.R;
34

    
35
import java.util.Random;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

    
39
public class TwistyIvy extends TwistyObject
40
{
41
  public static final float IVY_D = 0.003f;
42
  private static final int  IVY_N = 8;
43

    
44
  private static final int FACES_PER_CUBIT =6;
45

    
46
  // the four rotation axis of a RubikIvy. Must be normalized.
47
  static final Static3D[] ROT_AXIS = new Static3D[]
48
         {
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
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
53
         };
54

    
55
  private static final int[] BASIC_ANGLE = new int[] { 3,3,3,3 };
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 RubikIvy
65
  private static final Static4D[] QUATS = new Static4D[]
66
         {
67
           new Static4D(  0.0f,  0.0f,  0.0f,  1.0f ),
68
           new Static4D(  1.0f,  0.0f,  0.0f,  0.0f ),
69
           new Static4D(  0.0f,  1.0f,  0.0f,  0.0f ),
70
           new Static4D(  0.0f,  0.0f,  1.0f,  0.0f ),
71

    
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
           new Static4D(  0.5f, -0.5f,  0.5f, -0.5f ),
78
           new Static4D(  0.5f, -0.5f, -0.5f,  0.5f ),
79
           new Static4D(  0.5f, -0.5f, -0.5f, -0.5f )
80
         };
81

    
82
  private static final int[][] mFaceMap =
83
         {
84
           {  4, 0, 2, 12,12,12 },
85
           {  5, 1, 2, 12,12,12 },
86
           {  4, 1, 3, 12,12,12 },
87
           {  5, 0, 3, 12,12,12 },
88

    
89
           {  6, 12,12,12,12,12 },
90
           {  7, 12,12,12,12,12 },
91
           {  8, 12,12,12,12,12 },
92
           {  9, 12,12,12,12,12 },
93
           { 10, 12,12,12,12,12 },
94
           { 11, 12,12,12,12,12 },
95
         };
96

    
97
  private static MeshBase mCornerMesh, mFaceMesh;
98

    
99
  private static final ObjectSticker[] mStickers;
100

    
101
  private static final float[][] STICKERS = new float[][]
102
          {
103
             { 0.29258922f, -0.5f, 0.29258922f, 0.29258922f, -0.5f, 0.29258922f },
104
             { -0.5f, 0.5f, 0.5f, -0.5f }
105
          };
106
  private static final int NUM_STICKERS = STICKERS.length;
107

    
108
  static
109
    {
110
    mStickers = new ObjectSticker[NUM_STICKERS];
111

    
112
    float D = (float)(Math.PI/4);
113
    final float[][] angles = { { 0,0,D },{ D,D } };
114
    final float[][] radii  = { { 0,0.02f,0 },{ 0.06f,0.06f } };
115
    final float[] strokes = { 0.03f, 0.08f };
116

    
117
    for(int s=0; s<NUM_STICKERS; s++)
118
      {
119
      mStickers[s] = new ObjectSticker(STICKERS[s], angles[s],radii[s],strokes[s]);
120
      }
121
    }
122

    
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124

    
125
  TwistyIvy(int size, Static4D quat, DistortedTexture texture,
126
            MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
127
    {
128
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.IVY, res, scrWidth);
129
    }
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
  float getScreenRatio()
134
    {
135
    return 1.0f;
136
    }
137

    
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139

    
140
  Static4D[] getQuats()
141
    {
142
    return QUATS;
143
    }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
  int getNumFaces()
148
    {
149
    return FACE_COLORS.length;
150
    }
151

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153

    
154
  boolean shouldResetTextureMaps()
155
    {
156
    return false;
157
    }
158

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160

    
161
  int getNumStickerTypes(int numLayers)
162
    {
163
    return NUM_STICKERS;
164
    }
165

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
  float[][] getCuts(int numLayers)
169
    {
170
    float[] cut = new float[] {0.0f};
171
    return new float[][] { cut,cut,cut,cut };
172
    }
173

    
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175

    
176
  int getNumCubitFaces()
177
    {
178
    return FACES_PER_CUBIT;
179
    }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

    
183
  float[][] getCubitPositions(int numLayers)
184
    {
185
    final float DIST_CORNER = (numLayers-1)*0.50f;
186
    final float DIST_CENTER = (numLayers-1)*0.50f;
187

    
188
    final float[][] CENTERS = new float[10][];
189

    
190
    CENTERS[0] = new float[] { DIST_CORNER, DIST_CORNER, DIST_CORNER };
191
    CENTERS[1] = new float[] {-DIST_CORNER, DIST_CORNER,-DIST_CORNER };
192
    CENTERS[2] = new float[] {-DIST_CORNER,-DIST_CORNER, DIST_CORNER };
193
    CENTERS[3] = new float[] { DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
194
    CENTERS[4] = new float[] { DIST_CENTER,           0,           0 };
195
    CENTERS[5] = new float[] {-DIST_CENTER,           0,           0 };
196
    CENTERS[6] = new float[] {           0, DIST_CENTER,           0 };
197
    CENTERS[7] = new float[] {           0,-DIST_CENTER,           0 };
198
    CENTERS[8] = new float[] {           0,           0, DIST_CENTER };
199
    CENTERS[9] = new float[] {           0,           0,-DIST_CENTER };
200

    
201
    return CENTERS;
202
    }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

    
206
  private int getQuat(int cubit)
207
    {
208
    switch(cubit)
209
      {
210
      case  0: return 0;
211
      case  1: return 2;
212
      case  2: return 3;
213
      case  3: return 1;
214

    
215
      case  4: return 8;
216
      case  5: return 11;
217
      case  6: return 10;
218
      case  7: return 9;
219
      case  8: return 0;
220
      case  9: return 2;
221
      }
222

    
223
    return 0;
224
    }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227

    
228
  MeshBase createCubitMesh(int cubit, int numLayers)
229
    {
230
    MeshBase mesh;
231

    
232
    if( cubit<4 )
233
      {
234
      if( mCornerMesh==null )
235
        {
236
        final float angle = (float)Math.PI/(2*IVY_N);
237
        final float CORR  = 1.0f - 2*IVY_D;
238

    
239
        float[][] centers= new float[][] { {-0.5f,-0.5f,-0.5f} };
240
        float[][] corners= new float[][] { {0.03f,0.10f}, {0.02f,0.10f} };
241
        int[] cornerIndexes= new int[3*(IVY_N+1)+4];
242
        int[] centerIndexes= new int[3*(IVY_N+1)+4];
243
        double[][] vertices= new double[3*(IVY_N+1)+4][3];
244
        int[][] vertIndexes= new int[6][IVY_N+4];
245
        int[] bandIndexes= new int[] { 0,0,0,1,1,1 };
246

    
247
        float[][] bands =
248
          {
249
               {+0.015f,20,0.2f,0.5f,7,1,2},
250
               {-0.100f,20,0.2f,0.0f,2,1,2}
251
          };
252

    
253
        for(int i=0; i<3*(IVY_N+1); i++)
254
          {
255
          cornerIndexes[i+4] = -1;
256
          centerIndexes[i+4] = -1;
257
          }
258
        cornerIndexes[0] = 1;
259
        cornerIndexes[1] = 0;
260
        cornerIndexes[2] = 0;
261
        cornerIndexes[3] = 0;
262

    
263
        centerIndexes[0] = 0;
264
        centerIndexes[1] = 0;
265
        centerIndexes[2] = 0;
266
        centerIndexes[3] = 0;
267

    
268
        vertices[0][0] = 0.0;
269
        vertices[0][1] = 0.0;
270
        vertices[0][2] = 0.0;
271
        vertices[1][0] =-1.0;
272
        vertices[1][1] = 0.0;
273
        vertices[1][2] = 0.0;
274
        vertices[2][0] = 0.0;
275
        vertices[2][1] =-1.0;
276
        vertices[2][2] = 0.0;
277
        vertices[3][0] = 0.0;
278
        vertices[3][1] = 0.0;
279
        vertices[3][2] =-1.0;
280

    
281
        vertIndexes[0][0] = 2;
282
        vertIndexes[0][1] = 0;
283
        vertIndexes[0][2] = 1;
284
        vertIndexes[3][0] = 2;
285
        vertIndexes[3][1] = 0;
286
        vertIndexes[3][2] = 1;
287

    
288
        vertIndexes[1][0] = 3;
289
        vertIndexes[1][1] = 0;
290
        vertIndexes[1][2] = 2;
291
        vertIndexes[4][0] = 3;
292
        vertIndexes[4][1] = 0;
293
        vertIndexes[4][2] = 2;
294

    
295
        vertIndexes[2][0] = 1;
296
        vertIndexes[2][1] = 0;
297
        vertIndexes[2][2] = 3;
298
        vertIndexes[5][0] = 1;
299
        vertIndexes[5][1] = 0;
300
        vertIndexes[5][2] = 3;
301

    
302
        int N1 = 4;
303
        int N2 = N1 + IVY_N + 1;
304
        int N3 = N2 + IVY_N + 1;
305

    
306
        for(int i=0; i<=IVY_N; i++)
307
          {
308
          double cos1 = Math.cos((IVY_N-i)*angle);
309
          double sin1 = Math.sin((IVY_N-i)*angle);
310
          double cos2 = Math.cos((      i)*angle);
311
          double sin2 = Math.sin((      i)*angle);
312

    
313
          vertices[N1+i][0] = CORR*(cos1-0.5) - 0.5;
314
          vertices[N1+i][1] = CORR*(sin1-0.5) - 0.5;
315
          vertices[N1+i][2] = 0.0;
316

    
317
          vertices[N2+i][0] = 0.0;
318
          vertices[N2+i][1] = CORR*(sin2-0.5) - 0.5;
319
          vertices[N2+i][2] = CORR*(cos2-0.5) - 0.5;
320

    
321
          vertices[N3+i][0] = CORR*(cos2-0.5) - 0.5;
322
          vertices[N3+i][1] = 0.0;
323
          vertices[N3+i][2] = CORR*(sin2-0.5) - 0.5;
324

    
325
          vertIndexes[0][i+3] = N1 + i;
326
          vertIndexes[1][i+3] = N2 + i;
327
          vertIndexes[2][i+3] = N3 + i;
328
          vertIndexes[3][i+3] = N1 + i;
329
          vertIndexes[4][i+3] = N2 + i;
330
          vertIndexes[5][i+3] = N3 + i;
331
          }
332

    
333
        float C = 0.5f - SQ2/4;
334
        float[] convexCenter = new float[] {-C,-C,-C};
335

    
336
        FactoryCubit factory = FactoryCubit.getInstance();
337
        factory.createNewFaceTransform(vertices,vertIndexes);
338
        mCornerMesh = factory.createRoundedSolid(vertices, vertIndexes,
339
                                                 bands, bandIndexes,
340
                                                 corners, cornerIndexes,
341
                                                 centers, centerIndexes,
342
                                                 getNumCubitFaces(), convexCenter );
343
        }
344
      mesh = mCornerMesh.copy(true);
345
      }
346
    else
347
      {
348
      if( mFaceMesh==null )
349
        {
350
        final float angle = (float)Math.PI/(2*IVY_N);
351
        final float CORR  = 1.0f - 2*IVY_D;
352
        double[][] vertices = new double[2*IVY_N][3];
353
        int[][] vert_indices = new int[2][2*IVY_N];
354

    
355
        int[] bandIndexes= new int[] { 0,1 };
356
        int[] indexes    = new int[2*IVY_N];
357
        float[][] corners= new float[][] { {0.03f,0.10f} };
358
        float[][] centers= new float[][] { {-0.0f,-0.0f,-0.5f} };
359

    
360
        for(int i=0; i<IVY_N; i++)
361
          {
362
          double sin = Math.sin(i*angle);
363
          double cos = Math.cos(i*angle);
364

    
365
          vertices[i      ][0] = CORR*(0.5f-cos);
366
          vertices[i      ][1] = CORR*(0.5f-sin);
367
          vertices[i      ][2] = 0;
368
          vertices[i+IVY_N][0] = CORR*(cos-0.5f);
369
          vertices[i+IVY_N][1] = CORR*(sin-0.5f);
370
          vertices[i+IVY_N][2] = 0;
371
          }
372

    
373
        for(int i=0; i<2*IVY_N; i++)
374
          {
375
          vert_indices[0][i] = i;
376
          vert_indices[1][i] = 2*IVY_N-1-i;
377
          }
378

    
379
        for(int i=0; i<2*IVY_N; i++)
380
          {
381
          indexes[i] = -1;
382
          }
383
        indexes[0] = indexes[IVY_N] = 0;
384

    
385
        float[][] bands =
386
          {
387
               {+0.03f,35,0.5f,0.5f,5,0,0},
388
               {+0.10f,45,0.5f,0.0f,2,0,0}
389
          };
390

    
391
        FactoryCubit factory = FactoryCubit.getInstance();
392
        factory.createNewFaceTransform(vertices,vert_indices);
393
        mFaceMesh = factory.createRoundedSolid(vertices, vert_indices,
394
                                                bands, bandIndexes,
395
                                                corners, indexes,
396
                                                centers, indexes,
397
                                                getNumCubitFaces(), null );
398
        }
399
      mesh = mFaceMesh.copy(true);
400
      }
401

    
402
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[getQuat(cubit)], new Static3D(0,0,0) );
403
    mesh.apply(quat,0xffffffff,0);
404

    
405
    return mesh;
406
    }
407

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

    
410
  int getFaceColor(int cubit, int cubitface, int numLayers)
411
    {
412
    return mFaceMap[cubit][cubitface];
413
    }
414

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

    
417
  int getColor(int face)
418
    {
419
    return FACE_COLORS[face];
420
    }
421

    
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423

    
424
  ObjectSticker retSticker(int face)
425
    {
426
    return mStickers[face/NUM_FACES];
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

    
431
  float returnMultiplier()
432
    {
433
    return 2.0f;
434
    }
435

    
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437
// PUBLIC API
438

    
439
  public Static3D[] getRotationAxis()
440
    {
441
    return ROT_AXIS;
442
    }
443

    
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445

    
446
  public int[] getBasicAngle()
447
    {
448
    return BASIC_ANGLE;
449
    }
450

    
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

    
453
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
454
    {
455
    if( curr==0 )
456
      {
457
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
458
      }
459
    else
460
      {
461
      int newVector = rnd.nextInt(NUM_AXIS -1);
462
      scramble[curr][0] = (newVector>=scramble[curr-1][0] ? newVector+1 : newVector);
463
      }
464

    
465
    scramble[curr][1] = rnd.nextFloat()<=0.5f ? 0 : 1;
466

    
467
    switch( rnd.nextInt(2) )
468
      {
469
      case 0: scramble[curr][2] = -1; break;
470
      case 1: scramble[curr][2] =  1; break;
471
      }
472
    }
473

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475
// The Ivy is solved if and only if:
476
//
477
// 1) all 4 of its corner cubits are rotated with the same quat
478
// 2) all its face cubits are rotated with the same quat like the corner ones,
479
//    and optionally they also might be upside down.
480
//
481
// i.e.
482
// cubits [4] and [5] - might be extra QUAT[1]
483
// cubits [6] and [7] - might be extra QUAT[2]
484
// cubits [8] and [9] - might be extra QUAT[3]
485

    
486
  public boolean isSolved()
487
    {
488
    int q1,q = CUBITS[0].mQuatIndex;
489

    
490
    if( CUBITS[1].mQuatIndex == q &&
491
        CUBITS[2].mQuatIndex == q &&
492
        CUBITS[3].mQuatIndex == q  )
493
      {
494
      q1 = mulQuat(q,1);
495
      if( CUBITS[4].mQuatIndex != q && CUBITS[4].mQuatIndex != q1 ) return false;
496
      if( CUBITS[5].mQuatIndex != q && CUBITS[5].mQuatIndex != q1 ) return false;
497

    
498
      q1 = mulQuat(q,2);
499
      if( CUBITS[6].mQuatIndex != q && CUBITS[6].mQuatIndex != q1 ) return false;
500
      if( CUBITS[7].mQuatIndex != q && CUBITS[7].mQuatIndex != q1 ) return false;
501

    
502
      q1 = mulQuat(q,3);
503
      if( CUBITS[8].mQuatIndex != q && CUBITS[8].mQuatIndex != q1 ) return false;
504
      if( CUBITS[9].mQuatIndex != q && CUBITS[9].mQuatIndex != q1 ) return false;
505

    
506
      return true;
507
      }
508

    
509
    return false;
510
    }
511

    
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513

    
514
  public int getObjectName(int numLayers)
515
    {
516
    return R.string.ivy2;
517
    }
518

    
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520

    
521
  public int getInventor(int numLayers)
522
    {
523
    return R.string.ivy2_inventor;
524
    }
525

    
526
///////////////////////////////////////////////////////////////////////////////////////////////////
527

    
528
  public int getComplexity(int numLayers)
529
    {
530
    return 1;
531
    }
532
}
(28-28/41)