Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyPyraminx.java @ cce59cd4

1 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 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 1f9772f3 Leszek Koltunski
package org.distorted.objects;
21 e844c116 Leszek Koltunski
22 ccf9fec5 Leszek Koltunski
import android.content.res.Resources;
23 e844c116 Leszek Koltunski
import android.graphics.Canvas;
24
import android.graphics.Paint;
25
26
import org.distorted.library.main.DistortedEffects;
27
import org.distorted.library.main.DistortedTexture;
28
import org.distorted.library.mesh.MeshBase;
29 efa8aa48 Leszek Koltunski
import org.distorted.library.mesh.MeshSquare;
30 e844c116 Leszek Koltunski
import org.distorted.library.type.Static3D;
31
import org.distorted.library.type.Static4D;
32 6fd4a72c Leszek Koltunski
import org.distorted.main.R;
33 1ebc4767 Leszek Koltunski
import org.distorted.main.RubikSurfaceView;
34 e844c116 Leszek Koltunski
35 7c969a6d Leszek Koltunski
import java.util.Random;
36
37
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
38
39 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
40
41 9c2f0c91 Leszek Koltunski
public class TwistyPyraminx extends TwistyObject
42 e844c116 Leszek Koltunski
{
43 ad38d800 Leszek Koltunski
  static final Static3D[] ROT_AXIS = new Static3D[]
44 e844c116 Leszek Koltunski
         {
45 ac940e24 Leszek Koltunski
           new Static3D(     0,-SQ3/3,-SQ6/3),
46
           new Static3D(     0,-SQ3/3,+SQ6/3),
47
           new Static3D(+SQ6/3,+SQ3/3,     0),
48
           new Static3D(-SQ6/3,+SQ3/3,     0),
49 ad38d800 Leszek Koltunski
         };
50
51 e844c116 Leszek Koltunski
  private static final int[] FACE_COLORS = new int[]
52
         {
53 ece1b58d Leszek Koltunski
           COLOR_GREEN , COLOR_YELLOW,
54
           COLOR_BLUE  , COLOR_RED
55 e844c116 Leszek Koltunski
         };
56
57 9f4c44fe Leszek Koltunski
  // computed with res/raw/compute_quats.c
58 10585385 Leszek Koltunski
  private static final Static4D[] QUATS = new Static4D[]
59 e844c116 Leszek Koltunski
         {
60 10585385 Leszek Koltunski
           new Static4D(  0.0f,   0.0f,   0.0f,  1.0f),
61 ac940e24 Leszek Koltunski
           new Static4D(  0.0f,   1.0f,   0.0f,  0.0f),
62
           new Static4D( SQ2/2,   0.5f,   0.0f,  0.5f),
63
           new Static4D(-SQ2/2,   0.5f,   0.0f,  0.5f),
64
           new Static4D(  0.0f,  -0.5f, -SQ2/2,  0.5f),
65
           new Static4D(  0.0f,  -0.5f,  SQ2/2,  0.5f),
66
           new Static4D( SQ2/2,   0.5f,   0.0f, -0.5f),
67
           new Static4D(-SQ2/2,   0.5f,   0.0f, -0.5f),
68
           new Static4D(  0.0f,  -0.5f, -SQ2/2, -0.5f),
69
           new Static4D(  0.0f,  -0.5f,  SQ2/2, -0.5f),
70
           new Static4D( SQ2/2,   0.0f,  SQ2/2,  0.0f),
71
           new Static4D(-SQ2/2,   0.0f,  SQ2/2,  0.0f)
72 e844c116 Leszek Koltunski
         };
73
74 ac940e24 Leszek Koltunski
  private static MeshBase mOctaMesh, mTetraMesh;
75 49f67f9b Leszek Koltunski
76 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
77
78 ac940e24 Leszek Koltunski
  TwistyPyraminx(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
79
                 DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
80 e844c116 Leszek Koltunski
    {
81 d99f3a48 Leszek Koltunski
    super(size, size, 30, quat, texture, mesh, effects, moves, ObjectList.PYRA, res, scrWidth);
82 e844c116 Leszek Koltunski
    }
83
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85
86 ac940e24 Leszek Koltunski
  private void addTetrahedralLattice(int size, int index, Static3D[] pos)
87 49f67f9b Leszek Koltunski
    {
88 ac940e24 Leszek Koltunski
    final float DX = 1.0f;
89
    final float DY = SQ2/2;
90
    final float DZ = 1.0f;
91 49f67f9b Leszek Koltunski
92 ac940e24 Leszek Koltunski
    float startX = 0.0f;
93
    float startY =-DY*(size-1)/2;
94
    float startZ = DZ*(size-1)/2;
95 769409d2 Leszek Koltunski
96 ac940e24 Leszek Koltunski
    for(int layer=0; layer<size; layer++)
97 49f67f9b Leszek Koltunski
      {
98 ac940e24 Leszek Koltunski
      float currX = startX;
99
      float currY = startY;
100
101
      for(int x=0; x<layer+1; x++)
102
        {
103
        float currZ = startZ;
104
105
        for(int z=0; z<size-layer; z++)
106
          {
107
          pos[index] = new Static3D(currX,currY,currZ);
108
          index++;
109
          currZ -= DZ;
110
          }
111
112
        currX += DX;
113
        }
114
115
      startX-=DX/2;
116
      startY+=DY;
117
      startZ-=DZ/2;
118 49f67f9b Leszek Koltunski
      }
119
    }
120
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122 ac940e24 Leszek Koltunski
// there are (n^3-n)/6 octahedrons and ((n+1)^3 - (n+1))/6 tetrahedrons
123 49f67f9b Leszek Koltunski
124 e844c116 Leszek Koltunski
  Static3D[] getCubitPositions(int size)
125
    {
126 ac940e24 Leszek Koltunski
    int numOcta = (size-1)*size*(size+1)/6;
127
    int numTetra= size*(size+1)*(size+2)/6;
128
    Static3D[] ret = new Static3D[numOcta+numTetra];
129 49f67f9b Leszek Koltunski
130 ac940e24 Leszek Koltunski
    addTetrahedralLattice(size-1,      0,ret);
131
    addTetrahedralLattice(size  ,numOcta,ret);
132 49f67f9b Leszek Koltunski
133 ac940e24 Leszek Koltunski
    return ret;
134 e844c116 Leszek Koltunski
    }
135
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137
138 10585385 Leszek Koltunski
  Static4D[] getQuats()
139 e844c116 Leszek Koltunski
    {
140 10585385 Leszek Koltunski
    return QUATS;
141 e844c116 Leszek Koltunski
    }
142
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144
145
  int getNumFaces()
146
    {
147
    return FACE_COLORS.length;
148
    }
149
150 eab9d8f8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
151
152
  int getNumStickerTypes()
153
    {
154
    return 1;
155
    }
156
157 7403cdfa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
158
159 a97e02b7 Leszek Koltunski
  float[] getCuts(int size)
160 7403cdfa Leszek Koltunski
    {
161 a97e02b7 Leszek Koltunski
    float[] cuts = new float[size-1];
162
163
    for(int i=0; i<size-1; i++)
164
      {
165
      cuts[i] = (1.0f-0.25f*size+i)*(SQ6/3);
166
      }
167
168
    return cuts;
169 7403cdfa Leszek Koltunski
    }
170
171 8f53e513 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
172
173
  int getNumCubitFaces()
174
    {
175 ac940e24 Leszek Koltunski
    return 8;
176 8f53e513 Leszek Koltunski
    }
177
178 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
179
180
  float getScreenRatio()
181
    {
182 7381193e Leszek Koltunski
    return 0.82f;
183 f0fa83ae Leszek Koltunski
    }
184
185 eaee1ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
186
187
  boolean shouldResetTextureMaps()
188
    {
189
    return false;
190
    }
191
192 f6d06256 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
193
194 ac940e24 Leszek Koltunski
  private int faceColor(int cubit, int axis)
195 f6d06256 Leszek Koltunski
    {
196 ac940e24 Leszek Koltunski
    float row = CUBITS[cubit].mRotationRow[axis];
197
    return row*row < 0.1f ? axis : NUM_FACES;
198 f6d06256 Leszek Koltunski
    }
199
200 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
201
202 ac940e24 Leszek Koltunski
  int getFaceColor(int cubit, int cubitface, int size)
203 e844c116 Leszek Koltunski
    {
204 ac940e24 Leszek Koltunski
    if( cubit< (size-1)*size*(size+1)/6 )
205 40ab026e Leszek Koltunski
      {
206 ac940e24 Leszek Koltunski
      switch( cubitface )
207
        {
208
        case 0: return faceColor(cubit,0);
209
        case 2: return faceColor(cubit,1);
210
        case 5: return faceColor(cubit,3);
211
        case 7: return faceColor(cubit,2);
212
        default:return NUM_FACES;
213
        }
214 40ab026e Leszek Koltunski
      }
215 ac940e24 Leszek Koltunski
    else
216 89a11f7b Leszek Koltunski
      {
217 ac940e24 Leszek Koltunski
      return cubitface<NUM_FACES ? faceColor(cubit,cubitface) : NUM_FACES;
218 89a11f7b Leszek Koltunski
      }
219 e844c116 Leszek Koltunski
    }
220
221 40ab026e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
222
223 14bd7976 Leszek Koltunski
  MeshBase createCubitMesh(int cubit)
224 40ab026e Leszek Koltunski
    {
225 d99f3a48 Leszek Koltunski
    int numLayers = getNumLayers();
226 40ab026e Leszek Koltunski
227 d99f3a48 Leszek Koltunski
    if( cubit< (numLayers-1)*numLayers*(numLayers+1)/6 )
228 40ab026e Leszek Koltunski
      {
229 b89898c5 Leszek Koltunski
      if( mOctaMesh==null ) mOctaMesh = FactoryCubit.getInstance().createOctaMesh();
230 ac940e24 Leszek Koltunski
      return mOctaMesh.copy(true);
231 40ab026e Leszek Koltunski
      }
232
    else
233
      {
234 b89898c5 Leszek Koltunski
      if( mTetraMesh==null ) mTetraMesh = FactoryCubit.getInstance().createTetraMesh();
235 ac940e24 Leszek Koltunski
      return mTetraMesh.copy(true);
236 40ab026e Leszek Koltunski
      }
237
    }
238
239 7289fd6c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
240
241 ae755eda Leszek Koltunski
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
242 7289fd6c Leszek Koltunski
    {
243 ae755eda Leszek Koltunski
    float E = 0.75f;
244
    float F = 0.50f;
245 76c2bd07 Leszek Koltunski
    float R = 0.06f;
246
    float S = 0.08f;
247
    float[] vertices = { -F,-E/3, +F,-E/3, 0.0f,2*E/3};
248
249 b89898c5 Leszek Koltunski
    FactorySticker factory = FactorySticker.getInstance();
250 ae755eda Leszek Koltunski
    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face], R);
251 7289fd6c Leszek Koltunski
    }
