Project

General

Profile

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

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

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