Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikPyraminx.java @ ece1b58d

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 40ab026e Leszek Koltunski
import org.distorted.library.effect.VertexEffectDeform;
27
import org.distorted.library.effect.VertexEffectMove;
28
import org.distorted.library.effect.VertexEffectRotate;
29 e35247b8 Leszek Koltunski
import org.distorted.library.effect.VertexEffectSink;
30 e844c116 Leszek Koltunski
import org.distorted.library.main.DistortedEffects;
31
import org.distorted.library.main.DistortedTexture;
32
import org.distorted.library.mesh.MeshBase;
33 988f434e Leszek Koltunski
import org.distorted.library.mesh.MeshJoined;
34 231771f3 Leszek Koltunski
import org.distorted.library.mesh.MeshPolygon;
35 efa8aa48 Leszek Koltunski
import org.distorted.library.mesh.MeshSquare;
36 988f434e Leszek Koltunski
import org.distorted.library.type.Static1D;
37 e844c116 Leszek Koltunski
import org.distorted.library.type.Static3D;
38
import org.distorted.library.type.Static4D;
39 1ebc4767 Leszek Koltunski
import org.distorted.main.RubikSurfaceView;
40 e844c116 Leszek Koltunski
41 7c969a6d Leszek Koltunski
import java.util.Random;
42
43
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
44
45 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
46
47
public class RubikPyraminx extends RubikObject
48
{
49 9f4c44fe Leszek Koltunski
  private static final float SQ2 = (float)Math.sqrt(2);
50
  private static final float SQ3 = (float)Math.sqrt(3);
51 10585385 Leszek Koltunski
  private static final float SQ6 = (float)Math.sqrt(6);
52 9f4c44fe Leszek Koltunski
53 ad38d800 Leszek Koltunski
  static final Static3D[] ROT_AXIS = new Static3D[]
54 e844c116 Leszek Koltunski
         {
55 9f4c44fe Leszek Koltunski
           new Static3D(         0,        1,       0 ),
56 49f67f9b Leszek Koltunski
           new Static3D(         0,  -1.0f/3, 2*SQ2/3 ),
57 9f4c44fe Leszek Koltunski
           new Static3D(-SQ2*SQ3/3,  -1.0f/3,  -SQ2/3 ),
58 49f67f9b Leszek Koltunski
           new Static3D( SQ2*SQ3/3,  -1.0f/3,  -SQ2/3 )
59 e844c116 Leszek Koltunski
         };
60
61 ad38d800 Leszek Koltunski
  static final Static3D[] FACE_AXIS = new Static3D[]
62
         {
63
           new Static3D(         0,      -1,       0 ),
64
           new Static3D(         0,  1.0f/3,-2*SQ2/3 ),
65
           new Static3D( SQ2*SQ3/3,  1.0f/3,   SQ2/3 ),
66
           new Static3D(-SQ2*SQ3/3,  1.0f/3,   SQ2/3 )
67
         };
68
69 e844c116 Leszek Koltunski
  private static final int[] FACE_COLORS = new int[]
70
         {
71 ece1b58d Leszek Koltunski
           COLOR_GREEN , COLOR_YELLOW,
72
           COLOR_BLUE  , COLOR_RED
73 e844c116 Leszek Koltunski
         };
74
75 9f4c44fe Leszek Koltunski
  // computed with res/raw/compute_quats.c
76 10585385 Leszek Koltunski
  private static final Static4D[] QUATS = new Static4D[]
77 e844c116 Leszek Koltunski
         {
78 10585385 Leszek Koltunski
           new Static4D(  0.0f,   0.0f,   0.0f,  1.0f),
79
           new Static4D(  0.0f,  SQ3/2,   0.0f,  0.5f),
80
           new Static4D( SQ2/2, -SQ3/6, -SQ6/6,  0.5f),
81
           new Static4D(-SQ2/2, -SQ3/6, -SQ6/6,  0.5f),
82
           new Static4D(  0.0f, -SQ3/6,  SQ6/3,  0.5f),
83
           new Static4D(  0.0f,  SQ3/2,   0.0f, -0.5f),
84
           new Static4D( SQ2/2, -SQ3/6, -SQ6/6, -0.5f),
85
           new Static4D(-SQ2/2, -SQ3/6, -SQ6/6, -0.5f),
86
           new Static4D(  0.0f, -SQ3/6,  SQ6/3, -0.5f),
87
           new Static4D( SQ2/2, -SQ3/3,  SQ6/6,  0.0f),
88
           new Static4D(  0.0f, -SQ3/3, -SQ6/3,  0.0f),
89
           new Static4D(-SQ2/2, -SQ3/3,  SQ6/6,  0.0f)
90 e844c116 Leszek Koltunski
         };
91
92 89a11f7b Leszek Koltunski
  private int[] mRotArray;
93 40ab026e Leszek Koltunski
  private static VertexEffectRotate[] ROTATION;
94
95
  private static MeshBase mMesh =null;
96 ad38d800 Leszek Koltunski
  private static MeshBase[] mMeshRotated = new MeshBase[ROT_AXIS.length];
97 89a11f7b Leszek Koltunski
98
  static
99
    {
100
    Static3D center = new Static3D(0,0,0);
101
    Static1D angle  = new Static1D(180.0f);
102
103 ad38d800 Leszek Koltunski
    ROTATION = new VertexEffectRotate[ROT_AXIS.length];
104 89a11f7b Leszek Koltunski
105 ad38d800 Leszek Koltunski
    for(int i = 0; i< ROT_AXIS.length; i++)
106 89a11f7b Leszek Koltunski
      {
107 ad38d800 Leszek Koltunski
      ROTATION[i] = new VertexEffectRotate( angle, ROT_AXIS[i], center);
108 40ab026e Leszek Koltunski
      mMeshRotated[i] = null;
109 89a11f7b Leszek Koltunski
      }
110
    }
111 49f67f9b Leszek Koltunski
112 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
113
114 4da7d87a Leszek Koltunski
  RubikPyraminx(int size, Static4D quat, DistortedTexture texture,
115 efa8aa48 Leszek Koltunski
                MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
116 e844c116 Leszek Koltunski
    {
117 5b893eee Leszek Koltunski
    super(size, 30, quat, texture, mesh, effects, moves, RubikObjectList.PYRA, res, scrWidth);
118 e844c116 Leszek Koltunski
    }
119
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121
122 89a11f7b Leszek Koltunski
  private void emitRow(float x, float y, float z, float dx, float dy, float dz, int n, int rot, Static3D[] array, int index)
123 49f67f9b Leszek Koltunski
    {
124
    for(int i=0; i<n; i++)
125
      {
126
      mRotArray[i+index] = rot;
127
      array[i+index] = new Static3D(x+0.5f,y+SQ2*SQ3/12,z+SQ3/6);
128
      x += dx;
129
      y += dy;
130
      z += dz;
131
      }
132
    }
133
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135
136
  private int emitLowermost(float x, float y, float z, int n, Static3D[] array)
137
    {
138
    int added = 0;
139
140 769409d2 Leszek Koltunski
    emitRow( x      +0.5f, y+SQ3*SQ2/9, z+ SQ3/18,  1.0f, 0,     0, n-1, 1, array, added);
141
    added += (n-1);
142
    emitRow( x    +1.0f/3, y+SQ3*SQ2/9, z+2*SQ3/9,  0.5f, 0, SQ3/2, n-1, 3, array, added);
143
    added += (n-1);
144
    emitRow( x+n-1-1.0f/3, y+SQ3*SQ2/9, z+2*SQ3/9, -0.5f, 0, SQ3/2, n-1, 2, array, added);
145
    added += (n-1);
146
147 49f67f9b Leszek Koltunski
    for(int i=n; i>=1; i--)
148
      {
149 769409d2 Leszek Koltunski
      emitRow(x     , y, z      , 1,0,0, i  , -1, array, added);
150 49f67f9b Leszek Koltunski
      added += i;
151 769409d2 Leszek Koltunski
      emitRow(x+0.5f, y, z+SQ3/6, 1,0,0, i-1,  0, array, added);
152
      added += (i-1);
153 49f67f9b Leszek Koltunski
      x += 0.5f;
154
      y += 0.0f;
155
      z += SQ3/2;
156
      }
157
158
    return added;
159
    }
160
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162
163
  private int emitUpper(float x, float y, float z, int n, Static3D[] array, int index)
164
    {
165
    if( n>1 )
166
      {
167 769409d2 Leszek Koltunski
      emitRow( x           , y          , z        ,  1.0f, 0,     0, n-1, -1, array, index);
168
      index += (n-1);
169
      emitRow( x+0.5f      , y+SQ3*SQ2/9, z+SQ3/18 ,  1.0f, 0,     0, n-1,  1, array, index);
170
      index += (n-1);
171
      emitRow( x+0.5f      , y          , z+SQ3/2  ,  0.5f, 0, SQ3/2, n-1, -1, array, index);
172
      index += (n-1);
173
      emitRow( x    +1.0f/3, y+SQ3*SQ2/9, z+2*SQ3/9,  0.5f, 0, SQ3/2, n-1,  3, array, index);
174 49f67f9b Leszek Koltunski
      index += (n-1);
175 769409d2 Leszek Koltunski
      emitRow( x+n-1       , y          , z        , -0.5f, 0, SQ3/2, n-1, -1, array, index);
176 49f67f9b Leszek Koltunski
      index += (n-1);
177 769409d2 Leszek Koltunski
      emitRow( x+n-1-1.0f/3, y+SQ3*SQ2/9, z+2*SQ3/9, -0.5f, 0, SQ3/2, n-1,  2, array, index);
178 49f67f9b Leszek Koltunski
      index += (n-1);
179
      }
180
    else
181
      {
182 89a11f7b Leszek Koltunski
      mRotArray[index] = -1;
183 49f67f9b Leszek Koltunski
      array[index] = new Static3D(x+0.5f,y+SQ2*SQ3/12,z+SQ3/6);
184
      index++;
185
      }
186
187
    return index;
188
    }
189
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191
// size^2 + 3*(size-1) in the lowermost layer, then 6*(size-2) in the next, 6*(size-3) in the next,
192
// ... 6 in the forelast, 1 in the last = 4size^2 - 6size +4 (if size>1)
193
194 e844c116 Leszek Koltunski
  Static3D[] getCubitPositions(int size)
195
    {
196 769409d2 Leszek Koltunski
    int numCubits = size>1 ? 4*size*size - 6*size +4 : 1;
197 c2cb520d Leszek Koltunski
    Static3D[] tmp = new Static3D[numCubits];
198 89a11f7b Leszek Koltunski
    mRotArray = new int[numCubits];
199 49f67f9b Leszek Koltunski
200
    int currentIndex = emitLowermost( -0.5f*size, -(SQ2*SQ3/12)*size, -(SQ3/6)*size, size, tmp);
201 c2cb520d Leszek Koltunski
202 49f67f9b Leszek Koltunski
    for(int i=size-1; i>=1; i--)
203 cc7dc72a Leszek Koltunski
      {
204 49f67f9b Leszek Koltunski
      currentIndex = emitUpper( -0.5f*i, ((SQ2*SQ3)/12)*(3*size-4*i), -(SQ3/6)*i, i, tmp, currentIndex);
205 cc7dc72a Leszek Koltunski
      }
206 49f67f9b Leszek Koltunski
207 c2cb520d Leszek Koltunski
    return tmp;
208 e844c116 Leszek Koltunski
    }
209
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211
212 10585385 Leszek Koltunski
  Static4D[] getQuats()
213 e844c116 Leszek Koltunski
    {
214 10585385 Leszek Koltunski
    return QUATS;
215 e844c116 Leszek Koltunski
    }
216
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218
219
  int getNumFaces()
220
    {
221
    return FACE_COLORS.length;
222
    }
223
224 eab9d8f8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
225
226
  int getNumStickerTypes()
227
    {
228
    return 1;
229
    }
230
231 7403cdfa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
232
233
  float getBasicStep()
234
    {
235
    return SQ6/3;
236
    }
237
238 8f53e513 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
239
240
  int getNumCubitFaces()
241
    {
242
    return FACE_COLORS.length;
243
    }
244
245 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
246
247
  float getScreenRatio()
248
    {
249 7381193e Leszek Koltunski
    return 0.82f;
250 f0fa83ae Leszek Koltunski
    }
251
252 eaee1ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
253
254
  boolean shouldResetTextureMaps()
255
    {
256
    return false;
257
    }
258
259 f6d06256 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
260
261
  int getFaceColor(int cubit, int cubitface, int size)
262
    {
263
    boolean belongs = isOnFace(cubit, cubitface, 0 );
264
    return belongs ? cubitface : NUM_FACES;
265
    }
266
267 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
268
269 14bd7976 Leszek Koltunski
  private MeshBase createStaticMesh(int cubit)
270 e844c116 Leszek Koltunski
    {
271 40ab026e Leszek Koltunski
    final float SQ2 = (float)Math.sqrt(2);
272
    final float SQ3 = (float)Math.sqrt(3);
273 988f434e Leszek Koltunski
    final float angleFaces = (float)((180/Math.PI)*(2*Math.asin(SQ3/3))); // angle between two faces of a tetrahedron
274
    final int MESHES=4;
275
276 231771f3 Leszek Koltunski
    int size = getSize();
277 40ab026e Leszek Koltunski
    int association = 1;
278 231771f3 Leszek Koltunski
279 befd50be Leszek Koltunski
    float D = 0.0005f;
280 e35247b8 Leszek Koltunski
    float E = SQ3/2 - 3*D*SQ2;
281 231771f3 Leszek Koltunski
    float F = 0.5f - D*SQ2*SQ3;
282
    float[] bands;
283
    int extraI, extraV;
284
285 e35247b8 Leszek Koltunski
    float[] vertices = { -F,-E/3, +F,-E/3, 0.0f,2*E/3};
286 988f434e Leszek Koltunski
287 231771f3 Leszek Koltunski
    switch(size)
288
      {
289 e35247b8 Leszek Koltunski
      case 3 : bands = new float[] { 1.0f    ,-D,
290
                                     1.0f  -D,-D*0.80f,
291
                                     1.0f-2*D,-D*0.65f,
292
                                     1.0f-4*D,+D*0.10f,
293
                                     0.50f, 0.035f,
294
                                     0.0f, 0.040f };
295 231771f3 Leszek Koltunski
                      extraI = 2;
296
                      extraV = 2;
297
                      break;
298 e35247b8 Leszek Koltunski
      case 4 : bands = new float[] { 1.0f    ,-D,
299
                                     1.0f-D*1.2f,-D*0.70f,
300
                                     1.0f-3*D, -D*0.15f,
301
                                     0.50f, 0.035f,
302
                                     0.0f, 0.040f };
303 231771f3 Leszek Koltunski
                      extraI = 2;
304
                      extraV = 2;
305
                      break;
306 e35247b8 Leszek Koltunski
      default: bands = new float[] { 1.0f    ,-D,
307
                                     1.0f-D*1.2f,-D*0.70f,
308
                                     1.0f-3*D, -D*0.15f,
309
                                     0.50f, 0.035f,
310
                                     0.0f, 0.040f };
311 231771f3 Leszek Koltunski
                      extraI = 2;
312
                      extraV = 1;
313
                      break;
314
      }
315
316 e35247b8 Leszek Koltunski
    MeshBase[] meshes = new MeshPolygon[MESHES];
317 231771f3 Leszek Koltunski
    meshes[0] = new MeshPolygon(vertices, bands, extraI,extraV);
318 e82f3f9c Leszek Koltunski
    meshes[0].setEffectAssociation(0,association,0);
319 988f434e Leszek Koltunski
320 40ab026e Leszek Koltunski
    for(int i=1; i<MESHES; i++)
321
      {
322
      association <<= 1;
323
      meshes[i] = meshes[0].copy(true);
324 e82f3f9c Leszek Koltunski
      meshes[i].setEffectAssociation(0,association,0);
325 40ab026e Leszek Koltunski
      }
326 988f434e Leszek Koltunski
327 40ab026e Leszek Koltunski
    MeshBase result = new MeshJoined(meshes);
328
329
    Static3D a0 = new Static3D(         0,        1,       0 );
330
    Static3D a1 = new Static3D(         0,  -1.0f/3, 2*SQ2/3 );
331
    Static3D a2 = new Static3D(-SQ2*SQ3/3,  -1.0f/3,  -SQ2/3 );
332
    Static3D a3 = new Static3D( SQ2*SQ3/3,  -1.0f/3,  -SQ2/3 );
333
334
    float tetraHeight = SQ2*SQ3/3;
335 52336e82 Leszek Koltunski
    float d1 = (0.75f-2*SQ2*D)*tetraHeight;
336 e35247b8 Leszek Koltunski
    float d2 =-0.06f*tetraHeight;
337
    float d3 = 0.05f*tetraHeight;
338
    float d4 = 0.70f*tetraHeight;
339
    float d5 = 1.2f;
340 40ab026e Leszek Koltunski
341
    Static3D dCen0 = new Static3D( d1*a0.get0(), d1*a0.get1(), d1*a0.get2() );
342
    Static3D dCen1 = new Static3D( d1*a1.get0(), d1*a1.get1(), d1*a1.get2() );
343
    Static3D dCen2 = new Static3D( d1*a2.get0(), d1*a2.get1(), d1*a2.get2() );
344
    Static3D dCen3 = new Static3D( d1*a3.get0(), d1*a3.get1(), d1*a3.get2() );
345
346
    Static3D dVec0 = new Static3D( d2*a0.get0(), d2*a0.get1(), d2*a0.get2() );
347
    Static3D dVec1 = new Static3D( d2*a1.get0(), d2*a1.get1(), d2*a1.get2() );
348
    Static3D dVec2 = new Static3D( d2*a2.get0(), d2*a2.get1(), d2*a2.get2() );
349
    Static3D dVec3 = new Static3D( d2*a3.get0(), d2*a3.get1(), d2*a3.get2() );
350
351
    Static4D dReg  = new Static4D(0,0,0,d3);
352
    Static1D dRad  = new Static1D(1);
353 e35247b8 Leszek Koltunski
    Static3D center= new Static3D(0,0,0);
354
    Static4D sReg  = new Static4D(0,0,0,d4);
355
    Static1D sink  = new Static1D(d5);
356 40ab026e Leszek Koltunski
357
    Static1D angle  = new Static1D(angleFaces);
358
    Static3D axis1  = new Static3D(  -1, 0,      0);
359
    Static3D axis2  = new Static3D(0.5f, 0, -SQ3/2);
360
    Static3D axis3  = new Static3D(0.5f, 0, +SQ3/2);
361
    Static3D center1= new Static3D(0,-SQ3*SQ2/12,-SQ3/6);
362
    Static3D center2= new Static3D(0,-SQ3*SQ2/12,+SQ3/3);
363
364 e35247b8 Leszek Koltunski
    VertexEffectRotate  effect1 = new VertexEffectRotate( new Static1D(90), new Static3D(1,0,0), center );
365
    VertexEffectMove    effect2 = new VertexEffectMove  ( new Static3D(0,-SQ3*SQ2/12,0) );
366
    VertexEffectRotate  effect3 = new VertexEffectRotate( new Static1D(180), new Static3D(0,0,1), center1 );
367
    VertexEffectRotate  effect4 = new VertexEffectRotate( angle, axis1, center1 );
368
    VertexEffectRotate  effect5 = new VertexEffectRotate( angle, axis2, center2 );
369
    VertexEffectRotate  effect6 = new VertexEffectRotate( angle, axis3, center2 );
370
371
    VertexEffectDeform  effect7 = new VertexEffectDeform(dVec0, dRad, dCen0, dReg);
372
    VertexEffectDeform  effect8 = new VertexEffectDeform(dVec1, dRad, dCen1, dReg);
373
    VertexEffectDeform  effect9 = new VertexEffectDeform(dVec2, dRad, dCen2, dReg);
374
    VertexEffectDeform  effect10= new VertexEffectDeform(dVec3, dRad, dCen3, dReg);
375 40ab026e Leszek Koltunski
376 e35247b8 Leszek Koltunski
    VertexEffectSink effect11= new VertexEffectSink(sink,center, sReg);
377 40ab026e Leszek Koltunski
378 e35247b8 Leszek Koltunski
    effect3.setMeshAssociation(14,-1);  // apply to mesh[1], [2] and [3]
379
    effect4.setMeshAssociation( 2,-1);  // apply only to mesh[1]
380
    effect5.setMeshAssociation( 4,-1);  // apply only to mesh[2]
381
    effect6.setMeshAssociation( 8,-1);  // apply only to mesh[3]
382 40ab026e Leszek Koltunski
383
    result.apply(effect1);
384
    result.apply(effect2);
385
    result.apply(effect3);
386
    result.apply(effect4);
387
    result.apply(effect5);
388
    result.apply(effect6);
389 e35247b8 Leszek Koltunski
390 40ab026e Leszek Koltunski
    result.apply(effect7);
391
    result.apply(effect8);
392
    result.apply(effect9);
393
    result.apply(effect10);
394 e35247b8 Leszek Koltunski
395 40ab026e Leszek Koltunski
    result.apply(effect11);
396 89a11f7b Leszek Koltunski
397
    if( mRotArray[cubit]>=0 )
398
      {
399
      result.apply( ROTATION[mRotArray[cubit]] );
400
      }
401
402 470820a7 Leszek Koltunski
    result.mergeEffComponents();
403
404 89a11f7b Leszek Koltunski
    return result;
405 e844c116 Leszek Koltunski
    }
406
407 40ab026e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
408
409 14bd7976 Leszek Koltunski
  MeshBase createCubitMesh(int cubit)
410 40ab026e Leszek Koltunski
    {
411
    int kind = mRotArray[cubit];
412
413
    if( kind>=0 )
414
      {
415 14bd7976 Leszek Koltunski
      if( mMeshRotated[kind]==null ) mMeshRotated[kind] = createStaticMesh(cubit);
416 470820a7 Leszek Koltunski
      return mMeshRotated[kind].copy(true);
417 40ab026e Leszek Koltunski
      }
418
    else
419
      {
420 14bd7976 Leszek Koltunski
      if( mMesh==null ) mMesh = createStaticMesh(cubit);
421 470820a7 Leszek Koltunski
      return mMesh.copy(true);
422 40ab026e Leszek Koltunski
      }
423
    }
424
425 7289fd6c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
426
427
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side)
428
    {
429 52336e82 Leszek Koltunski
    float STROKE = 0.044f*side;
430 7289fd6c Leszek Koltunski
    float OFF = STROKE/2 -1;
431
    float OFF2 = 0.5f*side + OFF;
432
    float HEIGHT = side - OFF;
433
    float RADIUS = side/12.0f;
434
    float ARC1_H = 0.2f*side;
435
    float ARC1_W = side*0.5f;
436
    float ARC2_W = 0.153f*side;
437
    float ARC2_H = 0.905f*side;
438
    float ARC3_W = side-ARC2_W;
439
440 e35247b8 Leszek Koltunski
    float M = SQ3/2;
441
    float D = (M/2 - 0.51f)*side;
442
443 7289fd6c Leszek Koltunski
    paint.setAntiAlias(true);
444
    paint.setStrokeWidth(STROKE);
445
    paint.setColor(FACE_COLORS[face]);
446
    paint.setStyle(Paint.Style.FILL);
447
448
    canvas.drawRect(left,top,left+side,top+side,paint);
449
450 14bd7976 Leszek Koltunski
    paint.setColor(INTERIOR_COLOR);
451 7289fd6c Leszek Koltunski
    paint.setStyle(Paint.Style.STROKE);
452
453 e35247b8 Leszek Koltunski
    canvas.drawLine(           left, M*HEIGHT+D,  side       +left, M*HEIGHT+D, paint);
454
    canvas.drawLine(      OFF +left, M*side  +D,       OFF2  +left,          D, paint);
455
    canvas.drawLine((side-OFF)+left, M*side  +D, (side-OFF2) +left,          D, paint);
456 7289fd6c Leszek Koltunski
457 e35247b8 Leszek Koltunski
    canvas.drawArc( ARC1_W-RADIUS+left, M*(ARC1_H-RADIUS)+D, ARC1_W+RADIUS+left, M*(ARC1_H+RADIUS)+D, 225, 90, false, paint);
458
    canvas.drawArc( ARC2_W-RADIUS+left, M*(ARC2_H-RADIUS)+D, ARC2_W+RADIUS+left, M*(ARC2_H+RADIUS)+D, 105, 90, false, paint);
459
    canvas.drawArc( ARC3_W-RADIUS+left, M*(ARC2_H-RADIUS)+D, ARC3_W+RADIUS+left, M*(ARC2_H+RADIUS)+D, 345, 90, false, paint);
460 7289fd6c Leszek Koltunski
    }
461
462 fb377dae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
463 7403cdfa Leszek Koltunski
// SQ6/3 = height of the tetrahedron
464 fb377dae Leszek Koltunski
465
  float returnMultiplier()
466
    {
467 7403cdfa Leszek Koltunski
    return getSize()/(SQ6/3);
468 fb377dae Leszek Koltunski
    }
469
470 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
471
472
  float[] getRowChances()
473
    {
474
    int size = getSize();
475
    int total = size*(size+1)/2;
476
    float running=0.0f;
477
    float[] chances = new float[size];
478
479
    for(int i=0; i<size; i++)
480
      {
481
      running += (size-i);
482
      chances[i] = running / total;
483
      }
484
485
    return chances;
486
    }
487
488 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
489
// PUBLIC API
490
491 12ad3fca Leszek Koltunski
  public Static3D[] getRotationAxis()
492
    {
493 ad38d800 Leszek Koltunski
    return ROT_AXIS;
494 12ad3fca Leszek Koltunski
    }
495
496
///////////////////////////////////////////////////////////////////////////////////////////////////
497
498 e844c116 Leszek Koltunski
  public int getBasicAngle()
499
    {
500
    return 3;
501
    }
502 39e74052 Leszek Koltunski
503
///////////////////////////////////////////////////////////////////////////////////////////////////
504
505 fb377dae Leszek Koltunski
  public int computeRowFromOffset(float offset)
506 39e74052 Leszek Koltunski
    {
507 7403cdfa Leszek Koltunski
    return (int)(getSize()*offset/(SQ6/3));
508 39e74052 Leszek Koltunski
    }
509 e46e17fb Leszek Koltunski
510 5cf34c5f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
511
512 7c969a6d Leszek Koltunski
  public float returnRotationFactor(float offset)
513 5cf34c5f Leszek Koltunski
    {
514
    int size = getSize();
515 7c969a6d Leszek Koltunski
    int row  = (int)(size*offset/(SQ3/2));
516 5cf34c5f Leszek Koltunski
517 7c969a6d Leszek Koltunski
    return ((float)size)/(size-row);
518
    }
519
520
///////////////////////////////////////////////////////////////////////////////////////////////////
521
522
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
523
    {
524
    int numAxis = ROTATION_AXIS.length;
525
526
    if( oldRotAxis == START_AXIS )
527 5cf34c5f Leszek Koltunski
      {
528 7c969a6d Leszek Koltunski
      return rnd.nextInt(numAxis);
529
      }
530
    else
531
      {
532
      int newVector = rnd.nextInt(numAxis-1);
533
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
534 5cf34c5f Leszek Koltunski
      }
535
    }
536
537 e46e17fb Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
538
539 7c969a6d Leszek Koltunski
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
540 e46e17fb Leszek Koltunski
    {
541 7c969a6d Leszek Koltunski
    float rowFloat = rnd.nextFloat();
542 e46e17fb Leszek Koltunski
543 7c969a6d Leszek Koltunski
    for(int row=0; row<mRowChances.length; row++)
544
      {
545
      if( rowFloat<=mRowChances[row] ) return row;
546
      }
547
548
    return 0;
549 e46e17fb Leszek Koltunski
    }
550 f0336037 Leszek Koltunski
551 6b6504fe Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
552
553
  public boolean isSolved()
554
    {
555
    int index = CUBITS[0].mQuatIndex;
556
557
    for(int i=1; i<NUM_CUBITS; i++)
558
      {
559
      if( !thereIsNoVisibleDifference(CUBITS[i], index) ) return false;
560
      }
561
562
    return true;
563
    }
564
565 1ebc4767 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
566
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different
567
// then if it were rotated by quaternion 'quat'.
568
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two
569
// middle squares get interchanged. No visible difference!
570
//
571
// So: this is true iff the cubit
572
// a) is a corner or edge and the quaternions are the same
573
// b) is inside one of the faces and after rotations by both quats it ends up on the same face.
574
575 6b6504fe Leszek Koltunski
  private boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex)
