Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyIvy.java @ 3e605536

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 TwistyIvy extends TwistyObject
38
{
39
  public static final float IVY_D = 0.003f;
40
  private static final int  IVY_N = 8;
41

    
42
  private static final int FACES_PER_CUBIT =6;
43

    
44
  // the four rotation axis of a RubikIvy. Must be normalized.
45
  static final Static3D[] ROT_AXIS = new Static3D[]
46
         {
47
           new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),
48
           new Static3D(+SQ3/3,+SQ3/3,-SQ3/3),
49
           new Static3D(+SQ3/3,-SQ3/3,+SQ3/3),
50
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
51
         };
52

    
53
  private static final int[] BASIC_ANGLE = new int[] { 3,3,3,3 };
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
  // All legal rotation quats of a RubikIvy
63
  private static final Static4D[] QUATS = new Static4D[]
64
         {
65
           new Static4D(  0.0f,  0.0f,  0.0f,  1.0f ),
66
           new Static4D(  1.0f,  0.0f,  0.0f,  0.0f ),
67
           new Static4D(  0.0f,  1.0f,  0.0f,  0.0f ),
68
           new Static4D(  0.0f,  0.0f,  1.0f,  0.0f ),
69

    
70
           new Static4D(  0.5f,  0.5f,  0.5f,  0.5f ),
71
           new Static4D(  0.5f,  0.5f,  0.5f, -0.5f ),
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
         };
79

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

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

    
95
  private static final ObjectSticker[] mStickers;
96

    
97
  private static final float[][] STICKERS = new float[][]
98
          {
99
             { 0.29258922f, -0.5f, 0.29258922f, 0.29258922f, -0.5f, 0.29258922f },
100
             { -0.5f, 0.5f, 0.5f, -0.5f }
101
          };
102
  private static final int NUM_STICKERS = STICKERS.length;
103

    
104
  static
105
    {
106
    mStickers = new ObjectSticker[NUM_STICKERS];
107

    
108
    float D = (float)(Math.PI/4);
109
    final float[][] angles = { { 0,0,D },{ D,D } };
110
    final float[][] radii  = { { 0,0.04f,0 },{ 0.06f,0.06f } };
111
    final float[] strokes = { 0.03f, 0.08f };
112

    
113
    for(int s=0; s<NUM_STICKERS; s++)
114
      {
115
      mStickers[s] = new ObjectSticker(STICKERS[s], angles[s],radii[s],strokes[s]);
116
      }
117
    }
118

    
119
///////////////////////////////////////////////////////////////////////////////////////////////////
120

    
121
  TwistyIvy(int size, Static4D quat, DistortedTexture texture,
122
            MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
123
    {
124
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.IVY, res, scrWidth);
125
    }
126

    
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128

    
129
  float getScreenRatio()
130
    {
131
    return 1.0f;
132
    }
133

    
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135

    
136
  Static4D[] getQuats()
137
    {
138
    return QUATS;
139
    }
140

    
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142

    
143
  int getNumFaces()
144
    {
145
    return FACE_COLORS.length;
146
    }
147

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

    
150
  boolean shouldResetTextureMaps()
151
    {
152
    return false;
153
    }
154

    
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156

    
157
  int getNumStickerTypes(int numLayers)
158
    {
159
    return NUM_STICKERS;
160
    }
161

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163

    
164
  float[][] getCuts(int numLayers)
165
    {
166
    float[] cut = new float[] {0.0f};
167
    return new float[][] { cut,cut,cut,cut };
168
    }
169

    
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171

    
172
  int getNumCubitFaces()
173
    {
174
    return FACES_PER_CUBIT;
175
    }
176

    
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

    
179
  float[][] getCubitPositions(int numLayers)
