Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyBandagedAbstract.java @ 3e605536

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.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
///////////////////////////////////////////////////////////////////////////////////////////////////
33

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

    
44
  private static final int[] BASIC_ANGLE = new int[] { 4,4,4 };
45

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

    
53
  private static final Static4D[] QUATS = new Static4D[]
54
         {
55
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
56
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
57
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
58
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
59

    
60
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
61
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
62
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
63
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
64
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
65
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
66
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
67
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
68
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
69
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
70
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
71
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
72

    
73
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
74
         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
75
         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
76
         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
77
         new Static4D( -0.5f,  -0.5f,  -0.5f,   0.5f),
78
         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
79
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
80
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
81
         };
82

    
83
  private static final Static4D[] INIT_QUATS = new Static4D[]
84
        {
85
        new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),  // NULL
86
        new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),  // X
87
        new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),  // Y
88
        new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),  // Z
89
        new Static4D( -0.5f,  +0.5f,  -0.5f,  +0.5f),  // ZX
90
        new Static4D( +0.5f,  +0.5f,  +0.5f,  -0.5f),  // YX
91
        };
92

    
93
  private static final int[][] mDimensions = new int[][]
94
        {
95
         {1,1,1},  // has to be X>=Z>=Y so that all
96
         {2,1,1},  // the faces are horizontal
97
         {3,1,1},
98
         {2,1,2},
99
         {2,2,2}
100
        };
101

    
102
  private static final int[][] mStickerDimensions = new int[][]
103
        {
104
         {1,1},  // dimensions of the faces of
105
         {2,1},  // the cuboids defined above
106
         {3,1},
107
         {2,2}
108
        };
109

    
110
  private static final int[][] mFaceMap = new int[][] // cubitface=2 when rotated by
111
    {                                                 // quatIndex=1 gets moved to
112
        {0,0,5,2,4,2},                                // position mFaceMap[2][1]
113
        {1,1,4,3,5,3},
114
        {2,4,2,1,1,4},
115
        {3,5,3,0,0,5},
116
        {4,3,0,4,3,0},
117
        {5,2,1,5,2,1}
118
    };
119

    
120
  private static final int[][] mAxisMap = new int[][] // axis=1 when rotated by
121
    {                                                 // quatIndex=2 gets moved to
122
        {0,0,2,1,2,1},                                // axis mAxisMap[1][2]
123
        {1,2,1,0,0,2},
124
        {2,1,0,2,1,0}
125
    };
126

    
127
  private static final int NUM_STICKERS = mStickerDimensions.length;
128

    
129
  private static final ObjectSticker[] mStickers;
130

    
131
  static
132
    {
133
    mStickers = new ObjectSticker[NUM_STICKERS];
134

    
135
    for(int s=0; s<NUM_STICKERS; s++)
136
      {
137
      float X = mStickerDimensions[s][0];
138
      float Y = mStickerDimensions[s][1];
139
      float MAX = Math.max(X,Y);
140
      X /= (2*MAX);
141
      Y /= (2*MAX);
142

    
143
      float R = 0.10f / MAX;
144
      float S = 0.08f / MAX;
145
      float[] coords = { -X,-Y, +X,-Y, +X,+Y, -X,+Y};
146
      float[] radii = new float[] {R,R,R,R};
147
      mStickers[s] = new ObjectSticker(coords,null,radii,S);
148
      }
149
    }
150

    
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152

    
153
  TwistyBandagedAbstract(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
154
                         DistortedEffects effects, int[][] moves, ObjectList list, Resources res, int scrWidth)
155
    {
156
    super(size, size, quat, texture, mesh, effects, moves, list, res, scrWidth);
157
    }
158

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160

    
161
  abstract float[][] getPositions();
162
  abstract int[] getQuatIndices();
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

    
166
  int getNumCubits()
