Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikPyraminx.java @ 3717a94e

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 ad38d800 Leszek Koltunski
           0xff00ff00, 0xffffff00,  // FACE_AXIS[0] (GREEN ) FACE_AXIS[1] (YELLOW )
72
           0xff0000ff, 0xffff0000   // FACE_AXIS[2] (BLUE  ) FACE_AXIS[3] (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 f6d06256 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
253
254
  int getFaceColor(int cubit, int cubitface, int size)
255
    {
256
    boolean belongs = isOnFace(cubit, cubitface, 0 );
257
    return belongs ? cubitface : NUM_FACES;
258
    }
259
260 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
261
262 14bd7976 Leszek Koltunski
  private MeshBase createStaticMesh(int cubit)
263 e844c116 Leszek Koltunski
    {
264 40ab026e Leszek Koltunski
    final float SQ2 = (float)Math.sqrt(2);
265
    final float SQ3 = (float)Math.sqrt(3);
266 988f434e Leszek Koltunski
    final float angleFaces = (float)((180/Math.PI)*(2*Math.asin(SQ3/3))); // angle between two faces of a tetrahedron
267
    final int MESHES=4;
268
269 231771f3 Leszek Koltunski
    int size = getSize();
270 40ab026e Leszek Koltunski
    int association = 1;
271 231771f3 Leszek Koltunski
272 befd50be Leszek Koltunski
    float D = 0.0005f;
273 e35247b8 Leszek Koltunski
    float E = SQ3/2 - 3*D*SQ2;
274 231771f3 Leszek Koltunski
    float F = 0.5f - D*SQ2*SQ3;
275
    float[] bands;
276
    int extraI, extraV;
277
278 e35247b8 Leszek Koltunski
    float[] vertices = { -F,-E/3, +F,-E/3, 0.0f,2*E/3};
279 988f434e Leszek Koltunski
280 231771f3 Leszek Koltunski
    switch(size)
281
      {
282 e35247b8 Leszek Koltunski
      case 3 : bands = new float[] { 1.0f    ,-D,
283
                                     1.0f  -D,-D*0.80f,
284
                                     1.0f-2*D,-D*0.65f,
285
                                     1.0f-4*D,+D*0.10f,
286
                                     0.50f, 0.035f,
287
                                     0.0f, 0.040f };
288 231771f3 Leszek Koltunski
                      extraI = 2;
289
                      extraV = 2;
290
                      break;
291 e35247b8 Leszek Koltunski
      case 4 : bands = new float[] { 1.0f    ,-D,
292
                                     1.0f-D*1.2f,-D*0.70f,
293
                                     1.0f-3*D, -D*0.15f,
294
                                     0.50f, 0.035f,
295
                                     0.0f, 0.040f };
296 231771f3 Leszek Koltunski
                      extraI = 2;
297
                      extraV = 2;
298
                      break;
299 e35247b8 Leszek Koltunski
      default: bands = new float[] { 1.0f    ,-D,
300
                                     1.0f-D*1.2f,-D*0.70f,
301
                                     1.0f-3*D, -D*0.15f,
302
                                     0.50f, 0.035f,
303
                                     0.0f, 0.040f };
304 231771f3 Leszek Koltunski
                      extraI = 2;
305
                      extraV = 1;
306
                      break;
307
      }
308
309 e35247b8 Leszek Koltunski
    MeshBase[] meshes = new MeshPolygon[MESHES];
310 231771f3 Leszek Koltunski
    meshes[0] = new MeshPolygon(vertices, bands, extraI,extraV);
311 e82f3f9c Leszek Koltunski
    meshes[0].setEffectAssociation(0,association,0);
312 988f434e Leszek Koltunski
313 40ab026e Leszek Koltunski
    for(int i=1; i<MESHES; i++)
314
      {
315
      association <<= 1;
316
      meshes[i] = meshes[0].copy(true);
317 e82f3f9c Leszek Koltunski
      meshes[i].setEffectAssociation(0,association,0);
318 40ab026e Leszek Koltunski
      }
319 988f434e Leszek Koltunski
320 40ab026e Leszek Koltunski
    MeshBase result = new MeshJoined(meshes);
321
322
    Static3D a0 = new Static3D(         0,        1,       0 );
323
    Static3D a1 = new Static3D(         0,  -1.0f/3, 2*SQ2/3 );
324
    Static3D a2 = new Static3D(-SQ2*SQ3/3,  -1.0f/3,  -SQ2/3 );
325
    Static3D a3 = new Static3D( SQ2*SQ3/3,  -1.0f/3,  -SQ2/3 );
326
327
    float tetraHeight = SQ2*SQ3/3;
328 52336e82 Leszek Koltunski
    float d1 = (0.75f-2*SQ2*D)*tetraHeight;
329 e35247b8 Leszek Koltunski
    float d2 =-0.06f*tetraHeight;
330
    float d3 = 0.05f*tetraHeight;
331
    float d4 = 0.70f*tetraHeight;
332
    float d5 = 1.2f;
333 40ab026e Leszek Koltunski
334
    Static3D dCen0 = new Static3D( d1*a0.get0(), d1*a0.get1(), d1*a0.get2() );
335
    Static3D dCen1 = new Static3D( d1*a1.get0(), d1*a1.get1(), d1*a1.get2() );
336
    Static3D dCen2 = new Static3D( d1*a2.get0(), d1*a2.get1(), d1*a2.get2() );
337
    Static3D dCen3 = new Static3D( d1*a3.get0(), d1*a3.get1(), d1*a3.get2() );
338
339
    Static3D dVec0 = new Static3D( d2*a0.get0(), d2*a0.get1(), d2*a0.get2() );
340
    Static3D dVec1 = new Static3D( d2*a1.get0(), d2*a1.get1(), d2*a1.get2() );
341
    Static3D dVec2 = new Static3D( d2*a2.get0(), d2*a2.get1(), d2*a2.get2() );
342
    Static3D dVec3 = new Static3D( d2*a3.get0(), d2*a3.get1(), d2*a3.get2() );
343
344
    Static4D dReg  = new Static4D(0,0,0,d3);
345
    Static1D dRad  = new Static1D(1);
346 e35247b8 Leszek Koltunski
    Static3D center= new Static3D(0,0,0);
347
    Static4D sReg  = new Static4D(0,0,0,d4);
348
    Static1D sink  = new Static1D(d5);
349 40ab026e Leszek Koltunski
350
    Static1D angle  = new Static1D(angleFaces);
351
    Static3D axis1  = new Static3D(  -1, 0,      0);
352
    Static3D axis2  = new Static3D(0.5f, 0, -SQ3/2);
353
    Static3D axis3  = new Static3D(0.5f, 0, +SQ3/2);
354
    Static3D center1= new Static3D(0,-SQ3*SQ2/12,-SQ3/6);
355
    Static3D center2= new Static3D(0,-SQ3*SQ2/12,+SQ3/3);
356
357 e35247b8 Leszek Koltunski
    VertexEffectRotate  effect1 = new VertexEffectRotate( new Static1D(90), new Static3D(1,0,0), center );
358
    VertexEffectMove    effect2 = new VertexEffectMove  ( new Static3D(0,-SQ3*SQ2/12,0) );
359
    VertexEffectRotate  effect3 = new VertexEffectRotate( new Static1D(180), new Static3D(0,0,1), center1 );
360
    VertexEffectRotate  effect4 = new VertexEffectRotate( angle, axis1, center1 );
361
    VertexEffectRotate  effect5 = new VertexEffectRotate( angle, axis2, center2 );
362
    VertexEffectRotate  effect6 = new VertexEffectRotate( angle, axis3, center2 );
363
364
    VertexEffectDeform  effect7 = new VertexEffectDeform(dVec0, dRad, dCen0, dReg);
365
    VertexEffectDeform  effect8 = new VertexEffectDeform(dVec1, dRad, dCen1, dReg);
366
    VertexEffectDeform  effect9 = new VertexEffectDeform(dVec2, dRad, dCen2, dReg);
367
    VertexEffectDeform  effect10= new VertexEffectDeform(dVec3, dRad, dCen3, dReg);
368 40ab026e Leszek Koltunski
369 e35247b8 Leszek Koltunski
    VertexEffectSink effect11= new VertexEffectSink(sink,center, sReg);
370 40ab026e Leszek Koltunski
371 e35247b8 Leszek Koltunski
    effect3.setMeshAssociation(14,-1);  // apply to mesh[1], [2] and [3]
372
    effect4.setMeshAssociation( 2,-1);  // apply only to mesh[1]
373
    effect5.setMeshAssociation( 4,-1);  // apply only to mesh[2]
374
    effect6.setMeshAssociation( 8,-1);  // apply only to mesh[3]
375 40ab026e Leszek Koltunski
376
    result.apply(effect1);
377
    result.apply(effect2);
378
    result.apply(effect3);
379
    result.apply(effect4);
380
    result.apply(effect5);
381
    result.apply(effect6);
382 e35247b8 Leszek Koltunski
383 40ab026e Leszek Koltunski
    result.apply(effect7);
384
    result.apply(effect8);
385
    result.apply(effect9);
386
    result.apply(effect10);
387 e35247b8 Leszek Koltunski
388 40ab026e Leszek Koltunski
    result.apply(effect11);
389 89a11f7b Leszek Koltunski
390
    if( mRotArray[cubit]>=0 )
391
      {
392
      result.apply( ROTATION[mRotArray[cubit]] );
393
      }
394
395 470820a7 Leszek Koltunski
    result.mergeEffComponents();
396
397 89a11f7b Leszek Koltunski
    return result;
398 e844c116 Leszek Koltunski
    }
