Project

General

Profile

« Previous | Next » 

Revision 7ff38997

Added by Leszek Koltunski about 3 years ago

Remove statics from the Cube classes.

View differences:

src/main/java/org/distorted/helpers/ScrambleStateSquare1.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 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.helpers;
21

  
22
import java.util.ArrayList;
23
import java.util.Random;
24

  
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
// producer of the ScrambleStateGraph - but only for a single Twisty Puzzle, the 'Square-1'.
27

  
28
public class ScrambleStateSquare1
29
{
30
  private static final int INVALID_MOVE = -1;
31
  private static final int NUM_MOVES = 23;
32

  
33
  private int mDist;
34
  private boolean mFresh;
35
  private long mID;
36
  private final long[] mMoves;
37

  
38
  private final int[][] mPermittedAngles;
39
  private final int[] mCornerQuat, mTmp;
40

  
41
  // QUATS[i]*QUATS[j] = QUATS[QUAT_MULT[i][j]]
42
  static final int[][] QUAT_MULT = new int[][]
43
    {
44
      {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,},
45
      {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12,},
46
      {  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13,},
47
      {  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14,},
48
      {  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15,},
49
      {  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16,},
50
      {  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17,},
51
      {  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18,},
52
      {  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19,},
53
      {  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20,},
54
      { 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,},
55
      { 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,},
56
      { 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,},
57
      { 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,},
58
      { 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,},
59
      { 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,},
60
      { 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,},
61
      { 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,},
62
      { 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,},
63
      { 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,},
64
      { 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,},
65
      { 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,},
66
      { 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11,},
67
      { 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0,}
68
    };
69

  
70
  // quat indices that make corner cubits bandage the puzzle.
71
  private static final int[][] BAD_CORNER_QUATS = new int[][]
72
    {
73
      { 2, 8,17,23},
74
      { 5,11,14,20},
75
    };
76

  
77
///////////////////////////////////////////////////////////////////////////////////////////////////
78

  
79
  public ScrambleStateSquare1(long id, int dist)
80
    {
81
    mCornerQuat = new int[8];
82
    mTmp        = new int[8];
83
    mPermittedAngles = new int[2][12];
84

  
85
    mDist = dist;
86
    mFresh = true;
87
    mID = id;
88
    mMoves = createMoves(mID);
89
    }
90

  
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

  
93
  private void setNotFresh()
94
    {
95
    mFresh = false;
96
    }
97

  
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99

  
100
  private boolean isFresh()
101
    {
102
    return mFresh;
103
    }
104

  
105
///////////////////////////////////////////////////////////////////////////////////////////////////
106

  
107
  public static void computeGraph()
108
    {
109
    ArrayList<ScrambleStateSquare1> graph;
110

  
111
    ScrambleStateSquare1 bsg = new ScrambleStateSquare1(0,0);
112
    graph = new ArrayList<>();
113
    graph.add(bsg);
114

  
115
android.util.Log.e("D", "INSERTING");
116

  
117
    insertChildren(graph,0);
118

  
119
//android.util.Log.e("D", "PRUNING "+graph.size());
120

  
121
//    pruneGraph(graph);
122

  
123
android.util.Log.e("D", "REMAPPING "+graph.size());
124

  
125
    remapGraph(graph);
126

  
127
    int num = graph.size();
128
    android.util.Log.e("D", "\n"+num+" states\n");
129

  
130
    for(int i=0; i<num; i++)
131
      {
132
      bsg = graph.get(i);
133
      android.util.Log.e("D", formatMoves(bsg));
134
      }
135
    }
136

  
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

  
139
  private static void insertChildren(ArrayList<ScrambleStateSquare1> list, long id)
140
    {
141
    ScrambleStateSquare1 bsg = findState(list,id);
142

  
143
    if( bsg==null )
144
      {
145
      android.util.Log.e("D", "error: "+id+" doesn't exist");
146
      return;
147
      }
148

  
149
    int dist = bsg.mDist;
150
    if( dist>6 ) return;
151

  
152
    for(int i=0; i<NUM_MOVES; i++)
153
      {
154
      long moveID = bsg.getMoveID(i);
155

  
156
      if( moveID!=INVALID_MOVE )
157
        {
158
        ScrambleStateSquare1 tmp = findState(list,moveID);
159

  
160
        if( tmp==null )
161
          {
162
          tmp = new ScrambleStateSquare1(moveID,dist+1);
163
          list.add(tmp);
164
          }
165
        }
166
      }
167

  
168
    for(int i=0; i<NUM_MOVES; i++)
169
      {
170
      long moveID = bsg.getMoveID(i);
171

  
172
      if( moveID!=INVALID_MOVE )
173
        {
174
        ScrambleStateSquare1 tmp = findState(list,moveID);
175

  
176
        if( tmp.isFresh() )
177
          {
178
          tmp.setNotFresh();
179
          insertChildren(list,moveID);
180
          }
181
        }
182
      }
183
    }
184

  
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

  
187
  private static void pruneGraph(ArrayList<ScrambleStateSquare1> list)
188
    {
189
    int num = list.size(), numAxis;
190
    boolean pruned = false;
191
    ScrambleStateSquare1 bsg;
192

  
193
    for(int i=0; i<num; i++)
194
      {
195
      bsg = list.get(i);
196
      numAxis = bsg.numAxis();
197

  
198
      if( numAxis<2 )
199
        {
200
        list.remove(i);
201
        long id = bsg.getID();
202
        pruned = true;
203
        remapID(list,id,INVALID_MOVE);
204
        break;
205
        }
206
      }
207

  
208
    if( pruned ) pruneGraph(list);
209
    }
210

  
211
///////////////////////////////////////////////////////////////////////////////////////////////////
212

  
213
  private static void remapGraph(ArrayList<ScrambleStateSquare1> list)
214
    {
215
    long id;
216
    int num = list.size();
217
    ScrambleStateSquare1 bsg;
218

  
219
    for(int i=0; i<num; i++ )
220
      {
221
      bsg = list.get(i);
222
      id = bsg.getID();
223
      bsg.setID(i);
224
      remapID(list,id,i);
225
      }
226
    }
227

  
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

  
230
  private static void remapID(ArrayList<ScrambleStateSquare1> list, long id, long newId)
231
    {
232
    ScrambleStateSquare1 bsg;
233
    int size = list.size();
234

  
235
    for(int i=0; i<size; i++)
236
      {
237
      bsg = list.get(i);
238

  
239
      for(int j=0; j<NUM_MOVES; j++)
240
        {
241
        if( bsg.getMoveID(j)==id ) bsg.setMoveID(j,newId);
242
        }
243
      }
244
    }
245

  
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247

  
248
  private static ScrambleStateSquare1 findState(ArrayList<ScrambleStateSquare1> list, long id)
249
    {
250
    ScrambleStateSquare1 bsg;
251
    int num = list.size();
252

  
253
    for(int i=0; i<num; i++)
254
      {
255
      bsg= list.get(i);
256
      if( bsg.getID() == id ) return bsg;
257
      }
258

  
259
    return null;
260
    }
261

  
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263

  
264
  private static String formatMoves(ScrambleStateSquare1 bsg)
265
    {
266
    String x = getTable(bsg,0);
267
    String y = getTable(bsg,11);
268
    String z = getTable(bsg,12);
269

  
270
    //return "    new ScrambleStateGraph( new int[][] { "+x+", "+y+", "+z+" } ),";
271

  
272
    long id = bsg.getID();
273

  
274
    return id+" "+x+" , "+y+" , "+z;
275
    }
276

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

  
279
  private static String getTable(ScrambleStateSquare1 sc, int index)
280
    {
281
    String ret = "";
282
    long m;
283
    int half = (NUM_MOVES)/2;
284

  
285
    if( index==11 )
286
      {
287
      m = sc.getMoveID(index);
288
      if( m==INVALID_MOVE ) return formatL("{}");
289
      ret += formatRet(ret,0,1,m);
290
      }
291
    else
292
      {
293
      for(int i=0; i<half; i++)
294
        {
295
        m = sc.getMoveID(index+i);
296
        int row = index==0 ? 0:2;
297
        int angle = i+1;
298
        if( m!=INVALID_MOVE ) ret += formatRet(ret,row,angle,m);
299
        }
300
      }
301

  
302
    return formatL("{" + ret + "}");
303
    }
304

  
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306

  
307
  private static String formatRet(String str, int row, int angle, long id)
308
    {
309
    String ret = str.length()!=0 ? "  ,":"  ";
310

  
311
    ret += row;
312
    ret += angle<0 ? "," : ",";
313
    ret += angle;
314

  
315
         if( id< 10 ) ret += (",  "+id);
316
    else if( id<100 ) ret += (", " +id);
317
    else              ret += (","  +id);
318

  
319
    return ret;
320
    }
321

  
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

  
324
  private static final int LENGTH = 28;
325

  
326
  private static String formatL(String input)
327
    {
328
    int len = input.length();
329
    String ret = input;
330
    for(int i=0 ;i<LENGTH-len; i++) ret += " ";
331
    return ret;
332
    }
333

  
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335

  
336
  private long getID()
337
    {
338
    return mID;
339
    }
340

  
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342

  
343
  private void setID(long id)
344
    {
345
    mID = id;
346
    }
347

  
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

  
350
  private long getMoveID(int index)
351
    {
352
    return (index>=0 && index<NUM_MOVES) ? mMoves[index] : -1;
353
    }
354

  
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

  
357
  private void setMoveID(int index, long newID)
358
    {
359
    if( index>=0 && index<NUM_MOVES ) mMoves[index] = newID;
360
    }
361

  
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

  
364
  private int numAxis()
365
    {
366
    int num = 0;
367
    int half = (NUM_MOVES)/2;
368

  
369
    for(int i=0; i<half; i++)
370
      {
371
      if( mMoves[i]!=INVALID_MOVE )
372
        {
373
        num++;
374
        break;
375
        }
376
      }
377

  
378
    for(int i=half; i<NUM_MOVES-1; i++)
379
      {
380
      if( mMoves[i]!=INVALID_MOVE )
381
        {
382
        num++;
383
        break;
384
        }
385
      }
386

  
387
    if( mMoves[NUM_MOVES-1]!=INVALID_MOVE ) num++;
388

  
389
    return num;
390
    }
391

  
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393

  
394
  private long[] createMoves(long id)
395
    {
396
    long[] ret = new long[NUM_MOVES];
397
    fillCornerQuat(id);
398
    computePermittedAngles();
399

  
400
    generateUMoves(ret, 0);
401
    generateSMoves(ret,11);
402
    generateLMoves(ret,12);
403

  
404
    return ret;
405
    }
406

  
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408

  
409
  private void generateUMoves(long[] table, int index)
410
    {
411
    for(int angle=1; angle<12; angle++)
412
      {
413
      table[index+angle-1] = mPermittedAngles[1][angle]==1 ? updateCornerQuats(0,2,angle) : INVALID_MOVE;
414
      }
415
    }
416

  
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418

  
419
  private void generateLMoves(long[] table, int index)
420
    {
421
    for(int angle=1; angle<12; angle++)
422
      {
423
      table[index+angle-1] = mPermittedAngles[0][angle]==1 ? updateCornerQuats(0,0,angle) : INVALID_MOVE;
424
      }
425
    }
426

  
427
///////////////////////////////////////////////////////////////////////////////////////////////////
428

  
429
  private void generateSMoves(long[] table, int index)
430
    {
431
    table[index] = updateCornerQuats(1,1,1);
432
    }
433

  
434
///////////////////////////////////////////////////////////////////////////////////////////////////
435

  
436
  private void fillCornerQuat(long id)
437
    {
438
    int NUM_QUATS = 24;
439

  
440
    for(int i=0; i<8; i++)
441
      {
442
      mCornerQuat[i] = (int)(id%NUM_QUATS);
443
      id/=NUM_QUATS;
444
      }
445
    }
446

  
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448

  
449
  private static long returnID(int[] cornerQuat)
450
    {
451
    int NUM_QUATS = 24;
452
    long mult=1,ret=0;
453

  
454
    for(int i=0; i<8; i++)
455
      {
456
      ret += mult*cornerQuat[i];
457
      mult*=NUM_QUATS;
458
      }
459

  
460
    return ret;
461
    }
462

  
463
///////////////////////////////////////////////////////////////////////////////////////////////////
464

  
465
  private boolean cornerIsUp(int index)
466
    {
467
    return ((index<4) ^ (mCornerQuat[index]>=12));
468
    }
469

  
470
///////////////////////////////////////////////////////////////////////////////////////////////////
471

  
472
  private boolean cornerIsLeft(int index)
473
    {
474
    int q = mCornerQuat[index];
475

  
476
    switch(index)
477
      {
478
      case 0:
479
      case 4: return ((q>=3 && q<= 7) || (q>=18 && q<=22));
480
      case 1:
481
      case 5: return ((q>=6 && q<=10) || (q>=15 && q<=19));
482
      case 2:
483
      case 6: return ((q==0 || q==1 || (q>=9 && q<=11)) || (q>=12 && q<=16));
484
      case 3:
485
      case 7: return ((q>=0 && q<=4) || (q==12 || q==13 || (q>=21 && q<=23)));
486
      }
487

  
488
    return false;
489
    }
490

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

  
493
  private int makeQuat(int axis,int index)
494
    {
495
    if( axis==1 ) return 13;
496
    if( index<0 ) index+=12;
497
    return index;
498
    }
499

  
500
///////////////////////////////////////////////////////////////////////////////////////////////////
501

  
502
  private boolean cornerBelongs(int index, int axis, int layer)
503
    {
504
    if( axis==0 )
505
      {
506
      boolean up = cornerIsUp(index);
507
      return ((up && layer==2) || (!up && layer==0));
508
      }
509
    else
510
      {
511
      boolean le = cornerIsLeft(index);
512
      return ((le && layer==0) || (!le && layer==1));
513
      }
514
    }
515

  
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517

  
518
  private long updateCornerQuats(int axis, int layer, int index)
519
    {
520
    int quat = makeQuat(axis,index);
521

  
522
    for(int corner=0; corner<8; corner++)
523
      {
524
      if( cornerBelongs(corner,axis,layer) )
525
        {
526
        int curr = mCornerQuat[corner];
527
        mTmp[corner] = QUAT_MULT[quat][curr];
528
        }
529
      else
530
        {
531
        mTmp[corner] = mCornerQuat[corner];
532
        }
533
      }
534

  
535
    return returnID(mTmp);
536
    }
537

  
538
///////////////////////////////////////////////////////////////////////////////////////////////////
539

  
540
  private boolean quatIsBad(int quatIndex, int corner)
541
    {
542
    int index = (corner%2);
543

  
544
    return ( quatIndex==BAD_CORNER_QUATS[index][0] ||
545
             quatIndex==BAD_CORNER_QUATS[index][1] ||
546
             quatIndex==BAD_CORNER_QUATS[index][2] ||
547
             quatIndex==BAD_CORNER_QUATS[index][3]  );
548
    }
549

  
550
///////////////////////////////////////////////////////////////////////////////////////////////////
551

  
552
  private int isPermittedDo(int angle)
553
    {
554
    for(int corner=0; corner<8; corner++)
555
      {
556
      if( !cornerIsUp(corner) )
557
        {
558
        int currQuat = mCornerQuat[corner];
559
        int finalQuat= QUAT_MULT[angle][currQuat];
560
        if( quatIsBad(finalQuat,corner) ) return 0;
561
        }
562
      }
563

  
564
    return 1;
565
    }
566

  
567
///////////////////////////////////////////////////////////////////////////////////////////////////
568

  
569
  private int isPermittedUp(int angle)
570
    {
571
    for(int corner=0; corner<8; corner++)
572
      {
573
      if( cornerIsUp(corner) )
574
        {
575
        int currQuat = mCornerQuat[corner];
576
        int finalQuat= QUAT_MULT[angle][currQuat];
577
        if( quatIsBad(finalQuat,corner) ) return 0;
578
        }
579
      }
580

  
581
    return 1;
582
    }
583

  
584
///////////////////////////////////////////////////////////////////////////////////////////////////
585

  
586
  private void computePermittedAngles()
587
    {
588
    for(int angle=0; angle<12; angle++)
589
      {
590
      mPermittedAngles[0][angle] = isPermittedDo(angle);
591
      mPermittedAngles[1][angle] = isPermittedUp(angle);
592
      }
593
    }
594
}
src/main/java/org/distorted/objects/Cubit.java
76 76
    float xd,yd,zd,wd;
