Project

General

Profile

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

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

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.ObjectSticker;
26
import org.distorted.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.main.DistortedEffects;
28
import org.distorted.library.main.DistortedTexture;
29
import org.distorted.library.mesh.MeshBase;
30
import org.distorted.library.mesh.MeshSquare;
31
import org.distorted.library.type.Static3D;
32
import org.distorted.library.type.Static4D;
33

    
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35

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

    
46
  private static final int[] BASIC_ANGLE = new int[] { 4,4,4 };
47

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

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

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

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

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

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

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

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

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

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

    
131
  private static final ObjectSticker[] mStickers;
132

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

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

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

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

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

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

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

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
  int getCubitVariant(int cubit)
169
    {
170
    float[][] pos = getPositions();
171

    
172
    if( cubit>=0 && cubit<pos.length )
173
      {
174
      int numPoints = pos[cubit].length/3;
175
      return numPoints==8 ? 4 : numPoints-1;
176
      }
177

    
178
    return 1;
179
    }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

    
183
  int getNumCubits()
184
    {
185
    return getPositions().length;
186
    }
187

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

    
190
  private float[] getCubitPosition(int cubit)
191
    {
192
    float[][] pos = getPositions();
193

    
194
    return ( cubit>=0 && cubit< pos.length ) ? pos[cubit] : null;
195
    }
196

    
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

    
199
  private int getQuatIndex(int cubit)
200
    {
201
    int[] indices = getQuatIndices();
202

    
203
    return ( cubit>=0 && cubit< indices.length ) ? indices[cubit] : 0;
204
    }
205

    
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

    
208
  MeshBase createCubitMesh(int cubit, int numLayers)
