Project

General

Profile

Download (15.8 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyBandagedAbstract.java @ 8592461c

1 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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.objectlib.objects;
21
22
import static org.distorted.objectlib.main.Movement.TYPE_NOT_SPLIT;
23
24
import android.content.res.Resources;
25
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
32
import org.distorted.objectlib.main.Movement;
33
import org.distorted.objectlib.main.Movement6;
34 198c5bf0 Leszek Koltunski
import org.distorted.objectlib.helpers.ObjectShape;
35
import org.distorted.objectlib.helpers.ObjectSticker;
36
import org.distorted.objectlib.helpers.ScrambleState;
37 8592461c Leszek Koltunski
import org.distorted.objectlib.main.ObjectControl;
38 29b82486 Leszek Koltunski
import org.distorted.objectlib.main.Twisty6;
39
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41
42
abstract class TwistyBandagedAbstract extends Twisty6
43
{
44
  // the three rotation axis of a 3x3 Cube. Must be normalized.
45
  static final Static3D[] ROT_AXIS = new Static3D[]
46
         {
47
           new Static3D(1,0,0),
48
           new Static3D(0,1,0),
49
           new Static3D(0,0,1)
50
         };
51
52
  private static final int[][] mDimensions = new int[][]
53
        {
54
         {1,1,1},  // has to be X>=Z>=Y so that all
55
         {2,1,1},  // the faces are horizontal
56
         {3,1,1},
57
         {2,1,2},
58
         {2,2,2}
59
        };
60
61
  private static final int[][][] ENABLED = new int[][][]
62
      {
63
          {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}},
64
      };
65
66
  private static final int NUM_STICKERS = 4;
67
68
  private int[] mBasicAngle;
69
  private Static4D[] mQuats;
70
  private ObjectSticker[] mStickers;
71
  private Static4D[] mInitQuats;
72
  private int[][] mAxisMap;
73
  private int[][] mFaceMap;
74
  private float[][] mCuts;
75
  private boolean[][] mLayerRotatable;
76
  private Movement mMovement;
77
  ScrambleState[] mStates;
78
  float[][] POSITIONS;
79
  int[] QUAT_INDICES;
80
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82
83 ecf3d6e3 Leszek Koltunski
  TwistyBandagedAbstract(int size, Static4D quat, Static3D move, DistortedTexture texture,
84
                         MeshSquare mesh, DistortedEffects effects, Resources res, int scrWidth)
85 29b82486 Leszek Koltunski
    {
86 ecf3d6e3 Leszek Koltunski
    super(size, size, quat, move, texture, mesh, effects, res, scrWidth);
87 29b82486 Leszek Koltunski
    }
88
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90
91
  abstract float[][] getPositions();
92
  abstract int[] getQuatIndices();
93
94
///////////////////////////////////////////////////////////////////////////////////////////////////
95
96
  private void initializeQuats()
97
    {
98
    mQuats = new Static4D[]
99
         {
100
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
101
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
102
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
103
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
104
105
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
106
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
107
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
108
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
109
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
110
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
111
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
112
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
113
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
114
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
115
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
116
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
117
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
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
125
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
126
         };
127
    }
128
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130
131
  protected int[] getSolvedQuats(int cubit, int numLayers)
132
    {
133
    if( mQuats==null ) initializeQuats();
134
    int status = retCubitSolvedStatus(cubit,numLayers);
135
    return status<0 ? null : buildSolvedQuats(Movement6.FACE_AXIS[status],mQuats);
136
    }
137
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139
140
  int getNumCubits()
141
    {
142
    return getPositions().length;
143
    }
144
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146
147
  private float[] getCubitPosition(int cubit)
148
    {
149
    float[][] pos = getPositions();
150
151
    return ( cubit>=0 && cubit< pos.length ) ? pos[cubit] : null;
152
    }
153
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155
156
  private int getQuatIndex(int cubit)
157
    {
158
    int[] indices = getQuatIndices();
159
    return ( cubit>=0 && cubit< indices.length ) ? indices[cubit] : 0;
160
    }
161
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163
164
  protected ObjectShape getObjectShape(int cubit, int numLayers)
165
    {
166
    int variant = getCubitVariant(cubit,numLayers);
167
168
    final int[][] vert_indices =
169
      {
170
        {2,3,1,0},
171
        {7,6,4,5},
172
        {4,0,1,5},
173
        {7,3,2,6},
174
        {6,2,0,4},
175
        {3,7,5,1},
176
      };
177
178
    float defHeight = 0.048f;
179
    int[] bandIndices = new int[] { 0,0,1,1,2,2 };
180
    float[][] corners = new float[][] { {0.04f,0.15f} };
181
    int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
182
    int[] centerIndices = new int[] { 0,1,2,3,4,5,6,7 };
183
184
    int X = mDimensions[variant][0];
185
    int Y = mDimensions[variant][1];
186
    int Z = mDimensions[variant][2];
187
188
    int maxXY = Math.max(X,Y);
189
    int maxXZ = Math.max(X,Z);
190
    int maxYZ = Math.max(Y,Z);
191
192
    double[][] vertices =
193
      {
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
        {-0.5f*X,-0.5f*Y,+0.5f*Z},
201
        {-0.5f*X,-0.5f*Y,-0.5f*Z}
202
      };
203
204
    float[][] bands= new float[][]
205
      {
206
        {defHeight/maxYZ,65,0.25f,0.5f,5,1,2},
207
        {defHeight/maxXZ,65,0.25f,0.5f,5,1,2},
208
        {defHeight/maxXY,65,0.25f,0.5f,5,1,2}
209
      };
210
211
    float[][] centers = new float[][]
212
      {
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
        {-0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
220
        {-0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)}
221
      };
222
223
    return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
224
    }
225
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227
228
  protected Static4D getQuat(int cubit, int numLayers)
229
    {
230
    if( mInitQuats ==null )
231
      {
232
      mInitQuats = new Static4D[]
233
        {
234
        new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),  // NULL
235
        new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),  // X
236
        new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),  // Y
237
        new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),  // Z