399
400 40ab026e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
401
402 14bd7976 Leszek Koltunski
  MeshBase createCubitMesh(int cubit)
403 40ab026e Leszek Koltunski
    {
404
    int kind = mRotArray[cubit];
405
406
    if( kind>=0 )
407
      {
408 14bd7976 Leszek Koltunski
      if( mMeshRotated[kind]==null ) mMeshRotated[kind] = createStaticMesh(cubit);
409 470820a7 Leszek Koltunski
      return mMeshRotated[kind].copy(true);
410 40ab026e Leszek Koltunski
      }
411
    else
412
      {
413 14bd7976 Leszek Koltunski
      if( mMesh==null ) mMesh = createStaticMesh(cubit);
414 470820a7 Leszek Koltunski
      return mMesh.copy(true);
415 40ab026e Leszek Koltunski
      }
416
    }
417
418 7289fd6c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
419
420
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side)
421
    {
422 52336e82 Leszek Koltunski
    float STROKE = 0.044f*side;
423 7289fd6c Leszek Koltunski
    float OFF = STROKE/2 -1;
424
    float OFF2 = 0.5f*side + OFF;
425
    float HEIGHT = side - OFF;
426
    float RADIUS = side/12.0f;
427
    float ARC1_H = 0.2f*side;
428
    float ARC1_W = side*0.5f;
429
    float ARC2_W = 0.153f*side;
430
    float ARC2_H = 0.905f*side;
431
    float ARC3_W = side-ARC2_W;
432
433 e35247b8 Leszek Koltunski
    float M = SQ3/2;
434
    float D = (M/2 - 0.51f)*side;
435
436 7289fd6c Leszek Koltunski
    paint.setAntiAlias(true);
437
    paint.setStrokeWidth(STROKE);
438
    paint.setColor(FACE_COLORS[face]);
439
    paint.setStyle(Paint.Style.FILL);
440
441
    canvas.drawRect(left,top,left+side,top+side,paint);
442
443 14bd7976 Leszek Koltunski
    paint.setColor(INTERIOR_COLOR);
444 7289fd6c Leszek Koltunski
    paint.setStyle(Paint.Style.STROKE);
445
446 e35247b8 Leszek Koltunski
    canvas.drawLine(           left, M*HEIGHT+D,  side       +left, M*HEIGHT+D, paint);
447
    canvas.drawLine(      OFF +left, M*side  +D,       OFF2  +left,          D, paint);
448
    canvas.drawLine((side-OFF)+left, M*side  +D, (side-OFF2) +left,          D, paint);
449 7289fd6c Leszek Koltunski
450 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);
451
    canvas.drawArc( ARC2_W-RADIUS+left, M*(ARC2_H-RADIUS)+D, ARC2_W+RADIUS+left, M*(ARC2_H+RADIUS)+D, 105, 90, false, paint);
