Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistySkewb.java @ 9c2f0c91

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objects;
21

    
22
import android.content.res.Resources;
23
import android.graphics.Canvas;
24
import android.graphics.Paint;
25

    
26
import org.distorted.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.effect.VertexEffectDeform;
28
import org.distorted.library.effect.VertexEffectMove;
29
import org.distorted.library.effect.VertexEffectRotate;
30
import org.distorted.library.effect.VertexEffectScale;
31
import org.distorted.library.main.DistortedEffects;
32
import org.distorted.library.main.DistortedTexture;
33
import org.distorted.library.mesh.MeshBase;
34
import org.distorted.library.mesh.MeshJoined;
35
import org.distorted.library.mesh.MeshPolygon;
36
import org.distorted.library.mesh.MeshSquare;
37
import org.distorted.library.mesh.MeshTriangle;
38
import org.distorted.library.type.Static1D;
39
import org.distorted.library.type.Static3D;
40
import org.distorted.library.type.Static4D;
41
import org.distorted.main.RubikSurfaceView;
42

    
43
import java.util.Random;
44

    
45
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
46

    
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48

    
49
public class TwistySkewb extends TwistyObject
50
{
51
  private static final float SQ2 = (float)Math.sqrt(2);
52
  private static final float SQ3 = (float)Math.sqrt(3);
53

    
54
  private static final int FACES_PER_CUBIT =6;
55

    
56
  // the four rotation axis of a RubikSkewb. Must be normalized.
57
  static final Static3D[] ROT_AXIS = new Static3D[]
58
         {
59
           new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),
60
           new Static3D(+SQ3/3,+SQ3/3,-SQ3/3),
61
           new Static3D(+SQ3/3,-SQ3/3,+SQ3/3),
62
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
63
         };
64

    
65
  // the six axis that determine the faces
66
  static final Static3D[] FACE_AXIS = new Static3D[]
67
         {
68
           new Static3D(1,0,0), new Static3D(-1,0,0),
69
           new Static3D(0,1,0), new Static3D(0,-1,0),
70
           new Static3D(0,0,1), new Static3D(0,0,-1)
71
         };
72

    
73
  private static final int[] FACE_COLORS = new int[]
74
         {
75
           COLOR_YELLOW, COLOR_WHITE,
76
           COLOR_BLUE  , COLOR_GREEN,
77
           COLOR_RED   , COLOR_BROWN
78
         };
79

    
80
  // All legal rotation quats of a RubikSkewb
81
  private static final Static4D[] QUATS = new Static4D[]
82
         {
83
           new Static4D(  0.0f,  0.0f,  0.0f,  1.0f ),
84
           new Static4D(  1.0f,  0.0f,  0.0f,  0.0f ),
85
           new Static4D(  0.0f,  1.0f,  0.0f,  0.0f ),
86
           new Static4D(  0.0f,  0.0f,  1.0f,  0.0f ),
87

    
88
           new Static4D(  0.5f,  0.5f,  0.5f,  0.5f ),
89
           new Static4D(  0.5f,  0.5f,  0.5f, -0.5f ),
90
           new Static4D(  0.5f,  0.5f, -0.5f,  0.5f ),
91
           new Static4D(  0.5f,  0.5f, -0.5f, -0.5f ),
92
           new Static4D(  0.5f, -0.5f,  0.5f,  0.5f ),
93
           new Static4D(  0.5f, -0.5f,  0.5f, -0.5f ),
94
           new Static4D(  0.5f, -0.5f, -0.5f,  0.5f ),
95
           new Static4D(  0.5f, -0.5f, -0.5f, -0.5f )
96
         };
97

    
98
  private static final float DIST_CORNER = 0.50f;
99
  private static final float DIST_CENTER = 0.49f;
100

    
101
  // centers of the 8 corners + 6 sides ( i.e. of the all 14 cubits)
102
  private static final Static3D[] CENTERS = new Static3D[]