252
253 fb377dae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
254 7403cdfa Leszek Koltunski
// SQ6/3 = height of the tetrahedron
255 fb377dae Leszek Koltunski
256
  float returnMultiplier()
257
    {
258 d99f3a48 Leszek Koltunski
    return getNumLayers()/(SQ6/3);
259 fb377dae Leszek Koltunski
    }
260
261 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
262
263
  float[] getRowChances()
264
    {
265 d99f3a48 Leszek Koltunski
    int numLayers = getNumLayers();
266
    int total = numLayers*(numLayers+1)/2;
267 7c969a6d Leszek Koltunski
    float running=0.0f;
268 d99f3a48 Leszek Koltunski
    float[] chances = new float[numLayers];
269 7c969a6d Leszek Koltunski
270 d99f3a48 Leszek Koltunski
    for(int i=0; i<numLayers; i++)
271 7c969a6d Leszek Koltunski
      {
272 d99f3a48 Leszek Koltunski
      running += (numLayers-i);
273 7c969a6d Leszek Koltunski
      chances[i] = running / total;
274
      }
275
276
    return chances;
277
    }
278
279 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
280
// PUBLIC API
281
282 12ad3fca Leszek Koltunski
  public Static3D[] getRotationAxis()
283
    {
284 ad38d800 Leszek Koltunski
    return ROT_AXIS;
285 12ad3fca Leszek Koltunski
    }