77 77
    float diff, mindiff = Float.MAX_VALUE;
78 78
    int ret=0;
79
    int num_quats = mParent.QUATS.length;
79
    int num_quats = mParent.OBJECT_QUATS.length;
80 80
    Static4D qt;
81 81

  
82 82
    for(int q=0; q<num_quats; q++)
83 83
      {
84
      qt = mParent.QUATS[q];
84
      qt = mParent.OBJECT_QUATS[q];
85 85

  
86 86
      xd = x - qt.get0();
87 87
      yd = y - qt.get1();
......
189 189

  
190 190
  int removeRotationNow(Static4D quat)
191 191
    {
192
    Static4D q = QuatHelper.quatMultiply(quat,mParent.QUATS[mQuatIndex]);
192
    Static4D q = QuatHelper.quatMultiply(quat,mParent.OBJECT_QUATS[mQuatIndex]);
193 193
    mQuatIndex = normalizeScrambleQuat(q);
194 194

  
195 195
    modifyCurrentPosition(quat);
src/main/java/org/distorted/objects/TwistyCube.java
37 37

  
38 38
class TwistyCube extends TwistyObject
39 39
{
40
  // the three rotation axis of a RubikCube. Must be normalized.
41 40
  static final Static3D[] ROT_AXIS = new Static3D[]
42 41
         {
43 42
           new Static3D(1,0,0),
......
45 44
           new Static3D(0,0,1)
46 45
         };
47 46

  
48
  private static final int[] BASIC_ANGLE = new int[] { 4,4,4 };
49

  
50 47
  private static final int[] FACE_COLORS = new int[]
51 48
         {
52 49
           COLOR_YELLOW, COLOR_WHITE,
......
54 51
           COLOR_RED   , COLOR_ORANGE
55 52
         };
56 53

  
57
  // All legal rotation quats of a RubikCube of any size.
58
  // Here's how to compute this:
59
  // 1) compute how many rotations there are (RubikCube of any size = 24)
60
  // 2) take the AXIS, angles of rotation (90 in RubikCube's case) compute the basic quaternions
61
  // (i.e. rotations of 1 basic angle along each of the axis) and from there start semi-randomly
62
  // multiplying them and eventually you'll find all (24) legal rotations.
63
  // Example program in C, res/raw/compute_quats.c , is included.
64
  private static final Static4D[] QUATS = new Static4D[]
65
         {
66
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
67
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
68
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
69
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
70

  
71
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
72
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
73
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
74
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
75
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
76
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
77
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
78
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
79
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
80
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
81
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
82
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
83

  
84
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
85
         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
86
         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
87
         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
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
         };
93

  
94
  private static final double[][] VERTICES = new double[][]
95
          {
96
              { 0.5, 0.5, 0.5 },
97
              { 0.5, 0.5,-0.5 },
98
              { 0.5,-0.5, 0.5 },
99
              { 0.5,-0.5,-0.5 },
100
              {-0.5, 0.5, 0.5 },
101
              {-0.5, 0.5,-0.5 },
102
              {-0.5,-0.5, 0.5 },
103
              {-0.5,-0.5,-0.5 },
104
          };
105

  
106
  private static final int[][] VERT_INDEXES = new int[][]
107
          {
108
              {2,3,1,0},   // counterclockwise!
109
              {7,6,4,5},
110
              {4,0,1,5},
111
              {7,3,2,6},
112
              {6,2,0,4},
113
              {3,7,5,1}
114
          };
115

  
116
  private static final float[][] STICKERS = new float[][]
117
          {
118
              { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f }
119
          };
120

  
121
  private static final ObjectSticker[] mStickers;
122

  
123
  static
124
    {
125
    final float radius = 0.10f;
126
    final float stroke = 0.08f;
127
    final float[] radii = {radius,radius,radius,radius};
128
    mStickers = new ObjectSticker[STICKERS.length];
129
    mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke );
130
    }
131

  
132 54
  private int mCurrState;
133 55
  private int mIndexExcluded;
134 56
  private final ScrambleState[] mStates;
135 57
  private int[][] mScrambleTable;
136 58
  private int[] mNumOccurences;
59
  private Static4D[] mQuats;
60
  private int[] mBasicAngle;
61
  private ObjectSticker[] mStickers;
137 62

  
138 63
///////////////////////////////////////////////////////////////////////////////////////////////////
139 64

  
......
188 113
    return ret;
189 114
    }
190 115

  
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117

  
118
  private void initializeQuats()
119
    {
120
    mQuats = new Static4D[]
121
         {
122
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
123
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
124
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
125
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
126

  
127
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
128
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
129
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
130
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
131
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
132
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
133
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
134
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
135
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
136
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
137
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
138
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
139

  
140
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
141
         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
142
         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
143
         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
144
         new Static4D( -0.5f,  -0.5f,  -0.5f,   0.5f),
145
         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
146
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
147
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
148
         };
149
    }
150

  
191 151
///////////////////////////////////////////////////////////////////////////////////////////////////
192 152

  
193 153
  int[] getSolvedQuats(int cubit, int numLayers)
194 154
    {
155
    if( mQuats ==null ) initializeQuats();
195 156
    int status = retCubitSolvedStatus(cubit,numLayers);
196
    return status<0 ? null : buildSolvedQuats(MovementCube.FACE_AXIS[status],QUATS);
157
    return status<0 ? null : buildSolvedQuats(MovementCube.FACE_AXIS[status], mQuats);
197 158
    }
198 159

  
199 160
///////////////////////////////////////////////////////////////////////////////////////////////////
......
211 172
      default: num = 5; extraI = 0; extraV = 0; height = 0.045f; break;
212 173
      }