452
    canvas.drawArc( ARC3_W-RADIUS+left, M*(ARC2_H-RADIUS)+D, ARC3_W+RADIUS+left, M*(ARC2_H+RADIUS)+D, 345, 90, false, paint);
453 7289fd6c Leszek Koltunski
    }
454
455 fb377dae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
456 7403cdfa Leszek Koltunski
// SQ6/3 = height of the tetrahedron
457 fb377dae Leszek Koltunski
458
  float returnMultiplier()
459
    {
460 7403cdfa Leszek Koltunski
    return getSize()/(SQ6/3);
461 fb377dae Leszek Koltunski
    }
462
463 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
464
465
  float[] getRowChances()
466
    {
467
    int size = getSize();
468
    int total = size*(size+1)/2;
469
    float running=0.0f;
470
    float[] chances = new float[size];
471
472
    for(int i=0; i<size; i++)
473
      {
474
      running += (size-i);
475
      chances[i] = running / total;
476
      }
477
478
    return chances;
479
    }
480
481 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
482
// PUBLIC API
483
484 12ad3fca Leszek Koltunski
  public Static3D[] getRotationAxis()
485
    {
486 ad38d800 Leszek Koltunski
    return ROT_AXIS;
487 12ad3fca Leszek Koltunski
    }
488
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490
491 e844c116 Leszek Koltunski
  public int getBasicAngle()