180
    {
181
    final float DIST_CORNER = (numLayers-1)*0.50f;
182
    final float DIST_CENTER = (numLayers-1)*0.50f;
183

    
184
    final float[][] CENTERS = new float[10][];
185

    
186
    CENTERS[0] = new float[] { DIST_CORNER, DIST_CORNER, DIST_CORNER };
187
    CENTERS[1] = new float[] {-DIST_CORNER, DIST_CORNER,-DIST_CORNER };
188
    CENTERS[2] = new float[] {-DIST_CORNER,-DIST_CORNER, DIST_CORNER };
189
    CENTERS[3] = new float[] { DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
190
    CENTERS[4] = new float[] { DIST_CENTER,           0,           0 };
191
    CENTERS[5] = new float[] {-DIST_CENTER,           0,           0 };
192
    CENTERS[6] = new float[] {           0, DIST_CENTER,           0 };
193
    CENTERS[7] = new float[] {           0,-DIST_CENTER,           0 };
194
    CENTERS[8] = new float[] {           0,           0, DIST_CENTER };
195
    CENTERS[9] = new float[] {           0,           0,-DIST_CENTER };
196

    
197
    return CENTERS;
198
    }
199

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

    
202
  ObjectShape getObjectShape(int cubit, int numLayers)
203
    {
204
    int variant = getCubitVariant(cubit,numLayers);
205

    
206
    if( variant==0 )
207
      {
208
      final float angle = (float)Math.PI/(2*IVY_N);
209
      final float CORR  = 1.0f - 2*IVY_D;
210

    
211
      float[][] centers= new float[][] { {-0.5f,-0.5f,-0.5f} };
212
      float[][] corners= new float[][] { {0.03f,0.10f}, {0.02f,0.10f} };
213
      int[] cornerIndices= new int[3*(IVY_N+1)+4];
214
      int[] centerIndices= new int[3*(IVY_N+1)+4];
215
      double[][] vertices= new double[3*(IVY_N+1)+4][3];
216
      int[][] vertIndices= new int[6][IVY_N+4];
217
      int[] bandIndices  = new int[] { 0,0,0,1,1,1 };
218

    
219
      float[][] bands =
220
        {
221
          {+0.015f,20,0.2f,0.5f,7,1,2},
222
          {-0.100f,20,0.2f,0.0f,2,1,2}
223
        };
224

    
225
      for(int i=0; i<3*(IVY_N+1); i++)
226
        {
227
        cornerIndices[i+4] = -1;
228
        centerIndices[i+4] = -1;
229
        }
230

    
231
      cornerIndices[0] = 1;
232
      cornerIndices[1] = 0;
233
      cornerIndices[2] = 0;
234
      cornerIndices[3] = 0;
235

    
236
      centerIndices[0] = 0;
237
      centerIndices[1] = 0;
238
      centerIndices[2] = 0;
239
      centerIndices[3] = 0;
240

    
241
      vertices[0][0] = 0.0;
242
      vertices[0][1] = 0.0;
243
      vertices[0][2] = 0.0;
244
      vertices[1][0] =-1.0;
245
      vertices[1][1] = 0.0;
246
      vertices[1][2] = 0.0;
247
      vertices[2][0] = 0.0;
248
      vertices[2][1] =-1.0;
249
      vertices[2][2] = 0.0;
250
      vertices[3][0] = 0.0;
251
      vertices[3][1] = 0.0;
252
      vertices[3][2] =-1.0;
253

    
254
      vertIndices[0][0] = 2;
255
      vertIndices[0][1] = 0;
256
      vertIndices[0][2] = 1;
257
      vertIndices[3][0] = 2;
258
      vertIndices[3][1] = 0;
259
      vertIndices[3][2] = 1;
260

    
261
      vertIndices[1][0] = 3;
262
      vertIndices[1][1] = 0;
263
      vertIndices[1][2] = 2;
264
      vertIndices[4][0] = 3;
265
      vertIndices[4][1] = 0;
266
      vertIndices[4][2] = 2;
267

    
268
      vertIndices[2][0] = 1;
269
      vertIndices[2][1] = 0;
270
      vertIndices[2][2] = 3;
271
      vertIndices[5][0] = 1;
272
      vertIndices[5][1] = 0;
273
      vertIndices[5][2] = 3;
274

    
275
      int N1 = 4;
276
      int N2 = N1 + IVY_N + 1;
277
      int N3 = N2 + IVY_N + 1;
278

    
279
      for(int i=0; i<=IVY_N; i++)
280
        {
281
        double cos1 = Math.cos((IVY_N-i)*angle);
282
        double sin1 = Math.sin((IVY_N-i)*angle);
283
        double cos2 = Math.cos((      i)*angle);
284
        double sin2 = Math.sin((      i)*angle);
285

    
286
        vertices[N1+i][0] = CORR*(cos1-0.5) - 0.5;
287
        vertices[N1+i][1] = CORR*(sin1-0.5) - 0.5;
288
        vertices[N1+i][2] = 0.0;
289

    
290
        vertices[N2+i][0] = 0.0;
291
        vertices[N2+i][1] = CORR*(sin2-0.5) - 0.5;
292
        vertices[N2+i][2] = CORR*(cos2-0.5) - 0.5;
293

    
294
        vertices[N3+i][0] = CORR*(cos2-0.5) - 0.5;
295
        vertices[N3+i][1] = 0.0;
296
        vertices[N3+i][2] = CORR*(sin2-0.5) - 0.5;
297

    
298
        vertIndices[0][i+3] = N1 + i;
299
        vertIndices[1][i+3] = N2 + i;
300
        vertIndices[2][i+3] = N3 + i;
301
        vertIndices[3][i+3] = N1 + i;
302
        vertIndices[4][i+3] = N2 + i;
303
        vertIndices[5][i+3] = N3 + i;
304
        }
305

    
306
      float C = 0.5f - SQ2/4;
307
      float[] convexCenter = new float[] {-C,-C,-C};
308
      return new ObjectShape(vertices,vertIndices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), convexCenter);
309
      }
310
    else
311
      {
312
      final float angle = (float)Math.PI/(2*IVY_N);
313
      final float CORR  = 1.0f - 2*IVY_D;
314
      double[][] vertices = new double[2*IVY_N][3];
315
      int[][] vert_indices = new int[2][2*IVY_N];
316

    
317
      int[] bandIndices= new int[] { 0,1 };
318
      int[] indexes    = new int[2*IVY_N];
319
      float[][] corners= new float[][] { {0.03f,0.10f} };
320
      float[][] centers= new float[][] { {-0.0f,-0.0f,-0.5f} };
321

    
322
      for(int i=0; i<IVY_N; i++)
323
        {
324
        double sin = Math.sin(i*angle);
325
        double cos = Math.cos(i*angle);
326

    
327
        vertices[i      ][0] = CORR*(0.5f-cos);
328
        vertices[i      ][1] = CORR*(0.5f-sin);
329
        vertices[i      ][2] = 0;
330
        vertices[i+IVY_N][0] = CORR*(cos-0.5f);
331
        vertices[i+IVY_N][1] = CORR*(sin-0.5f);
332
        vertices[i+IVY_N][2] = 0;
333
        }
334

    
335
      for(int i=0; i<2*IVY_N; i++)
336
        {
337
        vert_indices[0][i] = i;
338
        vert_indices[1][i] = 2*IVY_N-1-i;
339
        }
340

    
341
      for(int i=0; i<2*IVY_N; i++)
342
        {
343
        indexes[i] = -1;
344
        }
345
      indexes[0] = indexes[IVY_N] = 0;
346

    
347
      float[][] bands =
348
        {
349
          {+0.03f,35,0.5f,0.5f,5,0,0},
350
          {+0.10f,45,0.5f,0.0f,2,0,0}
351
        };
352

    
353
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,indexes,centers,indexes,getNumCubitFaces(), null);
354
      }
