Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyIvy.java @ 9ce78850

1 49cd8581 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 749ef882 Leszek Koltunski
import org.distorted.helpers.FactoryCubit;
27
import org.distorted.helpers.FactorySticker;
28 49cd8581 Leszek Koltunski
import org.distorted.library.effect.MatrixEffectQuaternion;
29 be56193c Leszek Koltunski
import org.distorted.library.effect.VertexEffect;
30
import org.distorted.library.effect.VertexEffectMove;
31
import org.distorted.library.effect.VertexEffectRotate;
32
import org.distorted.library.effect.VertexEffectScale;
33 49cd8581 Leszek Koltunski
import org.distorted.library.main.DistortedEffects;
34
import org.distorted.library.main.DistortedTexture;
35
import org.distorted.library.mesh.MeshBase;
36 be56193c Leszek Koltunski
import org.distorted.library.mesh.MeshJoined;
37
import org.distorted.library.mesh.MeshPolygon;
38 49cd8581 Leszek Koltunski
import org.distorted.library.mesh.MeshSquare;
39 be56193c Leszek Koltunski
import org.distorted.library.type.Static1D;
40 49cd8581 Leszek Koltunski
import org.distorted.library.type.Static3D;
41
import org.distorted.library.type.Static4D;
42 6fd4a72c Leszek Koltunski
import org.distorted.main.R;
43 49cd8581 Leszek Koltunski
44
import java.util.Random;
45
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47
48
public class TwistyIvy extends TwistyObject
49
{
50 be56193c Leszek Koltunski
  public static final float IVY_D = 0.003f;
51
  public static final float IVY_C = 0.59f;
52
  public static final float IVY_M = 0.35f;
53
  private static final int IVY_N = 8;
54
55 18a5f95f Leszek Koltunski
  private static final int FACES_PER_CUBIT =6;
56 49cd8581 Leszek Koltunski
57
  // the four rotation axis of a RubikIvy. Must be normalized.
58
  static final Static3D[] ROT_AXIS = new Static3D[]
59
         {
60
           new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),
61
           new Static3D(+SQ3/3,+SQ3/3,-SQ3/3),
62
           new Static3D(+SQ3/3,-SQ3/3,+SQ3/3),
63
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
64
         };
65
66 925ed78f Leszek Koltunski
  private static final int[] BASIC_ANGLE = new int[] { 3,3,3,3 };
67
68 49cd8581 Leszek Koltunski
  private static final int[] FACE_COLORS = new int[]
69
         {
70
           COLOR_YELLOW, COLOR_WHITE,
71
           COLOR_BLUE  , COLOR_GREEN,
72 323b217c Leszek Koltunski
           COLOR_RED   , COLOR_ORANGE
73 49cd8581 Leszek Koltunski
         };
74
75
  // All legal rotation quats of a RubikIvy
76
  private static final Static4D[] QUATS = new Static4D[]
77
         {
78
           new Static4D(  0.0f,  0.0f,  0.0f,  1.0f ),
79
           new Static4D(  1.0f,  0.0f,  0.0f,  0.0f ),
80
           new Static4D(  0.0f,  1.0f,  0.0f,  0.0f ),
81
           new Static4D(  0.0f,  0.0f,  1.0f,  0.0f ),
82
83
           new Static4D(  0.5f,  0.5f,  0.5f,  0.5f ),
84
           new Static4D(  0.5f,  0.5f,  0.5f, -0.5f ),
85
           new Static4D(  0.5f,  0.5f, -0.5f,  0.5f ),
86
           new Static4D(  0.5f,  0.5f, -0.5f, -0.5f ),
87
           new Static4D(  0.5f, -0.5f,  0.5f,  0.5f ),
88
           new Static4D(  0.5f, -0.5f,  0.5f, -0.5f ),
89
           new Static4D(  0.5f, -0.5f, -0.5f,  0.5f ),
90
           new Static4D(  0.5f, -0.5f, -0.5f, -0.5f )
91
         };
92
93 18a5f95f Leszek Koltunski
  private static final int[][] mFaceMap =
94 49cd8581 Leszek Koltunski
         {
95 18a5f95f Leszek Koltunski
           {  4, 2, 0, 12,12,12 },
96
           {  5, 2, 1, 12,12,12 },
97
           {  4, 3, 1, 12,12,12 },
98
           {  5, 3, 0, 12,12,12 },
99
100
           {  6, 12,12,12,12,12 },
101
           {  7, 12,12,12,12,12 },
102
           {  8, 12,12,12,12,12 },
103
           {  9, 12,12,12,12,12 },
104
           { 10, 12,12,12,12,12 },
105
           { 11, 12,12,12,12,12 },
106 49cd8581 Leszek Koltunski
         };