286
287
///////////////////////////////////////////////////////////////////////////////////////////////////
288
289 e844c116 Leszek Koltunski
  public int getBasicAngle()
290
    {
291
    return 3;
292
    }
293 39e74052 Leszek Koltunski
294 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
295
296
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
297
    {
298
    int numAxis = ROTATION_AXIS.length;
299
300
    if( oldRotAxis == START_AXIS )
301 5cf34c5f Leszek Koltunski
      {
302 7c969a6d Leszek Koltunski
      return rnd.nextInt(numAxis);
303
      }
304
    else
305
      {
306
      int newVector = rnd.nextInt(numAxis-1);
307
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
308 5cf34c5f Leszek Koltunski
      }
309
    }
310
311 e46e17fb Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
312
313 7c969a6d Leszek Koltunski
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
314 e46e17fb Leszek Koltunski
    {
315 7c969a6d Leszek Koltunski
    float rowFloat = rnd.nextFloat();
316 e46e17fb Leszek Koltunski
317 7c969a6d Leszek Koltunski
    for(int row=0; row<mRowChances.length; row++)
318
      {
319
      if( rowFloat<=mRowChances[row] ) return row;
320
      }
321
322
    return 0;
323 e46e17fb Leszek Koltunski
    }
324 f0336037 Leszek Koltunski
325 6b6504fe Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
326
327
  public boolean isSolved()
