Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyPyraminx.java @ 749ef882

1
///////////////////////////////////////////////////////////////////////////////////////////////////
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
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.helpers.FactoryCubit;
27
import org.distorted.helpers.FactorySticker;
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
import org.distorted.main.R;
35

    
36
import java.util.Random;
37

    
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

    
40
public class TwistyPyraminx extends TwistyObject
41
{
42
  static final Static3D[] ROT_AXIS = new Static3D[]
43
         {
44
           new Static3D(     0,-SQ3/3,-SQ6/3),
45
           new Static3D(     0,-SQ3/3,+SQ6/3),
46
           new Static3D(+SQ6/3,+SQ3/3,     0),
47
           new Static3D(-SQ6/3,+SQ3/3,     0),
48
         };
49

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

    
56
  // computed with res/raw/compute_quats.c
57
  private static final Static4D[] QUATS = new Static4D[]
58
         {
59
           new Static4D(  0.0f,   0.0f,   0.0f,  1.0f),
60
           new Static4D(  0.0f,   1.0f,   0.0f,  0.0f),
61
           new Static4D( SQ2/2,   0.5f,   0.0f,  0.5f),
62
           new Static4D(-SQ2/2,   0.5f,   0.0f,  0.5f),
63
           new Static4D(  0.0f,  -0.5f, -SQ2/2,  0.5f),
64
           new Static4D(  0.0f,  -0.5f,  SQ2/2,  0.5f),
65
           new Static4D( SQ2/2,   0.5f,   0.0f, -0.5f),
66
           new Static4D(-SQ2/2,   0.5f,   0.0f, -0.5f),
67
           new Static4D(  0.0f,  -0.5f, -SQ2/2, -0.5f),
68
           new Static4D(  0.0f,  -0.5f,  SQ2/2, -0.5f),
69
           new Static4D( SQ2/2,   0.0f,  SQ2/2,  0.0f),
70
           new Static4D(-SQ2/2,   0.0f,  SQ2/2,  0.0f)
71
         };
72

    
73
  private static MeshBase mOctaMesh, mTetraMesh;
74

    
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76

    
77
  TwistyPyraminx(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
78
                 DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
79
    {
80
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.PYRA, res, scrWidth);
81
    }
82

    
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84

    
85
  private void addTetrahedralLattice(int size, int index, float[][] pos)
86
    {
87
    final float DX = 1.0f;
88
    final float DY = SQ2/2;
89
    final float DZ = 1.0f;
90

    
91
    float startX = 0.0f;
92
    float startY =-DY*(size-1)/2;
93
    float startZ = DZ*(size-1)/2;
94

    
95
    for(int layer=0; layer<size; layer++)
96
      {
97
      float currX = startX;
98
      float currY = startY;
99

    
100
      for(int x=0; x<layer+1; x++)
101
        {
102
        float currZ = startZ;
103

    
104
        for(int z=0; z<size-layer; z++)
105
          {
106
          pos[index] = new float[] {currX,currY,currZ};
107
          index++;
108
          currZ -= DZ;
109
          }
110

    
111
        currX += DX;
112
        }
113

    
114
      startX-=DX/2;
115
      startY+=DY;
116
      startZ-=DZ/2;
117
      }
118
    }
119

    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121
// there are (n^3-n)/6 octahedrons and ((n+1)^3 - (n+1))/6 tetrahedrons
122

    
123
  float[][] getCubitPositions(int size)
124
    {
125
    int numOcta = (size-1)*size*(size+1)/6;
126
    int numTetra= size*(size+1)*(size+2)/6;
127
    float[][] ret = new float[numOcta+numTetra][];
128

    
129
    addTetrahedralLattice(size-1,      0,ret);
130
    addTetrahedralLattice(size  ,numOcta,ret);
131

    
132
    return ret;
133
    }
134

    
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

    
137
  Static4D[] getQuats()
138
    {
139
    return QUATS;
140
    }
141

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

    
144
  int getNumFaces()
145
    {
146
    return FACE_COLORS.length;
147
    }
148

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150

    
151
  int getNumStickerTypes(int numLayers)
152
    {
153
    return 1;
154
    }
155

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

    
158
  float[] getCuts(int size)
159
    {
160
    float[] cuts = new float[size-1];
161

    
162
    for(int i=0; i<size-1; i++)
163
      {
164
      cuts[i] = (1.0f-0.25f*size+i)*(SQ6/3);
165
      }
166

    
167
    return cuts;
168
    }
169

    
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171

    
172
  int getNumCubitFaces()
173
    {
174
    return 8;
175
    }
176

    
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

    
179
  float getScreenRatio()
180
    {
181
    return 0.82f;
182
    }
183

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

    
186
  boolean shouldResetTextureMaps()
187
    {
188
    return false;
189
    }
190

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

    
193
  private int faceColor(int cubit, int axis)
194
    {
195
    return CUBITS[cubit].mRotationRow[axis] == 1 ? axis : NUM_FACES;
196
    }
197

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

    
200
  int getFaceColor(int cubit, int cubitface, int size)
201
    {
202
    if( cubit< (size-1)*size*(size+1)/6 )
203
      {
204
      switch( cubitface )
205
        {
206
        case 0: return faceColor(cubit,0);
207
        case 2: return faceColor(cubit,1);
208
        case 5: return faceColor(cubit,3);
209
        case 7: return faceColor(cubit,2);
210
        default:return NUM_FACES;
211
        }
212
      }
213
    else
214
      {
215
      return cubitface<NUM_FACES ? faceColor(cubit,cubitface) : NUM_FACES;
216
      }
217
    }
218

    
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

    
221
  MeshBase createCubitMesh(int cubit, int numLayers)
222
    {
223
    if( cubit< (numLayers-1)*numLayers*(numLayers+1)/6 )
224
      {
225
      if( mOctaMesh==null ) mOctaMesh = FactoryCubit.getInstance().createOctaMesh();
226
      return mOctaMesh.copy(true);
227
      }
228
    else
229
      {
230
      if( mTetraMesh==null ) mTetraMesh = FactoryCubit.getInstance().createTetraMesh();
231
      return mTetraMesh.copy(true);
232
      }
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
238
    {
239
    float E = 0.75f;
240
    float F = 0.50f;
241
    float R = 0.06f;
242
    float S = 0.08f;
243
    float[] vertices = { -F,-E/3, +F,-E/3, 0.0f,2*E/3};
244

    
245
    FactorySticker factory = FactorySticker.getInstance();
246
    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face], R);
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250
// SQ6/3 = height of the tetrahedron
251

    
252
  float returnMultiplier()
253
    {
254
    return getNumLayers()/(SQ6/3);
255
    }
256

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

    
259
  float[] getRowChances(int numLayers)
260
    {
261
    int total = numLayers*(numLayers+1)/2;
262
    float running=0.0f;
263
    float[] chances = new float[numLayers];
264

    
265
    for(int i=0; i<numLayers; i++)
266
      {
267
      running += (numLayers-i);
268
      chances[i] = running / total;
269
      }
270

    
271
    return chances;
272
    }
273

    
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275
// PUBLIC API
276

    
277
  public Static3D[] getRotationAxis()
278
    {
279
    return ROT_AXIS;
280
    }
281

    
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283

    
284
  public int getBasicAngle()
285
    {
286
    return 3;
287
    }
288

    
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290

    
291
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
292
    {
293
    if( num==0 )
294
      {
295
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
296
      }
297
    else
298
      {
299
      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
300
      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
301
      }
302

    
303
    float rowFloat = rnd.nextFloat();
304

    
305
    for(int row=0; row<mRowChances.length; row++)
306
      {
307
      if( rowFloat<=mRowChances[row] )
308
        {
309
        scramble[num][1] = row;
310
        break;
311
        }
312
      }
313

    
314
    switch( rnd.nextInt(2) )
315
      {
316
      case 0: scramble[num][2] = -1; break;
317
      case 1: scramble[num][2] =  1; break;
318
      }
319
    }
320

    
321
///////////////////////////////////////////////////////////////////////////////////////////////////
322

    
323
  public boolean isSolved()
324
    {
325
    int index = CUBITS[0].mQuatIndex;
326

    
327
    for(int i=1; i<NUM_CUBITS; i++)
328
      {
329
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
330
      }
331

    
332
    return true;
333
    }
334

    
335
////////////////////////////////////////////////////////////////////////
336
// only needed for solvers - there are no Pyraminx solvers ATM)
337

    
338
  public String retObjectString()
339
    {
340
    return "";
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  public int getObjectName(int numLayers)
346
    {
347
    switch(numLayers)
348
      {
349
      case 3: return R.string.pyra3;
350
      case 4: return R.string.pyra4;
351
      case 5: return R.string.pyra5;
352
      }
353
    return R.string.pyra3;
354
    }
355

    
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357

    
358
  public int getInventor(int numLayers)
359
    {
360
    switch(numLayers)
361
      {
362
      case 3: return R.string.pyra3_inventor;
363
      case 4: return R.string.pyra4_inventor;
364
      case 5: return R.string.pyra5_inventor;
365
      }
366
    return R.string.pyra3_inventor;
367
    }
368

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

    
371
  public int getComplexity(int numLayers)
372
    {
373
    switch(numLayers)
374
      {
375
      case 3: return 4;
376
      case 4: return 6;
377
      case 5: return 8;
378
      }
379
    return 4;
380
    }
381
}
(30-30/33)