107
108
  private static MeshBase mCornerMesh, mFaceMesh;
109
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111
112
  TwistyIvy(int size, Static4D quat, DistortedTexture texture,
113
            MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
114
    {
115 db875721 Leszek Koltunski
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.IVY, res, scrWidth);
116 49cd8581 Leszek Koltunski
    }
117
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119
120
  float getScreenRatio()
121
    {
122
    return 1.0f;
123
    }
124
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126
127
  Static4D[] getQuats()
128
    {
129
    return QUATS;
130
    }
131
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133
134
  int getNumFaces()
135
    {
136
    return FACE_COLORS.length;
137
    }
138
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140
141
  boolean shouldResetTextureMaps()
142
    {
143
    return false;
144
    }
145
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147
148 a64e07d0 Leszek Koltunski
  int getNumStickerTypes(int numLayers)
149 49cd8581 Leszek Koltunski
    {
150
    return 2;
151
    }
152
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154
155 e6734aa9 Leszek Koltunski
  float[][] getCuts(int numLayers)
156 49cd8581 Leszek Koltunski
    {
157 e6734aa9 Leszek Koltunski
    float[] cut = new float[] {0.0f};
158
    return new float[][] { cut,cut,cut,cut };
159 49cd8581 Leszek Koltunski
    }
160
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162
163
  int getNumCubitFaces()
164
    {
165
    return FACES_PER_CUBIT;
166
    }
167
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169
170 e6cf7283 Leszek Koltunski
  float[][] getCubitPositions(int numLayers)