576 1ebc4767 Leszek Koltunski
    {
577
    if ( cubit.mQuatIndex == quatIndex ) return true;
578
579
    int belongsToHowManyFaces = 0;
580
    int size = getSize()-1;
581
    float row;
582
    final float MAX_ERROR = 0.01f;
583
584
    for(int i=0; i<NUM_AXIS; i++)
585
      {
586
      row = cubit.mRotationRow[i];
587
      if( (row     <MAX_ERROR && row     >-MAX_ERROR) ||
588
          (row-size<MAX_ERROR && row-size>-MAX_ERROR)  ) belongsToHowManyFaces++;
589
      }
590
591
    switch(belongsToHowManyFaces)
592
      {
593
      case 0 : return true ;  // 'inside' cubit that does not lie on any face
594
      case 1 :                // cubit that lies inside one of the faces
595
               Static3D orig = cubit.getOrigPosition();
596
               Static4D quat1 = QUATS[quatIndex];
597
               Static4D quat2 = QUATS[cubit.mQuatIndex];
598
599
               Static4D cubitCenter = new Static4D( orig.get0(), orig.get1(), orig.get2(), 0);
600
               Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 );
601
               Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 );
602
603
               float row1, row2, row3, row4;
604
               float ax,ay,az;
605
               Static3D axis;
