Project

General

Profile

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

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

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 a57e6870 Leszek Koltunski
  TwistyBandagedAbstract(int[] numL, Static4D quat, Static3D move, DistortedTexture texture,
84 ecf3d6e3 Leszek Koltunski
                         MeshSquare mesh, DistortedEffects effects, Resources res, int scrWidth)
85 29b82486 Leszek Koltunski
    {
86 a57e6870 Leszek Koltunski
    super(numL, numL[0], 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 a57e6870 Leszek Koltunski
  protected int[] getSolvedQuats(int cubit, int[] numLayers)
132 29b82486 Leszek Koltunski
    {
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 a57e6870 Leszek Koltunski
  protected ObjectShape getObjectShape(int cubit, int[] numLayers)
165 29b82486 Leszek Koltunski
    {
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 a57e6870 Leszek Koltunski
  protected Static4D getQuat(int cubit, int[] numLayers)
229 29b82486 Leszek Koltunski
    {
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 a57e6870 Leszek Koltunski
  protected int getNumCubitVariants(int[] numLayers)
249 29b82486 Leszek Koltunski
    {
250
    return mDimensions.length;
251
    }
252
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254
255 a57e6870 Leszek Koltunski
  protected int getCubitVariant(int cubit, int[] numLayers)
256 29b82486 Leszek Koltunski
    {
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 a57e6870 Leszek Koltunski
  protected float[][] getCubitPositions(int[] numLayers)
312 29b82486 Leszek Koltunski
    {
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 a57e6870 Leszek Koltunski
  protected float[][] getCuts(int[] numLayers)
335 29b82486 Leszek Koltunski
    {
336 a57e6870 Leszek Koltunski
    int numL = numLayers[0];
337
338
    if( numL<2 ) return null;
339 29b82486 Leszek Koltunski
340
    if( mCuts==null )
341
      {
342 a57e6870 Leszek Koltunski
      mCuts = new float[3][numL-1];
343 29b82486 Leszek Koltunski
344 a57e6870 Leszek Koltunski
      for(int i=0; i<numL-1; i++)
345 29b82486 Leszek Koltunski
        {
346 a57e6870 Leszek Koltunski
        float cut = (2-numL)*0.5f + i;
347 29b82486 Leszek Koltunski
        mCuts[0][i] = cut;
348
        mCuts[1][i] = cut;
349
        mCuts[2][i] = cut;
350
        }
351
      }
352
353
    return mCuts;
354
    }
355
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357
358 a57e6870 Leszek Koltunski
  private void getLayerRotatable(int[] numLayers)
359 29b82486 Leszek Koltunski
    {
360
    if( mLayerRotatable==null )
361
      {
362
      int numAxis = ROT_AXIS.length;
363
      mLayerRotatable = new boolean[numAxis][];
364 a57e6870 Leszek Koltunski
365
      for(int i=0; i<numAxis; i++)
366
        {
367
        mLayerRotatable[i] = new boolean[numLayers[i]];
368
        for(int j=0; j<numLayers[i]; j++) mLayerRotatable[i][j] = true;
369
        }
370 29b82486 Leszek Koltunski
      }
371
    }
372
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374
375
  protected int getSolvedFunctionIndex()
376
    {
377
    return 0;
378
    }
379
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381
382 a57e6870 Leszek Koltunski
  protected int getNumStickerTypes(int[] numLayers)
383 29b82486 Leszek Koltunski
    {
384
    return NUM_STICKERS;
385
    }
386
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388
389
  protected int getNumCubitFaces()
390
    {
391
    return 6;
392
    }
393
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395
396
  private int retStickerIndex(int horzSize, int vertSize)
397
    {
398
    switch(horzSize)
399
      {
400
      case 1: return 0;
401
      case 2: return vertSize==1 ? 1:3;
402
      case 3: return 2;
403
      }
404
405
    return 0;
406
    }
407
408
///////////////////////////////////////////////////////////////////////////////////////////////////
409
410
  private int getStickerIndex(int cubitface, int[] dim)
411
    {
412
    switch(cubitface)
413
      {
414
      case 0: case 1: return retStickerIndex(dim[2],dim[1]);
415
      case 2: case 3: return retStickerIndex(dim[0],dim[2]);
416
      case 4: case 5: return retStickerIndex(dim[0],dim[1]);
417
      }
418
419
    return 0;
420
    }
421
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423
424 a57e6870 Leszek Koltunski
  protected int getFaceColor(int cubit, int cubitface, int[] numLayers)
425 29b82486 Leszek Koltunski
    {
426
    if( mFaceMap==null )
427
      {
428
      // cubitface=2 when rotated by quatIndex=1 gets moved to position mFaceMap[2][1]
429
      mFaceMap = new int[][]
430
          {
431
              {0,0,5,2,4,2},
432
              {1,1,4,3,5,3},
433
              {2,4,2,1,1,4},
434
              {3,5,3,0,0,5},
435
              {4,3,0,4,3,0},
436
              {5,2,1,5,2,1}
437
          };
438
      }
439
440
    if( mAxisMap==null )
441
      {
442
      // axis=1 when rotated by quatIndex=2 gets moved to axis mAxisMap[1][2]
443
      mAxisMap = new int[][] { {0,0,2,1,2,1}, {1,2,1,0,0,2}, {2,1,0,2,1,0} };
444
      }
445
446
    int variant      = getCubitVariant(cubit,numLayers);
447
    int[] dim        = mDimensions[variant];
448
    float[] pos      = getCubitPosition(cubit);
449
    int stickerIndex = getStickerIndex(cubitface,dim);
450
    int quatIndex    = getQuatIndex(cubit);
451
    int face         = mFaceMap[cubitface][quatIndex];
452
    int multiplier   = (face%2)==0 ? 1:-1;
453
    int posIndex     = face/2;
454
    int dimIndex     = mAxisMap[posIndex][quatIndex];
455
456
    float position = 0.0f;
457
    int len = pos.length/3;
458
    for(int i=0; i<len; i++) position += pos[3*i+posIndex];
459
    position /= len;
460
461 a57e6870 Leszek Koltunski
    boolean reaches  = multiplier*position + dim[dimIndex]*0.5f > (numLayers[0]-1)*0.5f;
462 29b82486 Leszek Koltunski
463
    return reaches ? stickerIndex*NUM_FACE_COLORS + face : NUM_TEXTURES;
464
    }
465
466
///////////////////////////////////////////////////////////////////////////////////////////////////
467
// PUBLIC API
468
469
  public Static3D[] getRotationAxis()
470
    {
471
    return ROT_AXIS;
472
    }
473
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475
476
  public Movement getMovement()
477
    {
478
    if( mMovement==null )
479
      {
480 a57e6870 Leszek Koltunski
      int[] numLayers = getNumLayers();
481 29b82486 Leszek Koltunski
      if( mCuts==null ) getCuts(numLayers);
482
      getLayerRotatable(numLayers);
483 a57e6870 Leszek Koltunski
      mMovement = new Movement6(ROT_AXIS,mCuts,mLayerRotatable,numLayers[0],TYPE_NOT_SPLIT,ENABLED);
484 29b82486 Leszek Koltunski
      }
485
    return mMovement;
486
    }
487
488
///////////////////////////////////////////////////////////////////////////////////////////////////
489
490
  public int[] getBasicAngle()
491
    {
492
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
493
    return mBasicAngle;
494
    }
495
}