171 49cd8581 Leszek Koltunski
    {
172
    final float DIST_CORNER = (numLayers-1)*0.50f;
173
    final float DIST_CENTER = (numLayers-1)*0.50f;
174
175 e6cf7283 Leszek Koltunski
    final float[][] CENTERS = new float[10][];
176
177
    CENTERS[0] = new float[] { DIST_CORNER, DIST_CORNER, DIST_CORNER };
178
    CENTERS[1] = new float[] {-DIST_CORNER, DIST_CORNER,-DIST_CORNER };
179
    CENTERS[2] = new float[] {-DIST_CORNER,-DIST_CORNER, DIST_CORNER };
180
    CENTERS[3] = new float[] { DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
181
    CENTERS[4] = new float[] { DIST_CENTER,           0,           0 };
182
    CENTERS[5] = new float[] {-DIST_CENTER,           0,           0 };
183
    CENTERS[6] = new float[] {           0, DIST_CENTER,           0 };
184
    CENTERS[7] = new float[] {           0,-DIST_CENTER,           0 };
185
    CENTERS[8] = new float[] {           0,           0, DIST_CENTER };
186
    CENTERS[9] = new float[] {           0,           0,-DIST_CENTER };
187 49cd8581 Leszek Koltunski
188
    return CENTERS;
189
    }
190
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192
193
  private int getQuat(int cubit)
194
    {
195
    switch(cubit)
196
      {
197
      case  0: return 0;
198
      case  1: return 2;
199
      case  2: return 3;
200
      case  3: return 1;
201
202
      case  4: return 8;
203
      case  5: return 11;
204
      case  6: return 10;
205
      case  7: return 9;
206
      case  8: return 0;
207
      case  9: return 2;
208
      }
209
210
    return 0;
211
    }
212
213 be56193c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
214
215
  MeshBase createFacesIvyCorner()
216
    {
217
    MeshBase[] meshes = new MeshBase[6];
218
219
    final float angle = (float)Math.PI/(2*IVY_N);
220
    final float CORR  = 1.0f - 2*IVY_D;
221
    final float DIST  = -0.5f*CORR + IVY_D;
222
    float[] vertices  = new float[2*(IVY_N+1)+6];
223
224
    vertices[0] = (0.5f-IVY_M) * IVY_C;
225
    vertices[1] = (DIST-IVY_M) * IVY_C;
226
    vertices[2] = (0.5f-IVY_M) * IVY_C;
227
    vertices[3] = (0.5f-IVY_M) * IVY_C;
228
    vertices[4] = (DIST-IVY_M) * IVY_C;
229
    vertices[5] = (0.5f-IVY_M) * IVY_C;
230
231
    for(int i=0; i<=IVY_N; i++)
232
      {
233
      float ang = (IVY_N-i)*angle;
234
      float sin = (float)Math.sin(ang);
235
      float cos = (float)Math.cos(ang);
236
237
      vertices[2*i+6] = (CORR*(cos-0.5f)-IVY_M)*IVY_C;
238
      vertices[2*i+7] = (CORR*(sin-0.5f)-IVY_M)*IVY_C;
239
      }
240
241
    FactoryCubit factory = FactoryCubit.getInstance();
242
    float[] bands0 = factory.computeBands(+0.012f,20,0.2f,0.5f,7);
243
    float[] bands1 = factory.computeBands(-0.100f,20,0.2f,0.0f,2);
244
245
    meshes[0] = new MeshPolygon(vertices,bands0,1,2);
246
    meshes[0].setEffectAssociation(0,1,0);
247
    meshes[1] = meshes[0].copy(true);
248
    meshes[1].setEffectAssociation(0,2,0);
249
    meshes[2] = meshes[0].copy(true);
250
    meshes[2].setEffectAssociation(0,4,0);
251
    meshes[3] = new MeshPolygon(vertices,bands1,1,2);
252
    meshes[3].setEffectAssociation(0,8,0);
253
    meshes[4] = meshes[3].copy(true);
254
    meshes[4].setEffectAssociation(0,16,0);
255
    meshes[5] = meshes[3].copy(true);
256
    meshes[5].setEffectAssociation(0,32,0);
257
258
    return new MeshJoined(meshes);
259
    }
260
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262
263
  private VertexEffect[] createVertexEffectsIvyCorner()
264
    {
265
    Static3D axisX  = new Static3D(1,0,0);
266
    Static3D axisY  = new Static3D(0,1,0);
267
    Static1D angle1 = new Static1D(+90);
268
    Static1D angle2 = new Static1D(-90);
269
    Static3D center = new Static3D(0,0,0);
270
    Static3D move1  = new Static3D(IVY_M-0.5f,IVY_M-0.5f,0);
271
272
    VertexEffect[] effect = new VertexEffect[5];
273
274
    effect[0] = new VertexEffectScale(1/IVY_C);
275
    effect[1] = new VertexEffectMove(move1);
276
    effect[2] = new VertexEffectScale(new Static3D(1,1,-1));
277
    effect[3] = new VertexEffectRotate(angle1,axisX,center);
278
    effect[4] = new VertexEffectRotate(angle2,axisY,center);
279
280
    effect[2].setMeshAssociation(54,-1);  // meshes 1,2,4,5
281
    effect[3].setMeshAssociation(18,-1);  // meshes 1,4
282
    effect[4].setMeshAssociation(36,-1);  // meshes 2,5
283
284
    return effect;
285
    }
286
287
///////////////////////////////////////////////////////////////////////////////////////////////////
288
289
  private MeshBase createFacesIvyFace()
290
    {
291
    MeshBase[] meshes = new MeshBase[2];
292
293
    final float angle = (float)Math.PI/(2*IVY_N);
294
    final float CORR  = 1.0f - 2*IVY_D;
295
    float[] vertices = new float[4*IVY_N];
296
297
    for(int i=0; i<IVY_N; i++)
298
      {
299
      float sin = (float)Math.sin(i*angle);
300
      float cos = (float)Math.cos(i*angle);
301
302
      vertices[2*i          ] = CORR*(0.5f-cos);
303
      vertices[2*i+1        ] = CORR*(0.5f-sin);
304
      vertices[2*i  +2*IVY_N] = CORR*(cos-0.5f);
305
      vertices[2*i+1+2*IVY_N] = CORR*(sin-0.5f);
306
      }
307
308
    FactoryCubit factory = FactoryCubit.getInstance();
309
    float[] bands0 = factory.computeBands(+0.03f,35,0.5f,0.5f,5);
310
    float[] bands1 = factory.computeBands(-0.10f,45,0.5f,0.0f,2);
311
312
    meshes[0] = new MeshPolygon(vertices,bands0,0,0);
313
    meshes[0].setEffectAssociation(0,1,0);
314
    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
315
    meshes[1].setEffectAssociation(0,2,0);
316
317
    return new MeshJoined(meshes);
318
    }
319
320
///////////////////////////////////////////////////////////////////////////////////////////////////
321
322
  private MeshBase createIvyFaceMesh()
323
    {
324
    MeshBase mesh = createFacesIvyFace();
325
326
    Static3D center = new Static3D(-0.0f,-0.0f,-0.5f);
327
    Static3D[] vertices = new Static3D[2];
328
    vertices[0] = new Static3D(-0.5f,+0.5f,+0.0f);
329
    vertices[1] = new Static3D(+0.5f,-0.5f,+0.0f);
330
331
    FactoryCubit.getInstance().roundCorners(mesh,center,vertices,0.03f,0.10f);
332
333
    mesh.mergeEffComponents();
334
    mesh.addEmptyTexComponent();
335
    mesh.addEmptyTexComponent();
336
    mesh.addEmptyTexComponent();
337
    mesh.addEmptyTexComponent();
338
339
    return mesh;
340
    }
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342
343
  private MeshBase createIvyCornerMesh()
344
    {
345
    MeshBase mesh = createFacesIvyCorner();
346
    VertexEffect[] effects = createVertexEffectsIvyCorner();
347
    for( VertexEffect effect : effects ) mesh.apply(effect);
348
349
    Static3D center = new Static3D(-0.5f,-0.5f,-0.5f);
350
    Static3D[] vertices = new Static3D[4];
351
    vertices[0] = new Static3D(+0.0f,+0.0f,+0.0f);
352
    vertices[1] = new Static3D(-1.0f,+0.0f,+0.0f);
353
    vertices[2] = new Static3D(+0.0f,-1.0f,+0.0f);
354
    vertices[3] = new Static3D(+0.0f,+0.0f,-1.0f);
355
356
    FactoryCubit.getInstance().roundCorners(mesh,center,vertices,0.03f,0.10f);
357
358
    mesh.mergeEffComponents();
359
360
    return mesh;
361
    }
362
363 49cd8581 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
364
365 a64e07d0 Leszek Koltunski
  MeshBase createCubitMesh(int cubit, int numLayers)
366 49cd8581 Leszek Koltunski
    {
367
    MeshBase mesh;
368
369
    if( cubit<4 )
370
      {
371 be56193c Leszek Koltunski
      if( mCornerMesh==null ) mCornerMesh = createIvyCornerMesh();
372 49cd8581 Leszek Koltunski
      mesh = mCornerMesh.copy(true);
373
      }
374
    else
375
      {
376 be56193c Leszek Koltunski
      if( mFaceMesh==null ) mFaceMesh = createIvyFaceMesh();
377 49cd8581 Leszek Koltunski
      mesh = mFaceMesh.copy(true);
378
      }
379
380
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[getQuat(cubit)], new Static3D(0,0,0) );
381
    mesh.apply(quat,0xffffffff,0);
382
383
    return mesh;
384
    }