355
    }
356

    
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358

    
359
  Static4D getQuat(int cubit, int numLayers)
360
    {
361
    switch(cubit)
362
      {
363
      case  0: return QUATS[0];
364
      case  1: return QUATS[2];
365
      case  2: return QUATS[3];
366
      case  3: return QUATS[1];
367

    
368
      case  4: return QUATS[8];
369
      case  5: return QUATS[11];
370
      case  6: return QUATS[10];
371
      case  7: return QUATS[9];
372
      case  8: return QUATS[0];
373
      case  9: return QUATS[2];
374
      }
375

    
376
    return QUATS[0];
377
    }
378

    
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380

    
381
  int getNumCubitVariants(int numLayers)
382
    {
383
    return 2;
384
    }
385

    
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387

    
388
  int getCubitVariant(int cubit, int numLayers)
389
    {
390
    return cubit<4 ? 0:1;
391
    }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

    
395
  int getFaceColor(int cubit, int cubitface, int numLayers)
396
    {
397
    return mFaceMap[cubit][cubitface];
398
    }
399

    
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401

    
402
  int getColor(int face)
403
    {
404
    return FACE_COLORS[face];
405
    }
406

    
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408

    
409
  ObjectSticker retSticker(int face)
410
    {
411
    return mStickers[face/NUM_FACES];
412
    }