167
    {
168
    return getPositions().length;
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172

    
173
  private float[] getCubitPosition(int cubit)
174
    {
175
    float[][] pos = getPositions();
176

    
177
    return ( cubit>=0 && cubit< pos.length ) ? pos[cubit] : null;
178
    }
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

    
182
  private int getQuatIndex(int cubit)
183
    {
184
    int[] indices = getQuatIndices();
185
    return ( cubit>=0 && cubit< indices.length ) ? indices[cubit] : 0;
186
    }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
  ObjectShape getObjectShape(int cubit, int numLayers)
191
    {
192
    int variant = getCubitVariant(cubit,numLayers);
193

    
194
    final int[][] vert_indices =
195
      {
196
        {2,3,1,0},
197
        {7,6,4,5},
198
        {4,0,1,5},
199
        {7,3,2,6},
200
        {6,2,0,4},
201
        {3,7,5,1},
202
      };
203

    
204
    float defHeight = 0.048f;
205
    int[] bandIndices = new int[] { 0,0,1,1,2,2 };
206
    float[][] corners = new float[][] { {0.04f,0.15f} };
207
    int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
208
    int[] centerIndices = new int[] { 0,1,2,3,4,5,6,7 };
209

    
210
    int X = mDimensions[variant][0];
211
    int Y = mDimensions[variant][1];
212
    int Z = mDimensions[variant][2];
213

    
214
    int maxXY = Math.max(X,Y);
215
    int maxXZ = Math.max(X,Z);
216
    int maxYZ = Math.max(Y,Z);
217

    
218
    double[][] vertices =
219
      {
220
        {+0.5f*X,+0.5f*Y,+0.5f*Z},
221
        {+0.5f*X,+0.5f*Y,-0.5f*Z},
222
        {+0.5f*X,-0.5f*Y,+0.5f*Z},
223
        {+0.5f*X,-0.5f*Y,-0.5f*Z},
224
        {-0.5f*X,+0.5f*Y,+0.5f*Z},
225
        {-0.5f*X,+0.5f*Y,-0.5f*Z},
226
        {-0.5f*X,-0.5f*Y,+0.5f*Z},
227
        {-0.5f*X,-0.5f*Y,-0.5f*Z}
228
      };
229

    
230
    float[][] bands= new float[][]
231
      {
232
        {defHeight/maxYZ,65,0.25f,0.5f,5,1,2},
233
        {defHeight/maxXZ,65,0.25f,0.5f,5,1,2},
234
        {defHeight/maxXY,65,0.25f,0.5f,5,1,2}
235
      };
236

    
237
    float[][] centers = new float[][]
238
      {
239
        {+0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
240
        {+0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
241
        {+0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
242
        {+0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)},
243
        {-0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
244
        {-0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
245
        {-0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
246
        {-0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)}
247
      };
248

    
249
    return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
250
    }
251

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

    
254
  Static4D getQuat(int cubit, int numLayers)
255
    {
256
    return INIT_QUATS[getQuatIndex(cubit)];
257
    }
258

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

    
261
  int getNumCubitVariants(int numLayers)
262
    {
263
    return mDimensions.length;
264
    }
265

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

    
268
  int getCubitVariant(int cubit, int numLayers)
269
    {
270
    float[][] pos = getPositions();
271

    
272
    if( cubit>=0 && cubit<pos.length )
273
      {
274
      int numPoints = pos[cubit].length/3;
275
      return numPoints==8 ? 4 : numPoints-1;
276
      }
277

    
278
    return 1;
279
    }
280

    
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

    
283
  int getColor(int face)
284
    {
285
    return FACE_COLORS[face];
286
    }
287

    
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

    
290
  ObjectSticker retSticker(int face)
291
    {
292
    return mStickers[face/NUM_FACES];
293
    }
294

    
295
///////////////////////////////////////////////////////////////////////////////////////////////////
296

    
297
  float[][] getCubitPositions(int size)
298
    {
299
    int numCubits = getNumCubits();
300
    float[][] tmp = new float[numCubits][];
301

    
302
    for(int cubit=0; cubit<numCubits; cubit++)
303
      {
304
      tmp[cubit] = getCubitPosition(cubit);
305
      }
306

    
307
    return tmp;
308
    }
309

    
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311

    
312
  Static4D[] getQuats()
313
    {
314
    return QUATS;
315
    }
316

    
317
///////////////////////////////////////////////////////////////////////////////////////////////////
318

    
319
  boolean shouldResetTextureMaps()
320
    {
321
    return false;
322
    }
323

    
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325

    
326
  int getNumFaces()
327
    {
328
    return FACE_COLORS.length;
329
    }
330

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

    
333
  float[][] getCuts(int numLayers)
334
    {
335
    float[][] cuts = new float[3][numLayers-1];
336

    
337
    for(int i=0; i<numLayers-1; i++)
338
      {
339
      float cut = (2-numLayers)*0.5f + i;
340
      cuts[0][i] = cut;
341
      cuts[1][i] = cut;
342
      cuts[2][i] = cut;
343
      }
344

    
345
    return cuts;
346
    }
347

    
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

    
350
  int getNumStickerTypes(int numLayers)
351
    {
352
    return NUM_STICKERS;
353
    }
354

    
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

    
357
  int getNumCubitFaces()
358
    {
359
    return FACE_COLORS.length;
360
    }
361

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

    
364
  float getScreenRatio()
365
    {
366
    return 0.5f;
367
    }
368

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

    
371
  private int retStickerIndex(int horzSize, int vertSize)
372
    {
373
    switch(horzSize)
374
      {
375
      case 1: return 0;
376
      case 2: return vertSize==1 ? 1:3;
377
      case 3: return 2;
378
      }
379

    
380
    return 0;
381
    }
382

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

    
385
  private int getStickerIndex(int cubitface, int[] dim)
386
    {
387
    switch(cubitface)
388
      {
389
      case 0: case 1: return retStickerIndex(dim[2],dim[1]);
390
      case 2: case 3: return retStickerIndex(dim[0],dim[2]);
391
      case 4: case 5: return retStickerIndex(dim[0],dim[1]);
392
      }
393

    
394
    return 0;
395
    }
396

    
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398

    
399
  int getFaceColor(int cubit, int cubitface, int numLayers)
400
    {
401
    int variant      = getCubitVariant(cubit,numLayers);
402
    int[] dim        = mDimensions[variant];
403
    float[] pos      = getCubitPosition(cubit);
404
    int stickerIndex = getStickerIndex(cubitface,dim);
405
    int quatIndex    = getQuatIndex(cubit);
406
    int face         = mFaceMap[cubitface][quatIndex];
407
    int multiplier   = (face%2)==0 ? 1:-1;
408
    int posIndex     = face/2;
409
    int dimIndex     = mAxisMap[posIndex][quatIndex];
410

    
411
    float position = 0.0f;
412
    int len = pos.length/3;
413
    for(int i=0; i<len; i++) position += pos[3*i+posIndex];
414
    position /= len;
415

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

    
418
    return reaches ? stickerIndex*NUM_FACES + face : NUM_STICKERS*NUM_FACES;
419
    }
420

    
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422
// this implements the fact that certain cubits have multiple 'centers' and this means the cubit
423
// might span more than one layer along a given axis - i.e. that this is a bandaged puzzle.
424

    
425
  int computeBitmapFromRow(int rowBitmap, int axis)
426
    {
427
    int bitmap, initBitmap=0;
428

    
429
    while( initBitmap!=rowBitmap )
430
      {
431
      initBitmap = rowBitmap;
432

    
433
      for(int cubit=0; cubit<NUM_CUBITS; cubit++)
434
        {
435
        bitmap = CUBITS[cubit].mRotationRow[axis];
436
        if( (rowBitmap & bitmap) != 0 ) rowBitmap |= bitmap;
437
        }
438
      }
439

    
440
    return rowBitmap;
441
    }
442

    
443
///////////////////////////////////////////////////////////////////////////////////////////////////
444

    
445
  float returnMultiplier()
446
    {
447
    return getNumLayers();
448
    }
449

    
450
///////////////////////////////////////////////////////////////////////////////////////////////////
451
// PUBLIC API
452

    
453
  public Static3D[] getRotationAxis()
454
    {
455
    return ROT_AXIS;
456
    }
457

    
458
///////////////////////////////////////////////////////////////////////////////////////////////////
459

    
460
  public int[] getBasicAngle()
461
    {
462
    return BASIC_ANGLE;
463
    }
464

    
465
///////////////////////////////////////////////////////////////////////////////////////////////////
466

    
467
  public boolean isSolved()
468
    {
469
    int index = CUBITS[0].mQuatIndex;
470

    
471
    for(int i=1; i<NUM_CUBITS; i++)
472
      {
473
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
474
      }
475

    
476
    return true;
477
    }
478
}
(19-19/41)