103
         {
104
           new Static3D( DIST_CORNER, DIST_CORNER, DIST_CORNER ),
105
           new Static3D( DIST_CORNER, DIST_CORNER,-DIST_CORNER ),
106
           new Static3D( DIST_CORNER,-DIST_CORNER, DIST_CORNER ),
107
           new Static3D( DIST_CORNER,-DIST_CORNER,-DIST_CORNER ),
108
           new Static3D(-DIST_CORNER, DIST_CORNER, DIST_CORNER ),
109
           new Static3D(-DIST_CORNER, DIST_CORNER,-DIST_CORNER ),
110
           new Static3D(-DIST_CORNER,-DIST_CORNER, DIST_CORNER ),
111
           new Static3D(-DIST_CORNER,-DIST_CORNER,-DIST_CORNER ),
112

    
113
           new Static3D( DIST_CENTER,        0.0f,        0.0f ),
114
           new Static3D(-DIST_CENTER,        0.0f,        0.0f ),
115
           new Static3D(        0.0f, DIST_CENTER,        0.0f ),
116
           new Static3D(        0.0f,-DIST_CENTER,        0.0f ),
117
           new Static3D(        0.0f,        0.0f, DIST_CENTER ),
118
           new Static3D(        0.0f,        0.0f,-DIST_CENTER ),
119
         };
120

    
121
  // Colors of the faces of cubits. Each cubit, even the face pyramid, has 6 faces
122
  // (the face has one extra 'fake' face so that everything would have the same number)
123
  private static final int[][] mFaceMap = new int[][]
124
         {
125
           { 4,2,0, 12,12,12 },
126
           { 2,5,0, 12,12,12 },
127
           { 3,4,0, 12,12,12 },
128
           { 5,3,0, 12,12,12 },
129
           { 1,2,4, 12,12,12 },
130
           { 5,2,1, 12,12,12 },
131
           { 4,3,1, 12,12,12 },
132
           { 1,3,5, 12,12,12 },
133

    
134
           { 6 , 12,12,12,12,12 },
135
           { 7 , 12,12,12,12,12 },
136
           { 8 , 12,12,12,12,12 },
137
           { 9 , 12,12,12,12,12 },
138
           { 10, 12,12,12,12,12 },
139
           { 11, 12,12,12,12,12 },
140
         };
141

    
142
  private static MeshBase mCornerMesh, mFaceMesh;