492
    {
493
    return 3;
494
    }
495 39e74052 Leszek Koltunski
496
///////////////////////////////////////////////////////////////////////////////////////////////////
497
498 fb377dae Leszek Koltunski
  public int computeRowFromOffset(float offset)
499 39e74052 Leszek Koltunski
    {
500 7403cdfa Leszek Koltunski
    return (int)(getSize()*offset/(SQ6/3));
501 39e74052 Leszek Koltunski
    }
502 e46e17fb Leszek Koltunski
503 5cf34c5f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
504
505 7c969a6d Leszek Koltunski
  public float returnRotationFactor(float offset)
506 5cf34c5f Leszek Koltunski
    {
507
    int size = getSize();
508 7c969a6d Leszek Koltunski
    int row  = (int)(size*offset/(SQ3/2));
509 5cf34c5f Leszek Koltunski
510 7c969a6d Leszek Koltunski
    return ((float)size)/(size-row);
511
    }
512
513
///////////////////////////////////////////////////////////////////////////////////////////////////
514
515
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
516
    {
517
    int numAxis = ROTATION_AXIS.length;
518
519
    if( oldRotAxis == START_AXIS )
520 5cf34c5f Leszek Koltunski
      {
521 7c969a6d Leszek Koltunski
      return rnd.nextInt(numAxis);
522
      }
523
    else
524
      {
525
      int newVector = rnd.nextInt(numAxis-1);
526
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
527 5cf34c5f Leszek Koltunski
      }
528
    }
529
530 e46e17fb Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
531
532 7c969a6d Leszek Koltunski
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
533 e46e17fb Leszek Koltunski
    {
534 7c969a6d Leszek Koltunski
    float rowFloat = rnd.nextFloat();
535 e46e17fb Leszek Koltunski
536 7c969a6d Leszek Koltunski
    for(int row=0; row<mRowChances.length; row++)
537
      {
538
      if( rowFloat<=mRowChances[row] ) return row;
539
      }
540
541
    return 0;
542 e46e17fb Leszek Koltunski
    }