238
        new Static4D( -0.5f,  +0.5f,  -0.5f,  +0.5f),  // ZX
239
        new Static4D( +0.5f,  +0.5f,  +0.5f,  -0.5f),  // YX
240
        };
241
      }
242
243
    return mInitQuats[getQuatIndex(cubit)];
244
    }
245
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247
248
  protected int getNumCubitVariants(int numLayers)
249
    {
250
    return mDimensions.length;
251
    }
252
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254
255
  protected int getCubitVariant(int cubit, int numLayers)
256
    {
257
    float[][] pos = getPositions();
258
259
    if( cubit>=0 && cubit<pos.length )
260
      {
261
      int numPoints = pos[cubit].length/3;
262
      return numPoints==8 ? 4 : numPoints-1;
263
      }
264
265
    return 1;
266
    }
267
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269
270
  protected ObjectSticker retSticker(int face)
271
    {
272
    if( mStickers==null )
273
      {
274
      mStickers = new ObjectSticker[NUM_STICKERS];
275
276
      int[][] stickerDimensions = new int[][]
277
        {
278
         {1,1},  // dimensions of the faces of
279
         {2,1},  // the cuboids defined in mDimensions
280
         {3,1},
281
         {2,2}
282
        };
283
284
      for(int s=0; s<NUM_STICKERS; s++)
285
        {
286
        float X = stickerDimensions[s][0];
287
        float Y = stickerDimensions[s][1];
288
        float MAX = Math.max(X,Y);
289
        X /= (2*MAX);
290
        Y /= (2*MAX);
291
292 8592461c Leszek Koltunski
        float radius = 0.10f / MAX;
293
        float stroke = 0.08f / MAX;
294 29b82486 Leszek Koltunski
        float[] coords = { -X,-Y, +X,-Y, +X,+Y, -X,+Y};
295 8592461c Leszek Koltunski
        float[] radii = new float[] {radius,radius,radius,radius};
296
297
        if( ObjectControl.isInIconMode() )
298
          {
299
          stroke*=2.0f;
300
          }
301
302
        mStickers[s] = new ObjectSticker(coords,null,radii,stroke);
303 29b82486 Leszek Koltunski
        }
304
      }
305
306
    return mStickers[face/NUM_FACE_COLORS];
307
    }
308
309
///////////////////////////////////////////////////////////////////////////////////////////////////
310
311
  protected float[][] getCubitPositions(int size)
312
    {
313
    int numCubits = getNumCubits();
314
    float[][] tmp = new float[numCubits][];
315
316
    for(int cubit=0; cubit<numCubits; cubit++)
317
      {
318
      tmp[cubit] = getCubitPosition(cubit);
319
      }
320
321
    return tmp;
322
    }
323
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325
326
  protected Static4D[] getQuats()
327
    {
328
    if( mQuats==null ) initializeQuats();
329
    return mQuats;
330
    }
331
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333
334
  protected float[][] getCuts(int numLayers)
335
    {
336
    if( numLayers<2 ) return null;
337
338
    if( mCuts==null )
339
      {
340
      mCuts = new float[3][numLayers-1];
341
342
      for(int i=0; i<numLayers-1; i++)
343
        {
344
        float cut = (2-numLayers)*0.5f + i;
345
        mCuts[0][i] = cut;
346
        mCuts[1][i] = cut;
347
        mCuts[2][i] = cut;
348
        }
349
      }
350
351
    return mCuts;
352
    }