213 174

  
175
    double[][] vertices = new double[][]
176
          {
177
              { 0.5, 0.5, 0.5 },
178
              { 0.5, 0.5,-0.5 },
179
              { 0.5,-0.5, 0.5 },
180
              { 0.5,-0.5,-0.5 },
181
              {-0.5, 0.5, 0.5 },
182
              {-0.5, 0.5,-0.5 },
183
              {-0.5,-0.5, 0.5 },
184
              {-0.5,-0.5,-0.5 },
185
          };
186

  
187
    int[][] vert_indices = new int[][]
188
          {
189
              {2,3,1,0},   // counterclockwise!
190
              {7,6,4,5},
191
              {4,0,1,5},
192
              {7,3,2,6},
193
              {6,2,0,4},
194
              {3,7,5,1}
195
          };
196

  
214 197
    float[][] bands     = new float[][] { {height,35,0.5f,0.7f,num,extraI,extraV} };
215 198
    int[] bandIndices   = new int[] { 0,0,0,0,0,0};
216 199
    float[][] corners   = new float[][] { {0.036f,0.12f} };
......
218 201
    float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
219 202
    int[] centerIndices = new int[] { 0,0,0,0,0,0,0,0 };
220 203

  
221
    return new ObjectShape(VERTICES,VERT_INDEXES,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
204
    return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
222 205
    }