143

    
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

    
146
  TwistySkewb(int size, Static4D quat, DistortedTexture texture,
147
              MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
148
    {
149
    super(size, 60, quat, texture, mesh, effects, moves, ObjectList.SKEW, res, scrWidth);
150
    }
151

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153

    
154
  private void createCornerMesh()
155
    {
156
    float D = 0.02f;
157
    float E = 0.5f;
158
    float F = SQ2/2;
159

    
160
    float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
161

    
162
    float[] bands0 = { 1.0f    , 0,
163
                       1.0f-2*D, D*0.25f,
164
                       1.0f-4*D, D*0.35f,
165
                       1.0f-8*D, D*0.6f,
166
                       0.60f   , D*1.0f,
167
                       0.30f   , D*1.375f,
168
                       0.0f    , D*1.4f };
169

    
170
    MeshBase[] meshes = new MeshBase[FACES_PER_CUBIT];
171

    
172
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
173
    meshes[0].setEffectAssociation(0,1,0);
174
    meshes[1] = meshes[0].copy(true);
175
    meshes[1].setEffectAssociation(0,2,0);
176
    meshes[2] = meshes[0].copy(true);
177
    meshes[2].setEffectAssociation(0,4,0);
178

    
179
    float[] vertices1 = { 0,0, F,0, F/2,(SQ3/2)*F };
180
    float[] bands1 = { 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f };
181

    
182
    meshes[3] = new MeshPolygon(vertices1,bands1,1,5);
183
    meshes[3].setEffectAssociation(0,8,0);
184
    meshes[4] = meshes[3].copy(true);
185
    meshes[4].setEffectAssociation(0,16,0);
186
    meshes[5] = meshes[3].copy(true);
187
    meshes[5].setEffectAssociation(0,32,0);
188

    
189
    mCornerMesh = new MeshJoined(meshes);
190

    
191
    Static3D axisX  = new Static3D(1,0,0);
192
    Static3D axisY  = new Static3D(0,1,0);
193
    Static3D axis0  = new Static3D(-SQ2/2,0,SQ2/2);
194
    Static3D axis1  = new Static3D(+SQ3/3,+SQ3/3,+SQ3/3);
195
    Static1D angle1 = new Static1D(+90);
196
    Static1D angle2 = new Static1D(-90);
197
    Static1D angle3 = new Static1D(-15);
198
    Static1D angle4 = new Static1D((float)((180.0f/Math.PI)*Math.acos(SQ3/3)));
199
    Static1D angle5 = new Static1D(120);
200
    Static1D angle6 = new Static1D(240);
201
    Static3D center1= new Static3D(0,0,0);
202
    Static3D center2= new Static3D(-0.5f,-0.5f,-0.5f);
203
    Static3D move1  = new Static3D(-E/4,-E/4,0);
204
    Static3D move2  = new Static3D(-0.5f,-0.5f,-0.5f);
205

    
206
    float d0 =-0.04f;
207
    float d1 = 0.04f;
208
    float r0 = 0.15f;
209
    float r1 = 0.10f;
210

    
211
    Static3D vec0   = new Static3D(d0*(+SQ3/3),d0*(+SQ3/3),d0*(+SQ3/3));
212
    Static3D vec1   = new Static3D(d1*(+SQ3/3),d1*(-SQ3/3),d1*(-SQ3/3));
213
    Static3D vec2   = new Static3D(d1*(-SQ3/3),d1*(+SQ3/3),d1*(-SQ3/3));
214
    Static3D vec3   = new Static3D(d1*(-SQ3/3),d1*(-SQ3/3),d1*(+SQ3/3));
215

    
216
    Static1D radius = new Static1D(0.5f);
217

    
218
    Static3D cent0  = new Static3D( 0.0f, 0.0f, 0.0f);
219
    Static3D cent1  = new Static3D(-0.5f, 0.0f, 0.0f);
220
    Static3D cent2  = new Static3D( 0.0f,-0.5f, 0.0f);
221
    Static3D cent3  = new Static3D( 0.0f, 0.0f,-0.5f);
222

    
223
    Static4D reg0   = new Static4D(0,0,0,r0);
224
    Static4D reg1   = new Static4D(0,0,0,r1);
225

    
226
    VertexEffectMove   effect0 = new VertexEffectMove(move1);
227
    VertexEffectScale  effect1 = new VertexEffectScale(new Static3D(1,1,-1));
228
    VertexEffectRotate effect2 = new VertexEffectRotate(angle1,axisX,center1);
229
    VertexEffectRotate effect3 = new VertexEffectRotate(angle2,axisY,center1);
230
    VertexEffectMove   effect4 = new VertexEffectMove(move2);
231
    VertexEffectRotate effect5 = new VertexEffectRotate(angle1,axisX,center2);
232
    VertexEffectRotate effect6 = new VertexEffectRotate(angle3,axisY,center2);
233
    VertexEffectRotate effect7 = new VertexEffectRotate(angle4,axis0,center2);
234
    VertexEffectRotate effect8 = new VertexEffectRotate(angle5,axis1,center2);
235
    VertexEffectRotate effect9 = new VertexEffectRotate(angle6,axis1,center2);
236

    
237
    VertexEffectDeform effect10= new VertexEffectDeform(vec0,radius,cent0,reg0);
238
    VertexEffectDeform effect11= new VertexEffectDeform(vec1,radius,cent1,reg1);
239
    VertexEffectDeform effect12= new VertexEffectDeform(vec2,radius,cent2,reg1);
240
    VertexEffectDeform effect13= new VertexEffectDeform(vec3,radius,cent3,reg1);
241

    
242
    effect0.setMeshAssociation( 7,-1);  // meshes 0,1,2
243
    effect1.setMeshAssociation( 6,-1);  // meshes 1,2
244
    effect2.setMeshAssociation( 2,-1);  // mesh 1
245
    effect3.setMeshAssociation( 4,-1);  // mesh 2
246
    effect4.setMeshAssociation(56,-1);  // meshes 3,4,5
247
    effect5.setMeshAssociation(56,-1);  // meshes 3,4,5
248
    effect6.setMeshAssociation(56,-1);  // meshes 3,4,5
249
    effect7.setMeshAssociation(56,-1);  // meshes 3,4,5
250
    effect8.setMeshAssociation(16,-1);  // mesh 4
251
    effect9.setMeshAssociation(32,-1);  // mesh 5
252

    
253
    effect10.setMeshAssociation(63,-1); // all meshes
254
    effect11.setMeshAssociation(63,-1); // all meshes
255
    effect12.setMeshAssociation(63,-1); // all meshes
256
    effect13.setMeshAssociation(63,-1); // all meshes
257

    
258
    mCornerMesh.apply(effect0);
259
    mCornerMesh.apply(effect1);
260
    mCornerMesh.apply(effect2);
261
    mCornerMesh.apply(effect3);
262
    mCornerMesh.apply(effect4);
263
    mCornerMesh.apply(effect5);
264
    mCornerMesh.apply(effect6);
265
    mCornerMesh.apply(effect7);
266
    mCornerMesh.apply(effect8);
267
    mCornerMesh.apply(effect9);
268

    
269
    mCornerMesh.apply(effect10);
270
    mCornerMesh.apply(effect11);
271
    mCornerMesh.apply(effect12);
272
    mCornerMesh.apply(effect13);
273

    
274
    mCornerMesh.mergeEffComponents();
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  private void createFaceMesh()
280
    {
281
    int association = 1;
282

    
283
    float D = 0.03f;
284
    float E = SQ2/4;
285
    float[] vertices0 = { -E,-E, +E,-E, +E,+E, -E,+E };
286

    
287
    float[] bands0 = { 1.0f    , 0,
288
                       1.0f-D/2, D*0.30f,
289
                       1.0f- D , D*0.50f,
290
                       1.0f-2*D, D*0.80f,
291
                       0.60f   , D*1.40f,
292
                       0.30f   , D*1.60f,
293
                       0.0f    , D*1.70f };
294

    
295
    MeshBase[] meshes = new MeshBase[FACES_PER_CUBIT];
296
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
297
    meshes[0].setEffectAssociation(0,association,0);
298

    
299
    association <<= 1;
300

    
301
    float[] vertices1 = { -E,-SQ3*E, +E,-SQ3*E, 0,0 };
302
    float[] bands1 = { 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f };
303

    
304
    meshes[1] = new MeshPolygon(vertices1,bands1,0,0);
305
    meshes[1].setEffectAssociation(0,association,0);
306

    
307
    for(int i=2; i<FACES_PER_CUBIT-1; i++)
308
      {
309
      association <<= 1;
310
      meshes[i] = meshes[1].copy(true);
311
      meshes[i].setEffectAssociation(0,association,0);
312
      }
313

    
314
    association <<= 1;
315
    meshes[FACES_PER_CUBIT-1] = new MeshTriangle(1);                  // empty triangle so that
316
    meshes[FACES_PER_CUBIT-1].setEffectAssociation(0,association,0);  // all cubits have 6 faces
317

    
318
    mFaceMesh = new MeshJoined(meshes);
319

    
320
    Static3D center = new Static3D(0,0,0);
321
    Static3D axis1   = new Static3D(1,0,0);
322
    Static3D axis2   = new Static3D(0,0,1);
323
    float angle = -(float)((180.0f/Math.PI)*Math.acos(SQ3/3));
324

    
325
    float f = 0.05f;
326
    float r = 0.10f;
327
    float d = 0.5f;
328
    float e = +D*0.6f;
329
    Static3D vector0 = new Static3D(-f, 0, 0);
330
    Static3D vector1 = new Static3D( 0,+f, 0);
331
    Static3D vector2 = new Static3D(+f, 0, 0);
332
    Static3D vector3 = new Static3D( 0,-f, 0);
333
    Static1D radius  = new Static1D(1.0f);
334
    Static4D region  = new Static4D(0,0,0,r);
335
    Static3D center0 = new Static3D(+d, 0, e);
336
    Static3D center1 = new Static3D( 0,-d, e);
337
    Static3D center2 = new Static3D(-d, 0, e);
338
    Static3D center3 = new Static3D( 0,+d, e);
339

    
340
    VertexEffectRotate effect0 = new VertexEffectRotate( new Static1D(angle), axis1, center);
341
    VertexEffectRotate effect1 = new VertexEffectRotate( new Static1D(  135), axis2, center);
342
    VertexEffectRotate effect2 = new VertexEffectRotate( new Static1D(   45), axis2, center);
343
    VertexEffectRotate effect3 = new VertexEffectRotate( new Static1D(  -45), axis2, center);
344
    VertexEffectRotate effect4 = new VertexEffectRotate( new Static1D( -135), axis2, center);
345
    VertexEffectMove   effect5 = new VertexEffectMove( new Static3D(0,0,-0.5f) );
346
    VertexEffectDeform effect6 = new VertexEffectDeform(vector0,radius,center0,region);
347
    VertexEffectDeform effect7 = new VertexEffectDeform(vector1,radius,center1,region);
348
    VertexEffectDeform effect8 = new VertexEffectDeform(vector2,radius,center2,region);
349
    VertexEffectDeform effect9 = new VertexEffectDeform(vector3,radius,center3,region);
350
    VertexEffectScale  effect10= new VertexEffectScale(0.01f);
351

    
352
    effect0.setMeshAssociation(30,-1);  // meshes 1,2,3,4
353
    effect1.setMeshAssociation( 2,-1);  // mesh 1
354
    effect2.setMeshAssociation( 5,-1);  // meshes 0,2
355
    effect3.setMeshAssociation( 8,-1);  // mesh 3
356
    effect4.setMeshAssociation(16,-1);  // mesh 4
357
    effect5.setMeshAssociation(30,-1);  // meshes 1,2,3,4
358
    effect6.setMeshAssociation(31,-1);  // meshes 0,1,2,3,4
359
    effect7.setMeshAssociation(31,-1);  // meshes 0,1,2,3,4
360
    effect8.setMeshAssociation(31,-1);  // meshes 0,1,2,3,4
361
    effect9.setMeshAssociation(31,-1);  // meshes 0,1,2,3,4
362
    effect10.setMeshAssociation(32,-1); // mesh 5
363

    
364
    mFaceMesh.apply(effect0);
365
    mFaceMesh.apply(effect1);
366
    mFaceMesh.apply(effect2);
367
    mFaceMesh.apply(effect3);
368
    mFaceMesh.apply(effect4);
369
    mFaceMesh.apply(effect5);
370
    mFaceMesh.apply(effect6);
371
    mFaceMesh.apply(effect7);
372
    mFaceMesh.apply(effect8);
373
    mFaceMesh.apply(effect9);
374
    mFaceMesh.apply(effect10);
375

    
376
    mFaceMesh.mergeEffComponents();
377
    }
378

    
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380

    
381
  float getScreenRatio()
382
    {
383
    return 1.0f;
384
    }
385

    
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387

    
388
  Static4D[] getQuats()
389
    {
390
    return QUATS;
391
    }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

    
395
  int getNumFaces()
396
    {
397
    return FACE_COLORS.length;
398
    }
399

    
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401

    
402
  boolean shouldResetTextureMaps()
403
    {
404
    return false;
405
    }
406

    
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408
// Each face has two types of a texture: the central square and the triangle in the corner.
409

    
410
  int getNumStickerTypes()
411
    {
412
    return 2;
413
    }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
  float getBasicStep()
418
    {
419
    return SQ3;
420
    }
421

    
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423

    
424
  int getNumCubitFaces()
425
    {
426
    return FACES_PER_CUBIT;
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

    
431
  Static3D[] getCubitPositions(int size)
432
    {
433
    return CENTERS;
434
    }
435

    
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437

    
438
  private Static4D getQuat(int cubit)
439
    {
440
    switch(cubit)
441
      {
442
      case  0: return QUATS[0];                          //  unit quat
443
      case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
444
      case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
445
      case  3: return QUATS[1];                          // 180 along X
446
      case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
447
      case  5: return QUATS[2];                          // 180 along Y
448
      case  6: return QUATS[3];                          // 180 along Z
449
      case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
450
      case  8: return new Static4D(0,-SQ2/2,0,SQ2/2);    // -90 along Y
451
      case  9: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
452
      case 10: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
453
      case 11: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
454
      case 12: return QUATS[0];                          //  unit quaternion
455
      case 13: return QUATS[1];                          // 180 along X
456
      }
457

    
458
    return null;
459
    }
460

    
461
///////////////////////////////////////////////////////////////////////////////////////////////////
462

    
463
  MeshBase createCubitMesh(int cubit)
464
    {
465
    MeshBase mesh;
466

    
467
    if( cubit<8 )
468
      {
469
      if( mCornerMesh==null ) createCornerMesh();
470
      mesh = mCornerMesh.copy(true);
471
      }
472
    else
473
      {
474
      if( mFaceMesh==null ) createFaceMesh();
475
      mesh = mFaceMesh.copy(true);
476
      }
477

    
478
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
479
    mesh.apply(quat,0xffffffff,0);
480

    
481
    return mesh;
482
    }
483

    
484
///////////////////////////////////////////////////////////////////////////////////////////////////
485

    
486
  int getFaceColor(int cubit, int cubitface, int size)
487
    {
488
    return mFaceMap[cubit][cubitface];
489
    }
490

    
491
///////////////////////////////////////////////////////////////////////////////////////////////////
492

    
493
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side)
494
    {
495
    int COLORS = FACE_COLORS.length;
496

    
497
    if( face<COLORS )
498
      {
499
      float STROKE = 0.035f*side;
500
      float L= left+0.125f*side;
501
      float H= 0.375f*side;
502
      float LEN = 0.5f*side;
503

    
504
      paint.setAntiAlias(true);
505
      paint.setStrokeWidth(STROKE);
506
      paint.setColor(FACE_COLORS[face]);
507
      paint.setStyle(Paint.Style.FILL);
508

    
509
      canvas.drawRect(left,top,left+side,top+side,paint);
510

    
511
      paint.setColor(INTERIOR_COLOR);
512
      paint.setStyle(Paint.Style.STROKE);
513

    
514
      canvas.drawLine( L    , H,  L+LEN, H    , paint);
515
      canvas.drawLine( L    , H,  L+LEN, H+LEN, paint);
516
      canvas.drawLine( L+LEN, H,  L+LEN, H+LEN, paint);
517

    
518
      float S1 = 0.125f*side;
519
      float S2 = 0.070f*side;
520
      float X  = 0.7f*S2;
521

    
522
      float LA = left+0.625f*side;
523
      float RA = left+0.125f*side;
524
      float TA = 0.375f*side;
525
      float BA = 0.875f*side;
526

    
527
      canvas.drawArc( LA-S1, TA     , LA     , TA+S1, 270, 90, false, paint);
528
      canvas.drawArc( RA+X , TA     , RA+X+S2, TA+S2, 135,135, false, paint);
529
      canvas.drawArc( LA-S2, BA-X-S2, LA     , BA-X ,   0,135, false, paint);
530
      }
531
    else
532
      {
533
      final float R = (SQ2/2)*side*0.10f;
534
      final float M = side*(0.5f-SQ2/4+0.018f);
535

    
536
      paint.setColor(FACE_COLORS[face-COLORS]);
537
      paint.setStyle(Paint.Style.FILL);
538
      canvas.drawRoundRect( left+M, top+M, left+side-M, top+side-M, R, R, paint);
539
      }
540
    }
541

    
542
///////////////////////////////////////////////////////////////////////////////////////////////////
543

    
544
  float returnMultiplier()
545
    {
546
    return 2.0f;
547
    }
548

    
549
///////////////////////////////////////////////////////////////////////////////////////////////////
550

    
551
  float[] getRowChances()
552
    {
553
    float[] chances = new float[2];
554

    
555
    chances[0] = 0.5f;
556
    chances[1] = 1.0f;
557

    
558
    return chances;
559
    }
560

    
561
///////////////////////////////////////////////////////////////////////////////////////////////////
562
// PUBLIC API
563

    
564
  public Static3D[] getRotationAxis()
565
    {
566
    return ROT_AXIS;
567
    }
568

    
569
///////////////////////////////////////////////////////////////////////////////////////////////////
570

    
571
  public int getBasicAngle()
572
    {
573
    return 3;
574
    }
575

    
576
///////////////////////////////////////////////////////////////////////////////////////////////////
577

    
578
  public int computeRowFromOffset(float offset)
579
    {
580
    return offset<0.25f ? 0:1;
581
    }
582

    
583
///////////////////////////////////////////////////////////////////////////////////////////////////
584

    
585
  public float returnRotationFactor(float offset)
586
    {
587
    return 1.0f;
588
    }
589

    
590
///////////////////////////////////////////////////////////////////////////////////////////////////
591

    
592
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
593
    {
594
    int numAxis = ROTATION_AXIS.length;
595

    
596
    if( oldRotAxis == START_AXIS )
597
      {
598
      return rnd.nextInt(numAxis);
599
      }
600
    else
601
      {
602
      int newVector = rnd.nextInt(numAxis-1);
603
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
604
      }
605
    }
606

    
607
///////////////////////////////////////////////////////////////////////////////////////////////////
608

    
609
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
610
    {
611
    float rowFloat = rnd.nextFloat();
612

    
613
    for(int row=0; row<mRowChances.length; row++)
614
      {
615
      if( rowFloat<=mRowChances[row] ) return row;
616
      }
617

    
618
    return 0;
619
    }
620

    
621
///////////////////////////////////////////////////////////////////////////////////////////////////
622
// remember about the double cover or unit quaternions!
623

    
624
  private int mulQuat(int q1, int q2)
625
    {
626
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
627

    
628
    float rX = result.get0();
629
    float rY = result.get1();
630
    float rZ = result.get2();
631
    float rW = result.get3();
632

    
633
    final float MAX_ERROR = 0.1f;
634
    float dX,dY,dZ,dW;
635

    
636
    for(int i=0; i<QUATS.length; i++)
637
      {
638
      dX = QUATS[i].get0() - rX;
639
      dY = QUATS[i].get1() - rY;
640
      dZ = QUATS[i].get2() - rZ;
641
      dW = QUATS[i].get3() - rW;
642

    
643
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
644
          dY<MAX_ERROR && dY>-MAX_ERROR &&
645
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
646
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
647

    
648
      dX = QUATS[i].get0() + rX;
649
      dY = QUATS[i].get1() + rY;
650
      dZ = QUATS[i].get2() + rZ;
651
      dW = QUATS[i].get3() + rW;
652

    
653
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
654
          dY<MAX_ERROR && dY>-MAX_ERROR &&
655
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
656
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
657
      }
658

    
659
    return -1;
660
    }
661

    
662
///////////////////////////////////////////////////////////////////////////////////////////////////
663
// The Skewb is solved if and only if:
664
//
665
// 1) all of its corner cubits are rotated with the same quat
666
// 2) all its face cubits are rotated with the same quat like the corner ones,
667
//    and optionally they also might be upside down.
668
//
669
// i.e.
670
// cubits [ 8] and [ 9] - might be extra QUAT[1]
671
// cubits [10] and [11] - might be extra QUAT[2]
672
// cubits [12] and [13] - might be extra QUAT[3]
673

    
674
  public boolean isSolved()
675
    {
676
    int q = CUBITS[0].mQuatIndex;
677

    
678
    if ( CUBITS[1].mQuatIndex == q &&
679
         CUBITS[2].mQuatIndex == q &&
680
         CUBITS[3].mQuatIndex == q &&
681
         CUBITS[4].mQuatIndex == q &&
682
         CUBITS[5].mQuatIndex == q &&
683
         CUBITS[6].mQuatIndex == q &&
684
         CUBITS[7].mQuatIndex == q  )
685
      {
686
      int q1 = mulQuat(q,1);
687
      int q2 = mulQuat(q,2);
688
      int q3 = mulQuat(q,3);
689

    
690
      return (CUBITS[ 8].mQuatIndex == q || CUBITS[ 8].mQuatIndex == q1) &&
691
             (CUBITS[ 9].mQuatIndex == q || CUBITS[ 9].mQuatIndex == q1) &&
692
             (CUBITS[10].mQuatIndex == q || CUBITS[10].mQuatIndex == q2) &&
693
             (CUBITS[11].mQuatIndex == q || CUBITS[11].mQuatIndex == q2) &&
694
             (CUBITS[12].mQuatIndex == q || CUBITS[12].mQuatIndex == q3) &&
695
             (CUBITS[13].mQuatIndex == q || CUBITS[13].mQuatIndex == q3)  ;
696
      }
697

    
698
    return false;
699
    }
700

    
701
///////////////////////////////////////////////////////////////////////////////////////////////////
702
// only needed for solvers - there are no Skewb solvers ATM)
703

    
704
  public String retObjectString()
705
    {
706
    return "";
707
    }
708

    
709
}
(18-18/18)