Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyBandagedAbstract.java @ d5380277

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.ObjectShape;
25
import org.distorted.helpers.ObjectSticker;
26
import org.distorted.helpers.ScrambleState;
27
import org.distorted.library.main.DistortedEffects;
28
import org.distorted.library.main.DistortedTexture;
29
import org.distorted.library.mesh.MeshSquare;
30
import org.distorted.library.type.Static3D;
31
import org.distorted.library.type.Static4D;
32

    
33
import java.util.Random;
34

    
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36

    
37
abstract class TwistyBandagedAbstract extends TwistyObject
38
{
39
  // the three rotation axis of a 3x3 Cube. Must be normalized.
40
  static final Static3D[] ROT_AXIS = new Static3D[]
41
         {
42
           new Static3D(1,0,0),
43
           new Static3D(0,1,0),
44
           new Static3D(0,0,1)
45
         };
46

    
47
  private static final int[] FACE_COLORS = new int[]
48
         {
49
           COLOR_YELLOW, COLOR_WHITE,
50
           COLOR_BLUE  , COLOR_GREEN,
51
           COLOR_RED   , COLOR_ORANGE
52
         };
53

    
54
  private static final int[][] mDimensions = new int[][]
55
        {
56
         {1,1,1},  // has to be X>=Z>=Y so that all
57
         {2,1,1},  // the faces are horizontal
58
         {3,1,1},
59
         {2,1,2},
60
         {2,2,2}
61
        };
62

    
63
  private static final int NUM_STICKERS = 4;
64

    
65
  private int[] mBasicAngle;
66
  private int mCurrState;
67
  private int mIndexExcluded;
68
  private int[][] mScrambleTable;
69
  private int[] mNumOccurences;
70
  private Static4D[] mQuats;
71
  private ObjectSticker[] mStickers;
72
  private Static4D[] mInitQuats;
73
  private int[][] mAxisMap;
74
  private int[][] mFaceMap;
75
  ScrambleState[] mStates;
76
  float[][] POSITIONS;
77
  int[] QUAT_INDICES;
78

    
79
///////////////////////////////////////////////////////////////////////////////////////////////////
80

    
81
  TwistyBandagedAbstract(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
82
                         DistortedEffects effects, int[][] moves, ObjectList list, Resources res, int scrWidth)
83
    {
84
    super(size, size, quat, texture, mesh, effects, moves, list, res, scrWidth);
85
    }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
  abstract float[][] getPositions();
90
  abstract int[] getQuatIndices();
91

    
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93

    
94
  private void initializeQuats()
95
    {
96
    mQuats = new Static4D[]
97
         {
98
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
99
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
100
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
101
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
102

    
103
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
104
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
105
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
106
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
107
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
108
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
109
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
110
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
111
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
112
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
113
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
114
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
115

    
116
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
117
         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
118
         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
119
         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
120
         new Static4D( -0.5f,  -0.5f,  -0.5f,   0.5f),
121
         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
122
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
123
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
124
         };
125
    }
126

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

    
129
  int[] getSolvedQuats(int cubit, int numLayers)
130
    {
131
    if( mQuats==null ) initializeQuats();
132
    int status = retCubitSolvedStatus(cubit,numLayers);
133
    return status<0 ? null : buildSolvedQuats(MovementCube.FACE_AXIS[status],mQuats);
134
    }
135

    
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

    
138
  int getNumCubits()
139
    {
140
    return getPositions().length;
141
    }
142

    
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

    
145
  private float[] getCubitPosition(int cubit)
146
    {
147
    float[][] pos = getPositions();
148

    
149
    return ( cubit>=0 && cubit< pos.length ) ? pos[cubit] : null;
150
    }
151

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

    
154
  private int getQuatIndex(int cubit)
155
    {
156
    int[] indices = getQuatIndices();
157
    return ( cubit>=0 && cubit< indices.length ) ? indices[cubit] : 0;
158
    }
159

    
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161

    
162
  ObjectShape getObjectShape(int cubit, int numLayers)
163
    {
164
    int variant = getCubitVariant(cubit,numLayers);
165

    
166
    final int[][] vert_indices =
167
      {
168
        {2,3,1,0},
169
        {7,6,4,5},
170
        {4,0,1,5},
171
        {7,3,2,6},
172
        {6,2,0,4},
173
        {3,7,5,1},
174
      };
175

    
176
    float defHeight = 0.048f;
177
    int[] bandIndices = new int[] { 0,0,1,1,2,2 };
178
    float[][] corners = new float[][] { {0.04f,0.15f} };
179
    int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
180
    int[] centerIndices = new int[] { 0,1,2,3,4,5,6,7 };
181

    
182
    int X = mDimensions[variant][0];
183
    int Y = mDimensions[variant][1];
184
    int Z = mDimensions[variant][2];
185

    
186
    int maxXY = Math.max(X,Y);
187
    int maxXZ = Math.max(X,Z);
188
    int maxYZ = Math.max(Y,Z);
189

    
190
    double[][] vertices =
191
      {
192
        {+0.5f*X,+0.5f*Y,+0.5f*Z},
193
        {+0.5f*X,+0.5f*Y,-0.5f*Z},
194
        {+0.5f*X,-0.5f*Y,+0.5f*Z},
195
        {+0.5f*X,-0.5f*Y,-0.5f*Z},
196
        {-0.5f*X,+0.5f*Y,+0.5f*Z},
197
        {-0.5f*X,+0.5f*Y,-0.5f*Z},
198
        {-0.5f*X,-0.5f*Y,+0.5f*Z},
199
        {-0.5f*X,-0.5f*Y,-0.5f*Z}
200
      };
201

    
202
    float[][] bands= new float[][]
203
      {
204
        {defHeight/maxYZ,65,0.25f,0.5f,5,1,2},
205
        {defHeight/maxXZ,65,0.25f,0.5f,5,1,2},
206
        {defHeight/maxXY,65,0.25f,0.5f,5,1,2}
207
      };
208

    
209
    float[][] centers = new float[][]
210
      {
211
        {+0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
212
        {+0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
213
        {+0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
214
        {+0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)},
215
        {-0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
216
        {-0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
217
        {-0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
218
        {-0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)}
219
      };
220

    
221
    return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
222
    }
223

    
224
///////////////////////////////////////////////////////////////////////////////////////////////////
225

    
226
  Static4D getQuat(int cubit, int numLayers)
227
    {
228
    if( mInitQuats ==null )
229
      {
230
      mInitQuats = new Static4D[]
231
        {
232
        new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),  // NULL
233
        new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),  // X
234
        new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),  // Y
235
        new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),  // Z
236
        new Static4D( -0.5f,  +0.5f,  -0.5f,  +0.5f),  // ZX
237
        new Static4D( +0.5f,  +0.5f,  +0.5f,  -0.5f),  // YX
238
        };
239
      }
240

    
241
    return mInitQuats[getQuatIndex(cubit)];
242
    }
243

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245

    
246
  int getNumCubitVariants(int numLayers)
247
    {
248
    return mDimensions.length;
249
    }
250

    
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252

    
253
  int getCubitVariant(int cubit, int numLayers)
254
    {
255
    float[][] pos = getPositions();
256

    
257
    if( cubit>=0 && cubit<pos.length )
258
      {
259
      int numPoints = pos[cubit].length/3;
260
      return numPoints==8 ? 4 : numPoints-1;
261
      }
262

    
263
    return 1;
264
    }
265

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

    
268
  int getColor(int face)
269
    {
270
    return FACE_COLORS[face];
271
    }
272

    
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
  ObjectSticker retSticker(int face)
276
    {
277
    if( mStickers==null )
278
      {
279
      mStickers = new ObjectSticker[NUM_STICKERS];
280

    
281
      int[][] stickerDimensions = new int[][]
282
        {
283
         {1,1},  // dimensions of the faces of
284
         {2,1},  // the cuboids defined in mDimensions
285
         {3,1},
286
         {2,2}
287
        };
288

    
289
      for(int s=0; s<NUM_STICKERS; s++)
290
        {
291
        float X = stickerDimensions[s][0];
292
        float Y = stickerDimensions[s][1];
293
        float MAX = Math.max(X,Y);
294
        X /= (2*MAX);
295
        Y /= (2*MAX);
296

    
297
        float R = 0.10f / MAX;
298
        float S = 0.08f / MAX;
299
        float[] coords = { -X,-Y, +X,-Y, +X,+Y, -X,+Y};
300
        float[] radii = new float[] {R,R,R,R};
301
        mStickers[s] = new ObjectSticker(coords,null,radii,S);
302
        }
303
      }
304

    
305
    return mStickers[face/NUM_FACES];
306
    }
307

    
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309

    
310
  float[][] getCubitPositions(int size)
311
    {
312
    int numCubits = getNumCubits();
313
    float[][] tmp = new float[numCubits][];
314

    
315
    for(int cubit=0; cubit<numCubits; cubit++)
316
      {
317
      tmp[cubit] = getCubitPosition(cubit);
318
      }
319

    
320
    return tmp;
321
    }
322

    
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324

    
325
  Static4D[] getQuats()
326
    {
327
    if( mQuats==null ) initializeQuats();
328
    return mQuats;
329
    }
330

    
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332

    
333
  boolean shouldResetTextureMaps()
334
    {
335
    return false;
336
    }
337

    
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339

    
340
  int getNumFaces()
341
    {
342
    return FACE_COLORS.length;
343
    }
344

    
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346

    
347
  float[][] getCuts(int numLayers)
348
    {
349
    float[][] cuts = new float[3][numLayers-1];
350

    
351
    for(int i=0; i<numLayers-1; i++)
352
      {
353
      float cut = (2-numLayers)*0.5f + i;
354
      cuts[0][i] = cut;
355
      cuts[1][i] = cut;
356
      cuts[2][i] = cut;
357
      }
358

    
359
    return cuts;
360
    }
361

    
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

    
364
  int getSolvedFunctionIndex()
365
    {
366
    return 0;
367
    }
368

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

    
371
  int getNumStickerTypes(int numLayers)
372
    {
373
    return NUM_STICKERS;
374
    }
375

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

    
378
  int getNumCubitFaces()
379
    {
380
    return FACE_COLORS.length;
381
    }
382

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

    
385
  float getScreenRatio()
386
    {
387
    return 0.5f;
388
    }
389

    
390
///////////////////////////////////////////////////////////////////////////////////////////////////
391

    
392
  private int retStickerIndex(int horzSize, int vertSize)
393
    {
394
    switch(horzSize)
395
      {
396
      case 1: return 0;
397
      case 2: return vertSize==1 ? 1:3;
398
      case 3: return 2;
399
      }
400

    
401
    return 0;
402
    }
403

    
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405

    
406
  private int getStickerIndex(int cubitface, int[] dim)
407
    {
408
    switch(cubitface)
409
      {
410
      case 0: case 1: return retStickerIndex(dim[2],dim[1]);
411
      case 2: case 3: return retStickerIndex(dim[0],dim[2]);
412
      case 4: case 5: return retStickerIndex(dim[0],dim[1]);
413
      }
414

    
415
    return 0;
416
    }
417

    
418
///////////////////////////////////////////////////////////////////////////////////////////////////
419

    
420
  int getFaceColor(int cubit, int cubitface, int numLayers)
421
    {
422
    if( mFaceMap==null )
423
      {
424
      // cubitface=2 when rotated by quatIndex=1 gets moved to position mFaceMap[2][1]
425
      mFaceMap = new int[][]
426
          {
427
              {0,0,5,2,4,2},
428
              {1,1,4,3,5,3},
429
              {2,4,2,1,1,4},
430
              {3,5,3,0,0,5},
431
              {4,3,0,4,3,0},
432
              {5,2,1,5,2,1}
433
          };
434
      }
435

    
436
    if( mAxisMap==null )
437
      {
438
      // axis=1 when rotated by quatIndex=2 gets moved to axis mAxisMap[1][2]
439
      mAxisMap = new int[][] { {0,0,2,1,2,1}, {1,2,1,0,0,2}, {2,1,0,2,1,0} };
440
      }
441

    
442
    int variant      = getCubitVariant(cubit,numLayers);
443
    int[] dim        = mDimensions[variant];
444
    float[] pos      = getCubitPosition(cubit);
445
    int stickerIndex = getStickerIndex(cubitface,dim);
446
    int quatIndex    = getQuatIndex(cubit);
447
    int face         = mFaceMap[cubitface][quatIndex];
448
    int multiplier   = (face%2)==0 ? 1:-1;
449
    int posIndex     = face/2;
450
    int dimIndex     = mAxisMap[posIndex][quatIndex];
451

    
452
    float position = 0.0f;
453
    int len = pos.length/3;
454
    for(int i=0; i<len; i++) position += pos[3*i+posIndex];
455
    position /= len;
456

    
457
    boolean reaches  = multiplier*position + dim[dimIndex]*0.5f > (numLayers-1)*0.5f;
458

    
459
    return reaches ? stickerIndex*NUM_FACES + face : NUM_TEXTURES;
460
    }
461

    
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463

    
464
  float returnMultiplier()
465
    {
466
    return getNumLayers();
467
    }
468

    
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

    
471
  private void initializeScrambling()
472
    {
473
    int numLayers = getNumLayers();
474

    
475
    if( mScrambleTable ==null )
476
      {
477
      mScrambleTable = new int[NUM_AXIS][numLayers];
478
      }
479
    if( mNumOccurences ==null )
480
      {
481
      int max=0;
482

    
483
      for (ScrambleState mState : mStates)
484
        {
485
        int tmp = mState.getTotal(-1);
486
        if (max < tmp) max = tmp;
487
        }
488

    
489
      mNumOccurences = new int[max];
490
      }
491

    
492
    for(int i=0; i<NUM_AXIS; i++)
493
      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
494
    }
495

    
496
///////////////////////////////////////////////////////////////////////////////////////////////////
497
// PUBLIC API
498

    
499
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
500
    {
501
    if( curr==0 )
502
      {
503
      mCurrState     = 0;
504
      mIndexExcluded =-1;
505
      initializeScrambling();
506
      }
507

    
508
    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
509

    
510
    scramble[curr][0] = info[0];
511
    scramble[curr][1] = info[1];
512
    scramble[curr][2] = info[2];
513

    
514
    mCurrState     = info[3];
515
    mIndexExcluded = info[0];
516
    }
517

    
518
///////////////////////////////////////////////////////////////////////////////////////////////////
519

    
520
  public Static3D[] getRotationAxis()
521
    {
522
    return ROT_AXIS;
523
    }
524

    
525
///////////////////////////////////////////////////////////////////////////////////////////////////
526

    
527
  public int[] getBasicAngle()
528
    {
529
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
530
    return mBasicAngle;
531
    }
532
}
(19-19/41)