328
    {
329
    int index = CUBITS[0].mQuatIndex;
330
331
    for(int i=1; i<NUM_CUBITS; i++)
332
      {
333
      if( !thereIsNoVisibleDifference(CUBITS[i], index) ) return false;
334
      }
335
336
    return true;
337
    }
338
339 1ebc4767 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
340
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different
341
// then if it were rotated by quaternion 'quat'.
342
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two
343
// middle squares get interchanged. No visible difference!
344
//
345
// So: this is true iff the cubit
346
// a) is a corner or edge and the quaternions are the same
347
// b) is inside one of the faces and after rotations by both quats it ends up on the same face.
348
349 6b6504fe Leszek Koltunski
  private boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex)
350 1ebc4767 Leszek Koltunski
    {
351
    if ( cubit.mQuatIndex == quatIndex ) return true;
352
353
    int belongsToHowManyFaces = 0;
354 d99f3a48 Leszek Koltunski
    int numLayers = getNumLayers()-1;
355 1ebc4767 Leszek Koltunski
    float row;
356
    final float MAX_ERROR = 0.01f;
357
358
    for(int i=0; i<NUM_AXIS; i++)
359
      {
360
      row = cubit.mRotationRow[i];
361 d99f3a48 Leszek Koltunski
      if( (row          <MAX_ERROR && row          >-MAX_ERROR) ||
362
          (row-numLayers<MAX_ERROR && row-numLayers>-MAX_ERROR)  ) belongsToHowManyFaces++;
363 1ebc4767 Leszek Koltunski
      }
364
365
    switch(belongsToHowManyFaces)
366
      {
367
      case 0 : return true ;  // 'inside' cubit that does not lie on any face
368
      case 1 :                // cubit that lies inside one of the faces
369
               Static3D orig = cubit.getOrigPosition();
370
               Static4D quat1 = QUATS[quatIndex];
371
               Static4D quat2 = QUATS[cubit.mQuatIndex];
372
373
               Static4D cubitCenter = new Static4D( orig.get0(), orig.get1(), orig.get2(), 0);
374
               Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 );
375
               Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 );
376
377 eb389a97 Leszek Koltunski
               float row1, row2;
378 1ebc4767 Leszek Koltunski
               float x1 = rotated1.get0();
379
               float y1 = rotated1.get1();
380
               float z1 = rotated1.get2();
381
               float x2 = rotated2.get0();
382
               float y2 = rotated2.get1();
383
               float z2 = rotated2.get2();
384
385
               for(int i=0; i<NUM_AXIS; i++)
386
                 {
387 eb389a97 Leszek Koltunski
                 row1 = computeRow(x1,y1,z1,i);
388
                 row2 = computeRow(x2,y2,z2,i);
389
390 bb490017 Leszek Koltunski
                 if( (row1==0 && row2==0) || (row1==numLayers && row2==numLayers) ) return true;
391 1ebc4767 Leszek Koltunski
                 }
392
               return false;
393
394
      default: return false;  // edge or corner
395
      }
396
    }
397
398 f0336037 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
399 ee35e63c Leszek Koltunski
// only needed for solvers - there are no Pyraminx solvers ATM)
400 f0336037 Leszek Koltunski
401 20931cf6 Leszek Koltunski
  public String retObjectString()
402 f0336037 Leszek Koltunski
    {
403
    return "";
404
    }
405 6fd4a72c Leszek Koltunski
406
///////////////////////////////////////////////////////////////////////////////////////////////////
407
408
  public int getObjectName(int numLayers)
409
    {
410
    switch(numLayers)
411
      {
412
      case 3: return R.string.pyra3;
413
      case 4: return R.string.pyra4;
414
      case 5: return R.string.pyra5;
415
      }
416
    return R.string.pyra3;
417
    }
418
419
///////////////////////////////////////////////////////////////////////////////////////////////////
420
421
  public int getInventor(int numLayers)
422
    {
423
    switch(numLayers)
424
      {
425
      case 3: return R.string.pyra3_inventor;
426
      case 4: return R.string.pyra4_inventor;
427
      case 5: return R.string.pyra5_inventor;
428
      }
429
    return R.string.pyra3_inventor;
430
    }
431
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433
434
  public int getComplexity(int numLayers)
435
    {
436
    switch(numLayers)
437
      {
438
      case 3: return 4;
439
      case 4: return 6;
440
      case 5: return 8;
441
      }
442
    return 4;
443
    }
444 e844c116 Leszek Koltunski
}