543 f0336037 Leszek Koltunski
544 6b6504fe Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
545
546
  public boolean isSolved()
547
    {
548
    int index = CUBITS[0].mQuatIndex;
549
550
    for(int i=1; i<NUM_CUBITS; i++)
551
      {
552
      if( !thereIsNoVisibleDifference(CUBITS[i], index) ) return false;
553
      }
554
555
    return true;
556
    }
557
558 1ebc4767 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
559
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different
560
// then if it were rotated by quaternion 'quat'.
561
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two
562
// middle squares get interchanged. No visible difference!
563
//
564
// So: this is true iff the cubit
565
// a) is a corner or edge and the quaternions are the same
566
// b) is inside one of the faces and after rotations by both quats it ends up on the same face.
567
568 6b6504fe Leszek Koltunski
  private boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex)
569 1ebc4767 Leszek Koltunski
    {
570
    if ( cubit.mQuatIndex == quatIndex ) return true;
571
572
    int belongsToHowManyFaces = 0;
573
    int size = getSize()-1;
574
    float row;
575
    final float MAX_ERROR = 0.01f;
576
577
    for(int i=0; i<NUM_AXIS; i++)
578
      {
579
      row = cubit.mRotationRow[i];
580
      if( (row     <MAX_ERROR && row     >-MAX_ERROR) ||
581
          (row-size<MAX_ERROR && row-size>-MAX_ERROR)  ) belongsToHowManyFaces++;
582
      }
583
584
    switch(belongsToHowManyFaces)
585
      {
586
      case 0 : return true ;  // 'inside' cubit that does not lie on any face
587
      case 1 :                // cubit that lies inside one of the faces
588
               Static3D orig = cubit.getOrigPosition();
589
               Static4D quat1 = QUATS[quatIndex];
590
               Static4D quat2 = QUATS[cubit.mQuatIndex];
591
592
               Static4D cubitCenter = new Static4D( orig.get0(), orig.get1(), orig.get2(), 0);
593
               Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 );
594
               Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 );
595
596
               float row1, row2, row3, row4;
597
               float ax,ay,az;
598
               Static3D axis;
599
               float x1 = rotated1.get0();
600
               float y1 = rotated1.get1();
601
               float z1 = rotated1.get2();
602
               float x2 = rotated2.get0();
603
               float y2 = rotated2.get1();
604
               float z2 = rotated2.get2();
605
606
               for(int i=0; i<NUM_AXIS; i++)
607
                 {
608
                 axis = ROTATION_AXIS[i];
609
                 ax = axis.get0();
610
                 ay = axis.get1();
611
                 az = axis.get2();
612
613
                 row1 = ((x1*ax + y1*ay + z1*az) - mStart) / mStep;
614
                 row2 = ((x2*ax + y2*ay + z2*az) - mStart) / mStep;
615
                 row3 = row1 - size;
616
                 row4 = row2 - size;
617
618
                 if( (row1<MAX_ERROR && row1>-MAX_ERROR && row2<MAX_ERROR && row2>-MAX_ERROR) ||
619
                     (row3<MAX_ERROR && row3>-MAX_ERROR && row4<MAX_ERROR && row4>-MAX_ERROR)  )
620
                   {
621
                   return true;
622
                   }
623
                 }
624
               return false;
625
626
      default: return false;  // edge or corner
627
      }
628
    }
629
630 f0336037 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
631 ee35e63c Leszek Koltunski
// only needed for solvers - there are no Pyraminx solvers ATM)
632 f0336037 Leszek Koltunski
633 20931cf6 Leszek Koltunski
  public String retObjectString()
634 f0336037 Leszek Koltunski
    {
635
    return "";
636
    }
637 e844c116 Leszek Koltunski
}