385
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387
388
  int getFaceColor(int cubit, int cubitface, int numLayers)
389
    {
390 18a5f95f Leszek Koltunski
    return mFaceMap[cubit][cubitface];
391 49cd8581 Leszek Koltunski
    }
392
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394
395
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
396
    {
397
    int COLORS = FACE_COLORS.length;
398
    FactorySticker factory = FactorySticker.getInstance();
399
400
    if( face<COLORS )
401
      {
402 9ce78850 Leszek Koltunski
      float S = 0.03f;
403
      float R = 0.02f;
404
405
      float ANGLE = (float)(Math.PI/4);
406
407
      float A = (+0.5f-IVY_M)*IVY_C;
408
      float B = (-0.5f-IVY_M)*IVY_C;
409
410
      float[] vertices = new float[] { A, B, A, A, B, A };
411
      float[] angles   = new float[] { 0, 0, ANGLE };
412
413
      factory.drawRoundedPolygon(canvas, paint, left, top, vertices, angles, S, FACE_COLORS[face%COLORS], R);
414 49cd8581 Leszek Koltunski
      }
415
    else
416
      {
417 9ce78850 Leszek Koltunski
      float S = 0.08f;
418
      float R = 0.06f;
419
420
      float ANGLE = (float)(Math.PI/4);
421
      float A = 0.50f-IVY_D;
422
423
      float[] vertices = new float[] { -A, A, A, -A };
424
      float[] angles   = new float[] { ANGLE, ANGLE };
425
426
      factory.drawRoundedPolygon(canvas, paint, left, top, vertices, angles, S, FACE_COLORS[face%COLORS], R);
427 49cd8581 Leszek Koltunski
      }
428
    }