223 206

  
224 207
///////////////////////////////////////////////////////////////////////////////////////////////////
225 208

  
226 209
  Static4D getQuat(int cubit, int numLayers)
227 210
    {
228
    return QUATS[0];
211
    if( mQuats ==null ) initializeQuats();
212
    return mQuats[0];
229 213
    }
230 214

  
231 215
///////////////////////////////////////////////////////////////////////////////////////////////////
......
253 237

  
254 238
  ObjectSticker retSticker(int face)
255 239
    {
240
    if( mStickers==null )
241
      {
242
      final float[][] STICKERS = new float[][]  { { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f } };
243
      final float radius = 0.10f;
244
      final float stroke = 0.08f;
245
      final float[] radii = {radius,radius,radius,radius};
246
      mStickers = new ObjectSticker[STICKERS.length];
247
      mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke );
248
      }
249

  
256 250
    return mStickers[face/NUM_FACES];
257 251
    }
258 252

  
......
281 275

  
282 276
  Static4D[] getQuats()
283 277
    {
284
    return QUATS;
278
    if( mQuats ==null ) initializeQuats();
279
    return mQuats;
285 280
    }
286 281

  
287 282
///////////////////////////////////////////////////////////////////////////////////////////////////
......
326 321

  
327 322
  int getNumStickerTypes(int numLayers)