209
    {
210
    if( mMeshes==null )
211
      {
212
      FactoryCubit factory = FactoryCubit.getInstance();
213
      factory.clear();
214
      int LEN = mDimensions.length;
215
      mMeshes = new MeshBase[LEN];
216

    
217
      final int[][] vert_indices =
218
          {
219
              {2,3,1,0},
220
              {7,6,4,5},
221
              {4,0,1,5},
222
              {7,3,2,6},
223
              {6,2,0,4},
224
              {3,7,5,1},
225
          };
226

    
227
      float defHeight = 0.048f;
228
      int[] bandIndexes = new int[] { 0,0,1,1,2,2 };
229
      float[][] corners = new float[][] { {0.04f,0.15f} };
230
      int[] cornerIndexes = new int[] { 0,0,0,0,0,0,0,0 };
231
      int[] centerIndexes = new int[] { 0,1,2,3,4,5,6,7 };
232

    
233
      for(int i=0; i<LEN; i++)
234
        {
235
        int X = mDimensions[i][0];
236
        int Y = mDimensions[i][1];
237
        int Z = mDimensions[i][2];
238

    
239
        int maxXY = Math.max(X,Y);
240
        int maxXZ = Math.max(X,Z);
241
        int maxYZ = Math.max(Y,Z);
242

    
243
        double[][] vertices =
244
            {
245
                {+0.5f*X,+0.5f*Y,+0.5f*Z},
246
                {+0.5f*X,+0.5f*Y,-0.5f*Z},
247
                {+0.5f*X,-0.5f*Y,+0.5f*Z},
248
                {+0.5f*X,-0.5f*Y,-0.5f*Z},
249
                {-0.5f*X,+0.5f*Y,+0.5f*Z},
250
                {-0.5f*X,+0.5f*Y,-0.5f*Z},
251
                {-0.5f*X,-0.5f*Y,+0.5f*Z},
252
                {-0.5f*X,-0.5f*Y,-0.5f*Z}
253
            };
254

    
255
        float[][] bands= new float[][]
256
            {
257
                {defHeight/maxYZ,65,0.25f,0.5f,5,1,2},
258
                {defHeight/maxXZ,65,0.25f,0.5f,5,1,2},
259
                {defHeight/maxXY,65,0.25f,0.5f,5,1,2}
260
            };
261

    
262
        float[][] centers = new float[][]
263
            {
264
                {+0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
265
                {+0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
266
                {+0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
267
                {+0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)},
268
                {-0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
269
                {-0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
270
                {-0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
271
                {-0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)}
272
            };
273

    
274
        factory.createNewFaceTransform(vertices,vert_indices);
275
        mMeshes[i] = factory.createRoundedSolid(vertices,vert_indices,
276
                                                bands, bandIndexes,
277
                                                corners, cornerIndexes,
278
                                                centers, centerIndexes,
279
                                                getNumCubitFaces(), null );
280
        }
281
      }
282

    
283
    int variant = getCubitVariant(cubit);
284
    MeshBase mesh = mMeshes[variant].copy(true);
285
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( INIT_QUATS[getQuatIndex(cubit)], new Static3D(0,0,0) );
286
    mesh.apply(quat,0xffffffff,0);
287

    
288
    return mesh;
289
    }
290

    
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292

    
293
  int getColor(int face)
294
    {
295
    return FACE_COLORS[face];
296
    }
297

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

    
300
  ObjectSticker retSticker(int face)
301
    {
302
    return mStickers[face/NUM_FACES];
303
    }
304

    
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306

    
307
  float[][] getCubitPositions(int size)
308
    {
309
    int numCubits = getNumCubits();
310
    float[][] tmp = new float[numCubits][];
311

    
312
    for(int cubit=0; cubit<numCubits; cubit++)
313
      {
314
      tmp[cubit] = getCubitPosition(cubit);
315
      }
316

    
317
    return tmp;
318
    }
319

    
320
///////////////////////////////////////////////////////////////////////////////////////////////////
321

    
322
  Static4D[] getQuats()
323
    {
324
    return QUATS;
325
    }
326

    
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328

    
329
  boolean shouldResetTextureMaps()
330
    {
331
    return false;
332
    }
333

    
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335

    
336
  int getNumFaces()
337
    {
338
    return FACE_COLORS.length;
339
    }
340

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

    
343
  float[][] getCuts(int numLayers)
344
    {
345
    float[][] cuts = new float[3][numLayers-1];
346

    
347
    for(int i=0; i<numLayers-1; i++)
348
      {
349
      float cut = (2-numLayers)*0.5f + i;
350
      cuts[0][i] = cut;
351
      cuts[1][i] = cut;
352
      cuts[2][i] = cut;
353
      }
354

    
355
    return cuts;
356
    }
357

    
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359

    
360
  int getNumStickerTypes(int numLayers)
361
    {
362
    return NUM_STICKERS;
363
    }
364

    
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366

    
367
  int getNumCubitFaces()
368
    {
369
    return FACE_COLORS.length;
370
    }
371

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
  float getScreenRatio()
375
    {
376
    return 0.5f;
377
    }
378

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

    
381
  private int retStickerIndex(int horzSize, int vertSize)
382
    {
383
    switch(horzSize)
384
      {
385
      case 1: return 0;
386
      case 2: return vertSize==1 ? 1:3;
387
      case 3: return 2;
388
      }
389

    
390
    return 0;
391
    }
392

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

    
395
  private int getStickerIndex(int cubitface, int[] dim)
396
    {
397
    switch(cubitface)
398
      {
399
      case 0: case 1: return retStickerIndex(dim[2],dim[1]);
400
      case 2: case 3: return retStickerIndex(dim[0],dim[2]);
401
      case 4: case 5: return retStickerIndex(dim[0],dim[1]);
402
      }
403

    
404
    return 0;
405
    }
406

    
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408

    
409
  int getFaceColor(int cubit, int cubitface, int numLayers)
410
    {
411
    int variant      = getCubitVariant(cubit);
412
    int[] dim        = mDimensions[variant];
413
    float[] pos      = getCubitPosition(cubit);
414
    int stickerIndex = getStickerIndex(cubitface,dim);
415
    int quatIndex    = getQuatIndex(cubit);
416
    int face         = mFaceMap[cubitface][quatIndex];
417
    int multiplier   = (face%2)==0 ? 1:-1;
418
    int posIndex     = face/2;
419
    int dimIndex     = mAxisMap[posIndex][quatIndex];
420

    
421
    float position = 0.0f;
422
    int len = pos.length/3;
423
    for(int i=0; i<len; i++) position += pos[3*i+posIndex];
424
    position /= len;
425

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

    
428
    return reaches ? stickerIndex*NUM_FACES + face : NUM_STICKERS*NUM_FACES;
429
    }
430

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

    
435
  int computeBitmapFromRow(int rowBitmap, int axis)
436
    {
437
    int bitmap, initBitmap=0;
438

    
439
    while( initBitmap!=rowBitmap )
440
      {
441
      initBitmap = rowBitmap;
442

    
443
      for(int cubit=0; cubit<NUM_CUBITS; cubit++)
444
        {
445
        bitmap = CUBITS[cubit].mRotationRow[axis];
446
        if( (rowBitmap & bitmap) != 0 ) rowBitmap |= bitmap;
447
        }
448
      }
449

    
450
    return rowBitmap;
451
    }
452

    
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454

    
455
  float returnMultiplier()
456
    {
457
    return getNumLayers();
458
    }
459

    
460
///////////////////////////////////////////////////////////////////////////////////////////////////
461
// PUBLIC API
462

    
463
  public Static3D[] getRotationAxis()
464
    {
465
    return ROT_AXIS;
466
    }
467

    
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469

    
470
  public int[] getBasicAngle()
471
    {
472
    return BASIC_ANGLE;
473
    }
474

    
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476

    
477
  public boolean isSolved()
478
    {
479
    int index = CUBITS[0].mQuatIndex;
480

    
481
    for(int i=1; i<NUM_CUBITS; i++)
482
      {
483
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
484
      }
485

    
486
    return true;
487
    }
488
}
(19-19/41)