429
430
///////////////////////////////////////////////////////////////////////////////////////////////////
431
432
  float returnMultiplier()
433
    {
434
    return 2.0f;
435
    }
436
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438
// PUBLIC API
439
440
  public Static3D[] getRotationAxis()
441
    {
442
    return ROT_AXIS;
443
    }
444
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446
447 925ed78f Leszek Koltunski
  public int[] getBasicAngle()
448 49cd8581 Leszek Koltunski
    {
449 925ed78f Leszek Koltunski
    return BASIC_ANGLE;
450 49cd8581 Leszek Koltunski
    }
451
452
///////////////////////////////////////////////////////////////////////////////////////////////////
453
454 9f171eba Leszek Koltunski
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
455 49cd8581 Leszek Koltunski
    {
456 9f171eba Leszek Koltunski
    if( curr==0 )
457 49cd8581 Leszek Koltunski
      {
458 9f171eba Leszek Koltunski
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
459 49cd8581 Leszek Koltunski
      }
460
    else
461
      {
462 582617c1 Leszek Koltunski
      int newVector = rnd.nextInt(NUM_AXIS -1);
463 9f171eba Leszek Koltunski
      scramble[curr][0] = (newVector>=scramble[curr-1][0] ? newVector+1 : newVector);
464 49cd8581 Leszek Koltunski
      }
465
466 9f171eba Leszek Koltunski
    scramble[curr][1] = rnd.nextFloat()<=0.5f ? 0 : 1;
467 49cd8581 Leszek Koltunski
468 5043d5d0 Leszek Koltunski
    switch( rnd.nextInt(2) )
469
      {
470 9f171eba Leszek Koltunski
      case 0: scramble[curr][2] = -1; break;
471
      case 1: scramble[curr][2] =  1; break;
472 5043d5d0 Leszek Koltunski
      }
473 49cd8581 Leszek Koltunski
    }
474
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476
// The Ivy is solved if and only if:
477
//
478
// 1) all 4 of its corner cubits are rotated with the same quat
479
// 2) all its face cubits are rotated with the same quat like the corner ones,
480
//    and optionally they also might be upside down.
481
//
482
// i.e.
483
// cubits [4] and [5] - might be extra QUAT[1]
484
// cubits [6] and [7] - might be extra QUAT[2]
485
// cubits [8] and [9] - might be extra QUAT[3]
486
487
  public boolean isSolved()
488
    {
489
    int q1,q = CUBITS[0].mQuatIndex;
490
491
    if( CUBITS[1].mQuatIndex == q &&
492
        CUBITS[2].mQuatIndex == q &&
493
        CUBITS[3].mQuatIndex == q  )
494
      {
495
      q1 = mulQuat(q,1);
496
      if( CUBITS[4].mQuatIndex != q && CUBITS[4].mQuatIndex != q1 ) return false;
497
      if( CUBITS[5].mQuatIndex != q && CUBITS[5].mQuatIndex != q1 ) return false;
498
499
      q1 = mulQuat(q,2);
500
      if( CUBITS[6].mQuatIndex != q && CUBITS[6].mQuatIndex != q1 ) return false;
501
      if( CUBITS[7].mQuatIndex != q && CUBITS[7].mQuatIndex != q1 ) return false;
502
503
      q1 = mulQuat(q,3);
504
      if( CUBITS[8].mQuatIndex != q && CUBITS[8].mQuatIndex != q1 ) return false;
505
      if( CUBITS[9].mQuatIndex != q && CUBITS[9].mQuatIndex != q1 ) return false;
506
507
      return true;
508
      }
509
510
    return false;
511
    }
512
513
///////////////////////////////////////////////////////////////////////////////////////////////////
514
// only needed for solvers - there are no Ivy solvers ATM)
515
516
  public String retObjectString()
517
    {
518
    return "";
519
    }
520 6fd4a72c Leszek Koltunski
521
///////////////////////////////////////////////////////////////////////////////////////////////////
522
523
  public int getObjectName(int numLayers)
524
    {
525
    return R.string.ivy2;
526
    }
527
528
///////////////////////////////////////////////////////////////////////////////////////////////////
529
530
  public int getInventor(int numLayers)
531
    {
532
    return R.string.ivy2_inventor;
533
    }
534
535
///////////////////////////////////////////////////////////////////////////////////////////////////
536
537
  public int getComplexity(int numLayers)
538
    {
539
    return 1;
540
    }
541 49cd8581 Leszek Koltunski
}