328 323
    {
329
    return STICKERS.length;
324
    return 1;
330 325
    }
331 326

  
332 327
///////////////////////////////////////////////////////////////////////////////////////////////////
......
369 364

  
370 365
  public int[] getBasicAngle()
371 366
    {
372
    return BASIC_ANGLE;
367
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
368
    return mBasicAngle;
373 369
    }
374 370

  
375 371
///////////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/objects/TwistyObject.java
88 88
  private static final int POST_ROTATION_MILLISEC = 500;
89 89

  
90 90
  MeshBase[] mMeshes;
91
  final Static4D[] QUATS;
91
  final Static4D[] OBJECT_QUATS;
92 92
  final Cubit[] CUBITS;
93 93
  final int NUM_FACES;
94 94
  final int NUM_TEXTURES;
95 95
  final int NUM_CUBITS;
96 96
  final int NUM_AXIS;
97
  final int NUM_QUATS;
97 98

  
98 99
  private final int mNumCubitFaces;
99 100
  private final Static3D[] mAxis;
......
158 159
    if( mCuts==null ) for(int i=0; i<mAxis.length; i++) mNumCuts[i] = 0;
159 160
    else              for(int i=0; i<mAxis.length; i++) mNumCuts[i] = mCuts[i].length;
160 161

  
161
    QUATS = getQuats();
