Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistySquare2.java @ 9c06394a

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 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
class TwistySquare2 extends TwistySquare
40
{
41
  private static final float Y = 0.75f + X/2;
42
  private static final float Z = 0.75f - X/2;
43

    
44
  private static final int[] QUAT_NUMBER = new int[]
45
    {
46
      0, 6,
47
      0, 9, 6, 3, 18, 15, 12, 21,
48
      0, 9, 6, 3, 0, 9, 6, 3,
49
      15, 12, 21, 18, 15, 12, 21, 18
50
    };
51

    
52
  // centers of the 2 middles + 8 edges + 8 left corners + 8 right corners
53
  private static final float[][] CENTERS = new float[][]
54
    {
55
      { 1.5f, 0.0f, 0.0f },
56
      {-1.5f, 0.0f, 0.0f },
57

    
58
      { 0.0f, 1.0f, 1.5f },
59
      { 1.5f, 1.0f, 0.0f },
60
      { 0.0f, 1.0f,-1.5f },
61
      {-1.5f, 1.0f, 0.0f },
62
      { 0.0f,-1.0f, 1.5f },
63
      { 1.5f,-1.0f, 0.0f },
64
      { 0.0f,-1.0f,-1.5f },
65
      {-1.5f,-1.0f, 0.0f },
66

    
67
      {    Y, 1.0f, 1.5f },
68
      { 1.5f, 1.0f,   -Y },
69
      {   -Y, 1.0f,-1.5f },
70
      {-1.5f, 1.0f,    Y },
71
      {    Y,-1.0f, 1.5f },
72
      { 1.5f,-1.0f,   -Y },
73
      {   -Y,-1.0f,-1.5f },
74
      {-1.5f,-1.0f,    Y },
75

    
76
      { 1.5f, 1.0f,    Y },
77
      {    Y, 1.0f,-1.5f },
78
      {-1.5f, 1.0f,   -Y },
79
      {   -Y, 1.0f, 1.5f },
80
      { 1.5f,-1.0f,    Y },
81
      {    Y,-1.0f,-1.5f },
82
      {-1.5f,-1.0f,   -Y },
83
      {   -Y,-1.0f, 1.5f },
84
    };
85

    
86
  private static final double[][] VERTICES_CORNER = new double[][]
87
    {
88
      { X-1.5+Z, 0.5,  0.0 },
89
      {       Z, 0.5,  0.0 },
90
      {  -1.5+Z, 0.5, -1.5 },
91
      { X-1.5+Z,-0.5,  0.0 },
92
      {       Z,-0.5,  0.0 },
93
      {  -1.5+Z,-0.5, -1.5 }
94
    };
95

    
96
  private static final int[][] VERT_INDEXES_CORNER = new int[][]
97
    {
98
      {0,1,2},   // counterclockwise!
99
      {5,4,3},
100
      {3,4,1,0},
101
      {4,5,2,1},
102
      {5,3,0,2}
103
    };
104

    
105
  private static final float[][] STICKERS = new float[][]
106
    {
107
      { -0.5f, -0.26289170f, 0.5f, -0.26289170f, 0.5f, 0.26289170f, -0.5f, 0.26289170f }, // middle front
108
      { -0.5f, -0.16666667f, 0.5f, -0.16666667f, 0.5f, 0.16666667f, -0.5f, 0.16666667f }, // middle right
109
      { -0.5f, -0.45534182f, 0.5f, -0.45534182f, 0.5f, 0.45534182f, -0.5f, 0.45534182f }, // middle back
110
      { -0.20096192f, -0.25f, 0.20096192f, -0.25f, 0.0f, 0.5f },                          // edge top
111
      { -0.40192384f, -0.5f, 0.40192384f, -0.5f, 0.40192384f, 0.5f, -0.40192384f, 0.5f }, // edge face
112
      { -0.11602539f, -0.25f, 0.4330127f, -0.25f, -0.3169873f, 0.5f }                     // corner top
113
    };
114

    
115
  private static final int NUM_STICKERS = STICKERS.length;
116

    
117
  private static final int[][] mStickerType = new int[][]
118
    {
119
      {  NUM_STICKERS,NUM_STICKERS,0,           1,           2,NUM_STICKERS },
120
      {             3,NUM_STICKERS,4,NUM_STICKERS,NUM_STICKERS,NUM_STICKERS },
121
      {             5,NUM_STICKERS,2,NUM_STICKERS,NUM_STICKERS,NUM_STICKERS },
122
      {  NUM_STICKERS,           5,2,NUM_STICKERS,NUM_STICKERS,NUM_STICKERS }
123
    };
124

    
125
  // YELLOW 0 WHITE 1 BLUE 2 GREEN 3 RED 4 ORANGE 5
126
  private static final int[][] mStickerColor = new int[][]
127
    {
128
      { 0, 0, 4, 0, 5, 0 }, // 0
129
      { 0, 0, 5, 1, 4, 0 },
130

    
131
      { 2, 0, 4, 0, 0, 0 }, // 2
132
      { 2, 0, 0, 0, 0, 0 },
133
      { 2, 0, 5, 0, 0, 0 },
134
      { 2, 0, 1, 0, 0, 0 },
135
      { 3, 0, 4, 0, 0, 0 },
136
      { 3, 0, 0, 0, 0, 0 },
137
      { 3, 0, 5, 0, 0, 0 },
138
      { 3, 0, 1, 0, 0, 0 },
139

    
140
      { 2, 0, 4, 0, 0, 0 }, // 10
141
      { 2, 0, 0, 0, 0, 0 },
142
      { 2, 0, 5, 0, 0, 0 },
143
      { 2, 0, 1, 0, 0, 0 },
144
      { 0, 3, 4, 0, 0, 0 },
145
      { 0, 3, 0, 0, 0, 0 },
146
      { 0, 3, 5, 0, 0, 0 },
147
      { 0, 3, 1, 0, 0, 0 },
148

    
149
      { 0, 2, 0, 0, 0, 0 }, // 18
150
      { 0, 2, 5, 0, 0, 0 },
151
      { 0, 2, 1, 0, 0, 0 },
152
      { 0, 2, 4, 0, 0, 0 },
153
      { 3, 0, 0, 0, 0, 0 },
154
      { 3, 0, 5, 0, 0, 0 },
155
      { 3, 0, 1, 0, 0, 0 },
156
      { 3, 0, 4, 0, 0, 0 },
157
    };
158

    
159
  private static final ObjectSticker[] mStickers;
160

    
161
  static
162
    {
163
    mStickers = new ObjectSticker[NUM_STICKERS];
164
    final float R1 = 0.06f;
165
    final float R2 = 0.04f;
166
    final float R3 = 0.11f;
167
    final float R4 = 0.03f;
168
    final float R5 = 0.11f;
169
    final float R6 = 0.025f;
170
    final float[][] radii  = { {R1,R1,R1,R1},{R2,R2,R2,R2},{R3,R3,R3,R3},{R4,R4,R4},{R5,R5,R5,R5},{R6,R6,R6} };
171
    final float[] strokes = { 0.05f,0.04f,0.09f,0.05f,0.08f,0.06f };
172

    
173
    for(int s=0; s<NUM_STICKERS; s++)
174
      {
175
      mStickers[s] = new ObjectSticker(STICKERS[s],null,radii[s],strokes[s]);
176
      }
177
    }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

    
181
  TwistySquare2(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
182
                DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
183
    {
184
    super(size, quat, texture, mesh, effects, moves, ObjectList.SQU2, res, scrWidth);
185
    }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
  private Static4D getQuat(int cubit)
190
    {
191
    return QUATS[QUAT_NUMBER[cubit]];
192
    }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

    
196
  MeshBase createCornerCubitMesh()
197
    {
198
    if( mMeshes[3]==null )
199
      {
200
      float[][] bands= new float[][]
201
        {
202
          {0.030f,35,0.9f,1.0f, 5,2,1},
203
          {0.001f,35,0.9f,1.0f, 5,2,1}
204
        };
205
      int[] bandIndexes   = new int[] { 0,0,0,1,1 };
206
      float[][] corners   = new float[][] { {0.05f,0.13f} };
207
      int[] cornerIndexes = new int[] { 0,0,-1,0,0,-1 };
208
      float[][] centers   = new float[][] { { 0.0f, 0.0f,-0.5f} };
209
      int[] centerIndexes = new int[] { 0,0,-1,0,0,-1 };
210

    
211
      FactoryCubit factory = FactoryCubit.getInstance();
212
      factory.createNewFaceTransform(VERTICES_CORNER,VERT_INDEXES_CORNER);
213
      mMeshes[3] = factory.createRoundedSolid(VERTICES_CORNER, VERT_INDEXES_CORNER,
214
                                              bands, bandIndexes,
215
                                              corners, cornerIndexes,
216
                                              centers, centerIndexes,
217
                                              getNumCubitFaces() );
218
      }
219
    return mMeshes[3].copy(true);
220
    }
221

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

    
224
  MeshBase createCubitMesh(int cubit, int numLayers)
225
    {
226
    if( mMeshes==null )
227
      {
228
      FactoryCubit factory = FactoryCubit.getInstance();
229
      factory.clear();
230
      mMeshes = new MeshBase[4];
231
      }
232

    
233
    MeshBase mesh;
234

    
235
         if( cubit< 2 ) mesh = createMiddleCubitMesh();
236
    else if( cubit<10 ) mesh = createEdgeCubitMesh();
237
    else                mesh = createCornerCubitMesh();
238

    
239
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
240
    mesh.apply(quat,0xffffffff,0);
241

    
242
    return mesh;
243
    }
244

    
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246

    
247
  ObjectSticker retSticker(int face)
248
    {
249
    return mStickers[face/NUM_FACES];
250
    }
251

    
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253

    
254
  float[][] getCubitPositions(int numLayers)
255
    {
256
    return CENTERS;
257
    }
258

    
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260

    
261
  int getNumStickerTypes(int numLayers)
262
    {
263
    return NUM_STICKERS;
264
    }
265

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267

    
268
  int getFaceColor(int cubit, int cubitface, int numLayers)
269
    {
270
    int type;
271

    
272
         if( cubit< 2             ) type = 0;
273
    else if( cubit<10             ) type = 1;
274
    else if( cubit>13 && cubit<22 ) type = 3;
275
    else                            type = 2;
276

    
277
    return mStickerType[type][cubitface]*FACE_COLORS.length + mStickerColor[cubit][cubitface];
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281
// PUBLIC API
282

    
283
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
284
    {
285
    int layer, nextAngle;
286

    
287
    if( curr==0 ) mLastRot = rnd.nextInt(4);
288

    
289
    switch(mLastRot)
290
      {
291
      case LAST_SL: layer = rnd.nextInt(2);
292
                    nextAngle = rnd.nextInt(12)-6;
293

    
294
                    if( nextAngle==0 )
295
                      {
296
                      layer = 1-layer;
297
                      nextAngle = (2*rnd.nextInt(2)-1)*(rnd.nextInt(5)+1);
298
                      }
299

    
300
                    scramble[curr][0] = 0;
301
                    scramble[curr][1] = 2*layer;
302
                    scramble[curr][2] = nextAngle;
303
                    mLastRot = layer==0 ? LAST_LO : LAST_UP;
304
                    break;
305
      case LAST_LO:
306
      case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
307
                    nextAngle = rnd.nextInt(12)-6;
308

    
309
                    if( nextAngle!=0 )
310
                      {
311
                      scramble[curr][0] = 0;
312
                      scramble[curr][1] = 2*layer;
313
                      scramble[curr][2] = nextAngle;
314
                      mLastRot = LAST_UL;
315
                      }
316
                    else
317
                      {
318
                      scramble[curr][0] = 1;
319
                      scramble[curr][1] = rnd.nextInt(2);
320
                      scramble[curr][2] = 1;
321
                      mLastRot = LAST_SL;
322
                      }
323
                    break;
324
      case LAST_UL: scramble[curr][0] = 1;
325
                    scramble[curr][1] = rnd.nextInt(2);
326
                    scramble[curr][2] = 1;
327
                    mLastRot = LAST_SL;
328
                    break;
329
      }
330
    }
331

    
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333
// Square-2 is solved iff
334
// a) all of its cubits are rotated with the same quat
335
// b) its two 'middle' cubits are rotated with the same quat, the 6 'front' and 6 'back'
336
// edges and corners with this quat multiplied by QUATS[18] (i.e. those are upside down)
337
// and all the 12 left and right edges and corners also with the same quat multiplied by
338
// QUATS[12] - i.e. also upside down.
339

    
340
  public boolean isSolved()
341
    {
342
    int index = CUBITS[0].mQuatIndex;
343

    
344
    if( CUBITS[1].mQuatIndex!=index ) return false;
345

    
346
    int indexX = mulQuat(index,12);  // QUATS[12] = 180deg (1,0,0)
347
    int indexZ = mulQuat(index,18);  // QUATS[18] = 180deg (0,0,1)
348

    
349
    for(int i=2; i<18; i+=2)
350
      {
351
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexZ ) return false;
352
      }
353
    for(int i=3; i<18; i+=2)
354
      {
355
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexX ) return false;
356
      }
357
    for(int i=18; i<NUM_CUBITS; i+=2)
358
      {
359
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexX ) return false;
360
      }
361
    for(int i=19; i<NUM_CUBITS; i+=2)
362
      {
363
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexZ ) return false;
364
      }
365

    
366
    return true;
367
    }
368

    
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370

    
371
  public int getObjectName(int numLayers)
372
    {
373
    return R.string.squa2;
374
    }
375

    
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377

    
378
  public int getInventor(int numLayers)
379
    {
380
    return R.string.squa2_inventor;
381
    }
382

    
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384

    
385
  public int getComplexity(int numLayers)
386
    {
387
    return 7;
388
    }
389
}
(40-40/41)