Project

General

Profile

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

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

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
import android.graphics.Canvas;
24
import android.graphics.Paint;
25

    
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[] 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 MeshBase[] mMeshes;
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
  TwistyBandagedAbstract(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
134
                         DistortedEffects effects, int[][] moves, ObjectList list, Resources res, int scrWidth)
135
    {
136
    super(size, size, quat, texture, mesh, effects, moves, list, res, scrWidth);
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140

    
141
  abstract float[][] getPositions();
142
  abstract int[] getQuatIndices();
143

    
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

    
146
  int getCubitVariant(int cubit)
147
    {
148
    float[][] pos = getPositions();
149

    
150
    if( cubit>=0 && cubit< pos.length )
151
      {
152
      int numPoints = pos[cubit].length/3;
153
      return numPoints==8 ? 4 : numPoints-1;
154
      }
155

    
156
    return 1;
157
    }
158

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

    
161
  int getNumCubits()
162
    {
163
    return getPositions().length;
164
    }
165

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

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

    
172
    return ( cubit>=0 && cubit< pos.length ) ? pos[cubit] : null;
173
    }
174

    
175
///////////////////////////////////////////////////////////////////////////////////////////////////
176

    
177
  private int getQuatIndex(int cubit)
178
    {
179
    int[] indices = getQuatIndices();
180

    
181
    return ( cubit>=0 && cubit< indices.length ) ? indices[cubit] : 0;
182
    }
183

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

    
186
  MeshBase createCubitMesh(int cubit, int numLayers)
187
    {
188
    if( mMeshes==null )
189
      {
190
      int LEN = mDimensions.length;
191
      mMeshes = new MeshBase[LEN];
192

    
193
      for(int i=0; i<LEN; i++)
194
        {
195
        mMeshes[i] = FactoryCubit.getInstance().createCuboidMesh(mDimensions[i]);
196
        }
197
      }
198

    
199
    int variant = getCubitVariant(cubit);
200
    MeshBase mesh = mMeshes[variant].copy(true);
201
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( INIT_QUATS[getQuatIndex(cubit)], new Static3D(0,0,0) );
202
    mesh.apply(quat,0xffffffff,0);
203

    
204
    return mesh;
205
    }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
210
    {
211
    int numFaces = FACE_COLORS.length;
212
    int stickerType = face/numFaces;
213
    int color = face%numFaces;
214
    float X = mStickerDimensions[stickerType][0];
215
    float Y = mStickerDimensions[stickerType][1];
216
    float MAX = Math.max(X,Y);
217
    float R = 0.10f / MAX;
218
    float S = 0.08f / MAX;
219
    X /= (2*MAX);
220
    Y /= (2*MAX);
221

    
222
    float[] vertices = { -X,-Y, +X,-Y, +X,+Y, -X,+Y};
223

    
224
    FactorySticker factory = FactorySticker.getInstance();
225
    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[color], R);
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  float[][] getCubitPositions(int size)
231
    {
232
    int numCubits = getNumCubits();
233
    float[][] tmp = new float[numCubits][];
234

    
235
    for(int cubit=0; cubit<numCubits; cubit++)
236
      {
237
      tmp[cubit] = getCubitPosition(cubit);
238
      }
239

    
240
    return tmp;
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

    
245
  Static4D[] getQuats()
246
    {
247
    return QUATS;
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  boolean shouldResetTextureMaps()
253
    {
254
    return false;
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  int getNumFaces()
260
    {
261
    return FACE_COLORS.length;
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

    
266
  float[] getCuts(int numLayers)
267
    {
268
    float[] cuts = new float[numLayers-1];
269

    
270
    for(int i=0; i<numLayers-1; i++)
271
      {
272
      cuts[i] = (2-numLayers)*0.5f + i;
273
      }
274

    
275
    return cuts;
276
    }
277

    
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279

    
280
  int getNumStickerTypes(int numLayers)
281
    {
282
    return NUM_STICKERS;
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

    
287
  int getNumCubitFaces()
288
    {
289
    return FACE_COLORS.length;
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  float getScreenRatio()
295
    {
296
    return 0.5f;
297
    }
298

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
  private int retStickerIndex(int horzSize, int vertSize)
302
    {
303
    switch(horzSize)
304
      {
305
      case 1: return 0;
306
      case 2: return vertSize==1 ? 1:3;
307
      case 3: return 2;
308
      }
309

    
310
    return 0;
311
    }
312

    
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314

    
315
  private int getStickerIndex(int cubitface, int[] dim)
316
    {
317
    switch(cubitface)
318
      {
319
      case 0: case 1: return retStickerIndex(dim[2],dim[1]);
320
      case 2: case 3: return retStickerIndex(dim[0],dim[2]);
321
      case 4: case 5: return retStickerIndex(dim[0],dim[1]);
322
      }
323

    
324
    return 0;
325
    }
326

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

    
329
  int getFaceColor(int cubit, int cubitface, int numLayers)
330
    {
331
    int variant      = getCubitVariant(cubit);
332
    int[] dim        = mDimensions[variant];
333
    float[] pos      = getCubitPosition(cubit);
334
    int stickerIndex = getStickerIndex(cubitface,dim);
335
    int quatIndex    = getQuatIndex(cubit);
336
    int face         = mFaceMap[cubitface][quatIndex];
337
    int multiplier   = (face%2)==0 ? 1:-1;
338
    int posIndex     = face/2;
339
    int dimIndex     = mAxisMap[posIndex][quatIndex];
340

    
341
    float position = 0.0f;
342
    int len = pos.length/3;
343
    for(int i=0; i<len; i++) position += pos[3*i+posIndex];
344
    position /= len;
345

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

    
348
    return reaches ? stickerIndex*NUM_FACES + face : NUM_STICKERS*NUM_FACES;
349
    }
350

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

    
353
  int computeBitmapFromRow(int rowBitmap, int axis)
354
    {
355
    int bitmap, initBitmap=0;
356

    
357
    while( initBitmap!=rowBitmap )
358
      {
359
      initBitmap = rowBitmap;
360

    
361
      for(int cubit=0; cubit<NUM_CUBITS; cubit++)
362
        {
363
        bitmap = CUBITS[cubit].mRotationRow[axis];
364
        if( (rowBitmap & bitmap) != 0 ) rowBitmap |= bitmap;
365
        }
366
      }
367

    
368
    return rowBitmap;
369
    }
370

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
  float returnMultiplier()
374
    {
375
    return getNumLayers();
376
    }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
  float[] getRowChances(int numLayers)
381
    {
382
    float[] chances = new float[numLayers];
383

    
384
    for(int i=0; i<numLayers; i++)
385
      {
386
      chances[i] = (i+1.0f) / numLayers;
387
      }
388

    
389
    return chances;
390
    }
391

    
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393
// PUBLIC API
394

    
395
  public Static3D[] getRotationAxis()
396
    {
397
    return ROT_AXIS;
398
    }
399

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

    
402
  public int getBasicAngle()
403
    {
404
    return 4;
405
    }
406

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

    
409
  public boolean isSolved()
410
    {
411
    int index = CUBITS[0].mQuatIndex;
412

    
413
    for(int i=1; i<NUM_CUBITS; i++)
414
      {
415
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
416
      }
417

    
418
    return true;
419
    }
420

    
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422
// only needed for solvers - there are no Bandaged solvers ATM)
423

    
424
  public String retObjectString()
425
    {
426
    return "";
427
    }
428
}
(18-18/35)