353
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355
356
  private void getLayerRotatable(int numLayers)
357
    {
358
    if( mLayerRotatable==null )
359
      {
360
      int numAxis = ROT_AXIS.length;
361
      boolean[] tmp = new boolean[numLayers];
362
      for(int i=0; i<numLayers; i++) tmp[i] = true;
363
      mLayerRotatable = new boolean[numAxis][];
364
      for(int i=0; i<numAxis; i++) mLayerRotatable[i] = tmp;
365
      }
366
    }
367
368
///////////////////////////////////////////////////////////////////////////////////////////////////
369
370
  protected int getSolvedFunctionIndex()
371
    {
372
    return 0;
373
    }
374
375
///////////////////////////////////////////////////////////////////////////////////////////////////
376
377
  protected int getNumStickerTypes(int numLayers)
378
    {
379
    return NUM_STICKERS;
380
    }
381
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383
384
  protected int getNumCubitFaces()
385
    {
386
    return 6;
387
    }
388
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390
391
  private int retStickerIndex(int horzSize, int vertSize)
392
    {
393
    switch(horzSize)
394
      {
395
      case 1: return 0;
396
      case 2: return vertSize==1 ? 1:3;
397
      case 3: return 2;
398
      }
399
400
    return 0;
401
    }
402
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404
405
  private int getStickerIndex(int cubitface, int[] dim)
406
    {
407
    switch(cubitface)
408
      {
409
      case 0: case 1: return retStickerIndex(dim[2],dim[1]);
410
      case 2: case 3: return retStickerIndex(dim[0],dim[2]);
411
      case 4: case 5: return retStickerIndex(dim[0],dim[1]);
412
      }
413
414
    return 0;
415
    }
416
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418
419
  protected int getFaceColor(int cubit, int cubitface, int numLayers)
420
    {
421
    if( mFaceMap==null )
422
      {
423
      // cubitface=2 when rotated by quatIndex=1 gets moved to position mFaceMap[2][1]
424
      mFaceMap = new int[][]
425
          {
426
              {0,0,5,2,4,2},
427
              {1,1,4,3,5,3},
428
              {2,4,2,1,1,4},
429
              {3,5,3,0,0,5},
430
              {4,3,0,4,3,0},
431
              {5,2,1,5,2,1}
432
          };
433
      }
434
435
    if( mAxisMap==null )
436
      {
437
      // axis=1 when rotated by quatIndex=2 gets moved to axis mAxisMap[1][2]
438
      mAxisMap = new int[][] { {0,0,2,1,2,1}, {1,2,1,0,0,2}, {2,1,0,2,1,0} };
439
      }
440
441
    int variant      = getCubitVariant(cubit,numLayers);
442
    int[] dim        = mDimensions[variant];
443
    float[] pos      = getCubitPosition(cubit);
444
    int stickerIndex = getStickerIndex(cubitface,dim);
445
    int quatIndex    = getQuatIndex(cubit);
446
    int face         = mFaceMap[cubitface][quatIndex];
447
    int multiplier   = (face%2)==0 ? 1:-1;
448
    int posIndex     = face/2;
449
    int dimIndex     = mAxisMap[posIndex][quatIndex];
450
451
    float position = 0.0f;
452
    int len = pos.length/3;
453
    for(int i=0; i<len; i++) position += pos[3*i+posIndex];
454
    position /= len;
455
456
    boolean reaches  = multiplier*position + dim[dimIndex]*0.5f > (numLayers-1)*0.5f;
457
458
    return reaches ? stickerIndex*NUM_FACE_COLORS + face : NUM_TEXTURES;
459
    }
460
461
///////////////////////////////////////////////////////////////////////////////////////////////////
462
// PUBLIC API
463
464
  public Static3D[] getRotationAxis()
465
    {
466
    return ROT_AXIS;
467
    }
468
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470
471
  public Movement getMovement()
472
    {
473
    if( mMovement==null )
474
      {
475
      int numLayers = getNumLayers();
476
      if( mCuts==null ) getCuts(numLayers);
477
      getLayerRotatable(numLayers);
478
      mMovement = new Movement6(ROT_AXIS,mCuts,mLayerRotatable,numLayers,TYPE_NOT_SPLIT,ENABLED);
479
      }
480
    return mMovement;
481
    }
482
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484
485
  public int[] getBasicAngle()
486
    {
487
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
488
    return mBasicAngle;
489
    }
490
}