162
    OBJECT_QUATS = getQuats();
162 163
    NUM_CUBITS  = mOrigPos.length;
163 164
    NUM_FACES = getNumFaces();
164 165
    NUM_TEXTURES = getNumStickerTypes(mNumLayers)*NUM_FACES;
165 166
    NUM_AXIS = mAxis.length;
167
    NUM_QUATS = OBJECT_QUATS.length;
166 168

  
167 169
    boolean bandaged=false;
168 170

  
......
213 215
    mTexture = new DistortedTexture();
214 216
    mEffects = new DistortedEffects();
215 217

  
216
    int num_quats = QUATS.length;
217
    for(int q=0; q<num_quats; q++)
218
    for(int q=0; q<NUM_QUATS; q++)
218 219
      {
219
      VertexEffectQuaternion vq = new VertexEffectQuaternion(QUATS[q],CENTER);
220
      VertexEffectQuaternion vq = new VertexEffectQuaternion(OBJECT_QUATS[q],CENTER);
220 221
      vq.setMeshAssociation(0,q);
221 222
      mEffects.apply(vq);
222 223
      }
......
343 344

  
344 345
  private void createDataStructuresForSolved(int numLayers)
345 346
    {
346
    mTmpQuats = new int[QUATS.length];
347
    mTmpQuats = new int[NUM_QUATS];
347 348
    mSolvedQuats = new int[NUM_CUBITS][];
348 349

  
349 350
    for(int c=0; c<NUM_CUBITS; c++)
......
432 433
    {
433 434
    if( mQuatMult==null )
434 435
      {
435
      int len = QUATS.length;
436
      mQuatMult = new int[len][len];
436
      mQuatMult = new int[NUM_QUATS][NUM_QUATS];
437 437

  
438
      for(int i=0; i<len; i++)
439
        for(int j=0; j<len; j++) mQuatMult[i][j] = -1;
438
      for(int i=0; i<NUM_QUATS; i++)
439
        for(int j=0; j<NUM_QUATS; j++) mQuatMult[i][j] = -1;
440 440
      }
441 441

  
442 442
    if( mQuatMult[index1][index2]==-1 )
......
499 499
    float MAXDIFF = 0.01f;
500 500
    float[] center= mOrigPos[centerNum];
501 501
    Static4D sc = new Static4D(center[0], center[1], center[2], 1.0f);
502
    Static4D result = QuatHelper.rotateVectorByQuat(sc,QUATS[quatNum]);
502
    Static4D result = QuatHelper.rotateVectorByQuat(sc,OBJECT_QUATS[quatNum]);
503 503

  
504 504
    float x = result.get0();
505 505
    float y = result.get1();
......
532 532
    {
533 533
    if( mScramble==null )
534 534
      {
535
      int numQuats = QUATS.length;
536
      mScramble = new int[numQuats][NUM_CUBITS];
535
      mScramble = new int[NUM_QUATS][NUM_CUBITS];
537 536
      mColors   = new int[NUM_CUBITS];
538 537

  
539
      for(int q=0; q<numQuats; q++)
538
      for(int q=0; q<NUM_QUATS; q++)
540 539
        for(int c=0; c<NUM_CUBITS; c++) mScramble[q][c] = computeScramble(q,c);
541 540
      }
542 541

  
......
815 814

  
816 815
  int mulQuat(int q1, int q2)
817 816
    {
818
    Static4D result = QuatHelper.quatMultiply(QUATS[q1],QUATS[q2]);
817
    Static4D result = QuatHelper.quatMultiply(OBJECT_QUATS[q1],OBJECT_QUATS[q2]);
819 818

  
820 819
    float rX = result.get0();
821 820
    float rY = result.get1();
......
825 824
    final float MAX_ERROR = 0.1f;
826 825
    float dX,dY,dZ,dW;
827 826

  
828
    for(int i=0; i<QUATS.length; i++)
827
    for(int i=0; i<NUM_QUATS; i++)
829 828
      {
830
      dX = QUATS[i].get0() - rX;
831
      dY = QUATS[i].get1() - rY;
832
      dZ = QUATS[i].get2() - rZ;
833
      dW = QUATS[i].get3() - rW;
829
      dX = OBJECT_QUATS[i].get0() - rX;
830
      dY = OBJECT_QUATS[i].get1() - rY;
831
      dZ = OBJECT_QUATS[i].get2() - rZ;
832
      dW = OBJECT_QUATS[i].get3() - rW;
834 833

  
835 834
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
836 835
          dY<MAX_ERROR && dY>-MAX_ERROR &&
837 836
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
838 837
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
839 838

  
840
      dX = QUATS[i].get0() + rX;
841
      dY = QUATS[i].get1() + rY;
842
      dZ = QUATS[i].get2() + rZ;
843
      dW = QUATS[i].get3() + rW;
839
      dX = OBJECT_QUATS[i].get0() + rX;
840
      dY = OBJECT_QUATS[i].get1() + rY;
841
      dZ = OBJECT_QUATS[i].get2() + rZ;
842
      dW = OBJECT_QUATS[i].get3() + rW;
844 843

  
845 844
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
846 845
          dY<MAX_ERROR && dY>-MAX_ERROR &&
......
946 945
      {
947 946
      mQuatDebug[i] = CUBITS[i].restorePreferences(preferences);
948 947

  
949
      if( mQuatDebug[i]>=0 && mQuatDebug[i]<QUATS.length)
948
      if( mQuatDebug[i]>=0 && mQuatDebug[i]<NUM_QUATS)
950 949
        {
951
        CUBITS[i].modifyCurrentPosition(QUATS[mQuatDebug[i]]);
950
        CUBITS[i].modifyCurrentPosition(OBJECT_QUATS[mQuatDebug[i]]);
952 951
        mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),mQuatDebug[i]);
953 952
        }
954 953
      else

Also available in: Unified diff