Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyIvy.java @ be56193c

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
  private static final int[] FACE_COLORS = new int[]
67
         {
68
           COLOR_YELLOW, COLOR_WHITE,
69
           COLOR_BLUE  , COLOR_GREEN,
70 323b217c Leszek Koltunski
           COLOR_RED   , COLOR_ORANGE
71 49cd8581 Leszek Koltunski
         };
72
73
  // All legal rotation quats of a RubikIvy
74
  private static final Static4D[] QUATS = new Static4D[]
75
         {
76
           new Static4D(  0.0f,  0.0f,  0.0f,  1.0f ),
77
           new Static4D(  1.0f,  0.0f,  0.0f,  0.0f ),
78
           new Static4D(  0.0f,  1.0f,  0.0f,  0.0f ),
79
           new Static4D(  0.0f,  0.0f,  1.0f,  0.0f ),
80
81
           new Static4D(  0.5f,  0.5f,  0.5f,  0.5f ),
82
           new Static4D(  0.5f,  0.5f,  0.5f, -0.5f ),
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
         };
90
91 18a5f95f Leszek Koltunski
  private static final int[][] mFaceMap =
92 49cd8581 Leszek Koltunski
         {
93 18a5f95f Leszek Koltunski
           {  4, 2, 0, 12,12,12 },
94
           {  5, 2, 1, 12,12,12 },
95
           {  4, 3, 1, 12,12,12 },
96
           {  5, 3, 0, 12,12,12 },
97
98
           {  6, 12,12,12,12,12 },
99
           {  7, 12,12,12,12,12 },
100
           {  8, 12,12,12,12,12 },
101
           {  9, 12,12,12,12,12 },
102
           { 10, 12,12,12,12,12 },
103
           { 11, 12,12,12,12,12 },
104 49cd8581 Leszek Koltunski
         };
105
106
  private static MeshBase mCornerMesh, mFaceMesh;
107
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109
110
  TwistyIvy(int size, Static4D quat, DistortedTexture texture,
111
            MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
112
    {
113 db875721 Leszek Koltunski
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.IVY, res, scrWidth);
114 49cd8581 Leszek Koltunski
    }
115
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117
118
  float getScreenRatio()
119
    {
120
    return 1.0f;
121
    }
122
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124
125
  Static4D[] getQuats()
126
    {
127
    return QUATS;
128
    }
129
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131
132
  int getNumFaces()
133
    {
134
    return FACE_COLORS.length;
135
    }
136
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138
139
  boolean shouldResetTextureMaps()
140
    {
141
    return false;
142
    }
143
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145
146 a64e07d0 Leszek Koltunski
  int getNumStickerTypes(int numLayers)
147 49cd8581 Leszek Koltunski
    {
148
    return 2;
149
    }
150
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152
153
  float[] getCuts(int numLayers)
154
    {
155
    float[] cuts = new float[1];
156
    cuts[0] = 0.0f;
157
158
    return cuts;
159
    }
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 9e5b990e Leszek Koltunski
    float S = 0.08f;
400 886d1ebb Leszek Koltunski
    float R = 0.12f;
401 49cd8581 Leszek Koltunski
402
    if( face<COLORS )
403
      {
404 9e5b990e Leszek Koltunski
      factory.drawIvyCornerSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S, R);
405 49cd8581 Leszek Koltunski
      }
406
    else
407
      {
408 9e5b990e Leszek Koltunski
      factory.drawIvyCenterSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S, R);
409 49cd8581 Leszek Koltunski
      }
410
    }
411
412
///////////////////////////////////////////////////////////////////////////////////////////////////
413
414
  float returnMultiplier()
415
    {
416
    return 2.0f;
417
    }
418
419
///////////////////////////////////////////////////////////////////////////////////////////////////
420
421 a64e07d0 Leszek Koltunski
  float[] getRowChances(int numLayers)
422 49cd8581 Leszek Koltunski
    {
423
    float[] chances = new float[2];
424
    chances[0] = 0.5f;
425
    chances[1] = 1.0f;
426
427
    return chances;
428
    }
429
430
///////////////////////////////////////////////////////////////////////////////////////////////////
431
// PUBLIC API
432
433
  public Static3D[] getRotationAxis()