606
               float x1 = rotated1.get0();
607
               float y1 = rotated1.get1();
608
               float z1 = rotated1.get2();
609
               float x2 = rotated2.get0();
610
               float y2 = rotated2.get1();
611
               float z2 = rotated2.get2();
612
613
               for(int i=0; i<NUM_AXIS; i++)
614
                 {
615
                 axis = ROTATION_AXIS[i];
616
                 ax = axis.get0();
617
                 ay = axis.get1();
618
                 az = axis.get2();
619
620
                 row1 = ((x1*ax + y1*ay + z1*az) - mStart) / mStep;
621
                 row2 = ((x2*ax + y2*ay + z2*az) - mStart) / mStep;
622
                 row3 = row1 - size;
623
                 row4 = row2 - size;
624
625
                 if( (row1<MAX_ERROR && row1>-MAX_ERROR && row2<MAX_ERROR && row2>-MAX_ERROR) ||
626
                     (row3<MAX_ERROR && row3>-MAX_ERROR && row4<MAX_ERROR && row4>-MAX_ERROR)  )
627
                   {
628
                   return true;
629
                   }
630
                 }
631
               return false;
632
633
      default: return false;  // edge or corner
634
      }
635
    }
636
637 f0336037 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
638 ee35e63c Leszek Koltunski
// only needed for solvers - there are no Pyraminx solvers ATM)
639 f0336037 Leszek Koltunski
640 20931cf6 Leszek Koltunski
  public String retObjectString()
641 f0336037 Leszek Koltunski
    {
642
    return "";
643
    }
644 e844c116 Leszek Koltunski
}