413

    
414
///////////////////////////////////////////////////////////////////////////////////////////////////
415

    
416
  float returnMultiplier()
417
    {
418
    return 2.0f;
419
    }
420

    
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422
// PUBLIC API
423

    
424
  public Static3D[] getRotationAxis()
425
    {
426
    return ROT_AXIS;
427
    }
428

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

    
431
  public int[] getBasicAngle()
432
    {
433
    return BASIC_ANGLE;
434
    }
435

    
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437

    
438
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
439
    {
440
    if( curr==0 )
441
      {
442
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
443
      }
444
    else
445
      {
446
      int newVector = rnd.nextInt(NUM_AXIS -1);
447
      scramble[curr][0] = (newVector>=scramble[curr-1][0] ? newVector+1 : newVector);
448
      }
449

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

    
452
    switch( rnd.nextInt(2) )
453
      {
454
      case 0: scramble[curr][2] = -1; break;
455
      case 1: scramble[curr][2] =  1; break;
456
      }
457
    }
458

    
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460
// The Ivy is solved if and only if:
461
//
462
// 1) all 4 of its corner cubits are rotated with the same quat
463
// 2) all its face cubits are rotated with the same quat like the corner ones,
464
//    and optionally they also might be upside down.
465
//
466
// i.e.
467
// cubits [4] and [5] - might be extra QUAT[1]
468
// cubits [6] and [7] - might be extra QUAT[2]
469
// cubits [8] and [9] - might be extra QUAT[3]
470

    
471
  public boolean isSolved()
472
    {
473
    int q1,q = CUBITS[0].mQuatIndex;
474

    
475
    if( CUBITS[1].mQuatIndex == q &&
476
        CUBITS[2].mQuatIndex == q &&
477
        CUBITS[3].mQuatIndex == q  )
478
      {
479
      q1 = mulQuat(q,1);
480
      if( CUBITS[4].mQuatIndex != q && CUBITS[4].mQuatIndex != q1 ) return false;
481
      if( CUBITS[5].mQuatIndex != q && CUBITS[5].mQuatIndex != q1 ) return false;
482

    
483
      q1 = mulQuat(q,2);
484
      if( CUBITS[6].mQuatIndex != q && CUBITS[6].mQuatIndex != q1 ) return false;
485
      if( CUBITS[7].mQuatIndex != q && CUBITS[7].mQuatIndex != q1 ) return false;
486

    
487
      q1 = mulQuat(q,3);
488
      if( CUBITS[8].mQuatIndex != q && CUBITS[8].mQuatIndex != q1 ) return false;
489
      if( CUBITS[9].mQuatIndex != q && CUBITS[9].mQuatIndex != q1 ) return false;
490

    
491
      return true;
492
      }
493

    
494
    return false;
495
    }
496

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

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

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

    
506
  public int getInventor(int numLayers)
507
    {
508
    return R.string.ivy2_inventor;
509
    }
510

    
511
///////////////////////////////////////////////////////////////////////////////////////////////////
512

    
513
  public int getComplexity(int numLayers)
514
    {
515
    return 1;
516
    }
517
}
(28-28/41)