Project

General

Profile

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

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

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.ObjectShape;
26
import org.distorted.helpers.ObjectSticker;
27
import org.distorted.library.effect.MatrixEffectQuaternion;
28
import org.distorted.library.main.DistortedEffects;
29
import org.distorted.library.main.DistortedTexture;
30
import org.distorted.library.mesh.MeshBase;
31
import org.distorted.library.mesh.MeshSquare;
32
import org.distorted.library.type.Static3D;
33
import org.distorted.library.type.Static4D;
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[] BASIC_ANGLE = new int[] { 4,4,4 };
48

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

    
56
  private static final Static4D[] QUATS = new Static4D[]
57
         {
58
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
59
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
60
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
61
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
62

    
63
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
64
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
65
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
66
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
67
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
68
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
69
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
70
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
71
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
72
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
73
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
74
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
75

    
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
         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
82
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
83
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
84
         };
85

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

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

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

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

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

    
130
  private static final int NUM_STICKERS = mStickerDimensions.length;
131

    
132
  private static final ObjectSticker[] mStickers;
133

    
134
  static
135
    {
136
    mStickers = new ObjectSticker[NUM_STICKERS];
137

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

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

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

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

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163

    
164
  abstract float[][] getPositions();
165
  abstract int[] getQuatIndices();
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  int getNumCubits()
170
    {
171
    return getPositions().length;
172
    }
173

    
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175

    
176
  private float[] getCubitPosition(int cubit)
177
    {
178
    float[][] pos = getPositions();
179

    
180
    return ( cubit>=0 && cubit< pos.length ) ? pos[cubit] : null;
181
    }
182

    
183
///////////////////////////////////////////////////////////////////////////////////////////////////
184

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

    
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

    
193
  private Static4D getQuat(int cubit, int numLayers)
194
    {
195
    return INIT_QUATS[getQuatIndex(cubit)];
196
    }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199

    
200
  private int getNumCubitVariants(int numLayers)
201
    {
202
    return mDimensions.length;
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
  int getCubitVariant(int cubit, int numLayers)
208
    {
209
    float[][] pos = getPositions();
210

    
211
    if( cubit>=0 && cubit<pos.length )
212
      {
213
      int numPoints = pos[cubit].length/3;
214
      return numPoints==8 ? 4 : numPoints-1;
215
      }
216

    
217
    return 1;
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
  ObjectShape getObjectShape(int cubit, int numLayers)
223
    {
224
    int variant = getCubitVariant(cubit,numLayers);
225

    
226
    final int[][] vert_indices =
227
      {
228
        {2,3,1,0},
229
        {7,6,4,5},
230
        {4,0,1,5},
231
        {7,3,2,6},
232
        {6,2,0,4},
233
        {3,7,5,1},
234
      };
235

    
236
    float defHeight = 0.048f;
237
    int[] bandIndices = new int[] { 0,0,1,1,2,2 };
238
    float[][] corners = new float[][] { {0.04f,0.15f} };
239
    int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
240
    int[] centerIndices = new int[] { 0,1,2,3,4,5,6,7 };
241

    
242
    int X = mDimensions[variant][0];
243
    int Y = mDimensions[variant][1];
244
    int Z = mDimensions[variant][2];
245

    
246
    int maxXY = Math.max(X,Y);
247
    int maxXZ = Math.max(X,Z);
248
    int maxYZ = Math.max(Y,Z);
249

    
250
    double[][] vertices =
251
      {
252
        {+0.5f*X,+0.5f*Y,+0.5f*Z},
253
        {+0.5f*X,+0.5f*Y,-0.5f*Z},
254
        {+0.5f*X,-0.5f*Y,+0.5f*Z},
255
        {+0.5f*X,-0.5f*Y,-0.5f*Z},
256
        {-0.5f*X,+0.5f*Y,+0.5f*Z},
257
        {-0.5f*X,+0.5f*Y,-0.5f*Z},
258
        {-0.5f*X,-0.5f*Y,+0.5f*Z},
259
        {-0.5f*X,-0.5f*Y,-0.5f*Z}
260
      };
261

    
262
    float[][] bands= new float[][]
263
      {
264
        {defHeight/maxYZ,65,0.25f,0.5f,5,1,2},
265
        {defHeight/maxXZ,65,0.25f,0.5f,5,1,2},
266
        {defHeight/maxXY,65,0.25f,0.5f,5,1,2}
267
      };
268

    
269
    float[][] centers = new float[][]
270
      {
271
        {+0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
272
        {+0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
273
        {+0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
274
        {+0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)},
275
        {-0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
276
        {-0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
277
        {-0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
278
        {-0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)}
279
      };
280

    
281
    return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
282
    }
283

    
284
///////////////////////////////////////////////////////////////////////////////////////////////////
285

    
286
  MeshBase createCubitMesh(int cubit, int numLayers)
287
    {
288
    int variant = getCubitVariant(cubit,numLayers);
289

    
290
    if( mMeshes==null )
291
      {
292
      FactoryCubit factory = FactoryCubit.getInstance();
293
      factory.clear();
294
      mMeshes = new MeshBase[getNumCubitVariants(numLayers)];
295
      }
296

    
297
    if( mMeshes[variant]==null )
298
      {
299
      ObjectShape shape = getObjectShape(cubit,numLayers);
300
      FactoryCubit factory = FactoryCubit.getInstance();
301
      factory.createNewFaceTransform(shape);
302
      mMeshes[variant] = factory.createRoundedSolid(shape);
303
      }
304

    
305
    MeshBase mesh = mMeshes[variant].copy(true);
306
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit,numLayers), new Static3D(0,0,0) );
307
    mesh.apply(quat,0xffffffff,0);
308

    
309
    return mesh;
310
    }
311

    
312
///////////////////////////////////////////////////////////////////////////////////////////////////
313

    
314
  int getColor(int face)
315
    {
316
    return FACE_COLORS[face];
317
    }
318

    
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320

    
321
  ObjectSticker retSticker(int face)
322
    {
323
    return mStickers[face/NUM_FACES];
324
    }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
  float[][] getCubitPositions(int size)
329
    {
330
    int numCubits = getNumCubits();
331
    float[][] tmp = new float[numCubits][];
332

    
333
    for(int cubit=0; cubit<numCubits; cubit++)
334
      {
335
      tmp[cubit] = getCubitPosition(cubit);
336
      }
337

    
338
    return tmp;
339
    }
340

    
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342

    
343
  Static4D[] getQuats()
344
    {
345
    return QUATS;
346
    }
347

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

    
350
  boolean shouldResetTextureMaps()
351
    {
352
    return false;
353
    }
354

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

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

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

    
364
  float[][] getCuts(int numLayers)
365
    {
366
    float[][] cuts = new float[3][numLayers-1];
367

    
368
    for(int i=0; i<numLayers-1; i++)
369
      {
370
      float cut = (2-numLayers)*0.5f + i;
371
      cuts[0][i] = cut;
372
      cuts[1][i] = cut;
373
      cuts[2][i] = cut;
374
      }
375

    
376
    return cuts;
377
    }
378

    
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380

    
381
  int getNumStickerTypes(int numLayers)
382
    {
383
    return NUM_STICKERS;
384
    }
385

    
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387

    
388
  int getNumCubitFaces()
389
    {
390
    return FACE_COLORS.length;
391
    }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

    
395
  float getScreenRatio()
396
    {
397
    return 0.5f;
398
    }
399

    
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401

    
402
  private int retStickerIndex(int horzSize, int vertSize)
403
    {
404
    switch(horzSize)
405
      {
406
      case 1: return 0;
407
      case 2: return vertSize==1 ? 1:3;
408
      case 3: return 2;
409
      }
410

    
411
    return 0;
412
    }
413

    
414
///////////////////////////////////////////////////////////////////////////////////////////////////
415

    
416
  private int getStickerIndex(int cubitface, int[] dim)
417
    {
418
    switch(cubitface)
419
      {
420
      case 0: case 1: return retStickerIndex(dim[2],dim[1]);
421
      case 2: case 3: return retStickerIndex(dim[0],dim[2]);
422
      case 4: case 5: return retStickerIndex(dim[0],dim[1]);
423
      }
424

    
425
    return 0;
426
    }
427

    
428
///////////////////////////////////////////////////////////////////////////////////////////////////
429

    
430
  int getFaceColor(int cubit, int cubitface, int numLayers)
431
    {
432
    int variant      = getCubitVariant(cubit,numLayers);
433
    int[] dim        = mDimensions[variant];
434
    float[] pos      = getCubitPosition(cubit);
435
    int stickerIndex = getStickerIndex(cubitface,dim);
436
    int quatIndex    = getQuatIndex(cubit);
437
    int face         = mFaceMap[cubitface][quatIndex];
438
    int multiplier   = (face%2)==0 ? 1:-1;
439
    int posIndex     = face/2;
440
    int dimIndex     = mAxisMap[posIndex][quatIndex];
441

    
442
    float position = 0.0f;
443
    int len = pos.length/3;
444
    for(int i=0; i<len; i++) position += pos[3*i+posIndex];
445
    position /= len;
446

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

    
449
    return reaches ? stickerIndex*NUM_FACES + face : NUM_STICKERS*NUM_FACES;
450
    }
451

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

    
456
  int computeBitmapFromRow(int rowBitmap, int axis)
457
    {
458
    int bitmap, initBitmap=0;
459

    
460
    while( initBitmap!=rowBitmap )
461
      {
462
      initBitmap = rowBitmap;
463

    
464
      for(int cubit=0; cubit<NUM_CUBITS; cubit++)
465
        {
466
        bitmap = CUBITS[cubit].mRotationRow[axis];
467
        if( (rowBitmap & bitmap) != 0 ) rowBitmap |= bitmap;
468
        }
469
      }
470

    
471
    return rowBitmap;
472
    }
473

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475

    
476
  float returnMultiplier()
477
    {
478
    return getNumLayers();
479
    }
480

    
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482
// PUBLIC API
483

    
484
  public Static3D[] getRotationAxis()
485
    {
486
    return ROT_AXIS;
487
    }
488

    
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490

    
491
  public int[] getBasicAngle()
492
    {
493
    return BASIC_ANGLE;
494
    }
495

    
496
///////////////////////////////////////////////////////////////////////////////////////////////////
497

    
498
  public boolean isSolved()
499
    {
500
    int index = CUBITS[0].mQuatIndex;
501

    
502
    for(int i=1; i<NUM_CUBITS; i++)
503
      {
504
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
505
      }
506

    
507
    return true;
508
    }
509
}
(19-19/41)