434
    {
435
    return ROT_AXIS;
436
    }
437
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439
440
  public int getBasicAngle()
441
    {
442
    return 3;
443
    }
444
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446
447 5043d5d0 Leszek Koltunski
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
448 49cd8581 Leszek Koltunski
    {
449 5043d5d0 Leszek Koltunski
    if( num==0 )
450 49cd8581 Leszek Koltunski
      {
451 5043d5d0 Leszek Koltunski
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
452 49cd8581 Leszek Koltunski
      }
453
    else
454
      {
455 bbc6471c Leszek Koltunski
      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
456 5043d5d0 Leszek Koltunski
      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
457 49cd8581 Leszek Koltunski
      }
458
459
    float rowFloat = rnd.nextFloat();
460
461
    for(int row=0; row<mRowChances.length; row++)
462
      {
463 bbc6471c Leszek Koltunski
      if( rowFloat<=mRowChances[row] )
464
        {
465 5043d5d0 Leszek Koltunski
        scramble[num][1] = row;
466 bbc6471c Leszek Koltunski
        break;
467
        }
468 49cd8581 Leszek Koltunski
      }
469
470 5043d5d0 Leszek Koltunski
    switch( rnd.nextInt(2) )
471
      {
472
      case 0: scramble[num][2] = -1; break;
473
      case 1: scramble[num][2] =  1; break;
474
      }
475 49cd8581 Leszek Koltunski
    }
476
477
///////////////////////////////////////////////////////////////////////////////////////////////////
478
// The Ivy is solved if and only if:
479
//
480
// 1) all 4 of its corner cubits are rotated with the same quat
481
// 2) all its face cubits are rotated with the same quat like the corner ones,
482
//    and optionally they also might be upside down.
483
//
484
// i.e.
485
// cubits [4] and [5] - might be extra QUAT[1]
486
// cubits [6] and [7] - might be extra QUAT[2]
487
// cubits [8] and [9] - might be extra QUAT[3]
488
489
  public boolean isSolved()
490
    {
491
    int q1,q = CUBITS[0].mQuatIndex;
492
493
    if( CUBITS[1].mQuatIndex == q &&
494
        CUBITS[2].mQuatIndex == q &&
495
        CUBITS[3].mQuatIndex == q  )
496
      {
497
      q1 = mulQuat(q,1);
498
      if( CUBITS[4].mQuatIndex != q && CUBITS[4].mQuatIndex != q1 ) return false;
499
      if( CUBITS[5].mQuatIndex != q && CUBITS[5].mQuatIndex != q1 ) return false;
500
501
      q1 = mulQuat(q,2);
502
      if( CUBITS[6].mQuatIndex != q && CUBITS[6].mQuatIndex != q1 ) return false;
503
      if( CUBITS[7].mQuatIndex != q && CUBITS[7].mQuatIndex != q1 ) return false;
504
505
      q1 = mulQuat(q,3);
506
      if( CUBITS[8].mQuatIndex != q && CUBITS[8].mQuatIndex != q1 ) return false;
507
      if( CUBITS[9].mQuatIndex != q && CUBITS[9].mQuatIndex != q1 ) return false;
508
509
      return true;
510
      }
511
512
    return false;
513
    }
514
515
///////////////////////////////////////////////////////////////////////////////////////////////////
516
// only needed for solvers - there are no Ivy solvers ATM)
517
518
  public String retObjectString()
519
    {
520
    return "";
521
    }
522 6fd4a72c Leszek Koltunski
523
///////////////////////////////////////////////////////////////////////////////////////////////////
524
525
  public int getObjectName(int numLayers)
526
    {
527
    return R.string.ivy2;
528
    }
529
530
///////////////////////////////////////////////////////////////////////////////////////////////////
531
532
  public int getInventor(int numLayers)
533
    {
534
    return R.string.ivy2_inventor;
535
    }
536
537
///////////////////////////////////////////////////////////////////////////////////////////////////
538
539
  public int getComplexity(int numLayers)
540
    {
541
    return 1;
542
    }
543 49cd8581 Leszek Koltunski
}