Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikPyraminx.java @ 3e5ad461

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