Project

General

Profile

Download (15.9 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / tablebases / TablebasesAbstract.java @ 8499ba3d

1 a110ebe1 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.objectlib.tablebases;
11
12 352b3356 Leszek Koltunski
import android.content.res.Resources;
13
14 a110ebe1 Leszek Koltunski
import org.distorted.library.main.QuatHelper;
15
import org.distorted.library.type.Static3D;
16
import org.distorted.library.type.Static4D;
17
import org.distorted.objectlib.helpers.QuatGroupGenerator;
18
19 352b3356 Leszek Koltunski
import java.io.ByteArrayOutputStream;
20
import java.io.IOException;
21
import java.io.InputStream;
22 bf5c802b Leszek Koltunski
import java.util.ArrayList;
23 3addecce Leszek Koltunski
import java.util.Random;
24 bf5c802b Leszek Koltunski
25 a110ebe1 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
26
27 1725b607 Leszek Koltunski
public abstract class TablebasesAbstract
28 a110ebe1 Leszek Koltunski
{
29
  private final Static3D[] mAxis;
30
  private final int mSize;
31
  private final int[][] mAngles;
32
  private final int mNumAxis;
33
  private final int[] mNumLayers;
34
  private final int mNumQuats;
35
  private final Static4D[] mQuats;
36
  private final int[][] mRotRow;
37
  private final int mNumCubits;
38
  private final float[][] mPosition;
39
  private final float[][] mCuts;
40
  private final int[] mNumCuts;
41 b4111717 Leszek Koltunski
  private final boolean[][] mRotatable;
42 3addecce Leszek Koltunski
  private final int mScalingFactor;
43 b4111717 Leszek Koltunski
44 d4b628bf Leszek Koltunski
  private Tablebase mTablebase;
45 a110ebe1 Leszek Koltunski
  private int[][] mQuatMult;
46 352b3356 Leszek Koltunski
  private boolean mInitialized;
47 a110ebe1 Leszek Koltunski
48 b4111717 Leszek Koltunski
  private static final float[] mTmp = new float[4];
49
50 a110ebe1 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
51
52
  abstract int[][] getBasicAngles();
53
  abstract Static3D[] getRotationAxis();
54
  abstract float[][] getPosition();
55
  abstract float[][] getCuts();
56
57 b4111717 Leszek Koltunski
  abstract boolean[][] getRotatable();
58
59
  abstract int getSize();
60
  abstract int[] getQuats(int index);
61
  abstract int getIndex(int[] quats);
62
63 a110ebe1 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
64
65 1725b607 Leszek Koltunski
  public TablebasesAbstract()
66 a110ebe1 Leszek Koltunski
    {
67
    mSize = getSize();
68
    mAngles = getBasicAngles();
69
    mAxis = getRotationAxis();
70
    mNumAxis = mAxis.length;
71
    mNumLayers = new int[mNumAxis];
72
    for(int i=0; i<mNumAxis; i++) mNumLayers[i] = mAngles[i].length;
73
    mQuats = QuatGroupGenerator.computeGroup(mAxis,mAngles);
74
    mNumQuats = mQuats.length;
75
    mPosition = getPosition();
76
    mNumCubits = mPosition.length;
77 b4111717 Leszek Koltunski
    mRotatable = getRotatable();
78 a110ebe1 Leszek Koltunski
    mCuts = getCuts();
79
    mNumCuts = new int[mNumAxis];
80
81 3addecce Leszek Koltunski
    int scaling = 0;
82
83 a110ebe1 Leszek Koltunski
    for(int i=0; i<mNumAxis; i++)
84
      {
85
      mNumCuts[i] = (mCuts==null || mCuts[i]==null ? 0 : mCuts[i].length);
86 3addecce Leszek Koltunski
      int numLayers = mNumLayers[i];
87
      for(int j=0; j<numLayers; j++) scaling+=(mAngles[i][j]-1);
88 a110ebe1 Leszek Koltunski
      }
89
90 3addecce Leszek Koltunski
    mScalingFactor = scaling;
91 a110ebe1 Leszek Koltunski
    mRotRow = new int[mNumCubits][mNumAxis];
92 5e501d98 Leszek Koltunski
    mInitialized = false;
93 352b3356 Leszek Koltunski
    }
94
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96
97 1725b607 Leszek Koltunski
  public TablebasesAbstract(Resources res, int resource)
98 352b3356 Leszek Koltunski
    {
99
    this();
100
101 f9980f6a Leszek Koltunski
    mInitialized = true;
102 352b3356 Leszek Koltunski
    InputStream stream = res.openRawResource(resource);
103
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
104
105
    int nRead;
106
    byte[] tmp = new byte[16384];
107
108
    try
109
      {
110
      while ((nRead = stream.read(tmp, 0, tmp.length)) != -1)
111
        {
112
        buffer.write(tmp, 0, nRead);
113
        }
114 1725b607 Leszek Koltunski
      stream.close();
115 352b3356 Leszek Koltunski
      byte[] data = buffer.toByteArray();
116 1725b607 Leszek Koltunski
      buffer.close();
117 352b3356 Leszek Koltunski
      mTablebase = new Tablebase(data);
118
      }
119
    catch(IOException ex)
120
      {
121
      mInitialized = false;
122
      }
123 a110ebe1 Leszek Koltunski
    }
124
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126
127 b4111717 Leszek Koltunski
  private int computeRow(float[] pos, int quat, int axisIndex)
128 a110ebe1 Leszek Koltunski
    {
129
    int ret=0;
130
    int len = pos.length/3;
131
    Static3D axis = mAxis[axisIndex];
132
    float axisX = axis.get0();
133
    float axisY = axis.get1();
134
    float axisZ = axis.get2();
135
    float casted, xoff=0, yoff=0, zoff=0;
136 b4111717 Leszek Koltunski
    Static4D q = mQuats[quat];
137 a110ebe1 Leszek Koltunski
138
    for(int i=0; i<len; i++)
139
      {
140 b4111717 Leszek Koltunski
      QuatHelper.rotateVectorByQuat(mTmp,pos[3*i],pos[3*i+1],pos[3*i+2],1.0f,q);
141
      casted = (mTmp[0]+xoff)*axisX + (mTmp[1]+yoff)*axisY + (mTmp[2]+zoff)*axisZ;
142 a110ebe1 Leszek Koltunski
      ret |= computeSingleRow(axisIndex,casted);
143
      }
144
145
    return ret;
146
    }
147
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149
150
  private int computeSingleRow(int axisIndex,float casted)
151
    {
152
    int num = mNumCuts[axisIndex];
153
154
    for(int i=0; i<num; i++)
155
      {
156
      if( casted<mCuts[axisIndex][i] ) return (1<<i);
157
      }
158
159
    return (1<<num);
160
    }
161
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163
// remember about the double cover or unit quaternions!
164
165
  private int mulQuat(int q1, int q2)
166
    {
167
    Static4D result = QuatHelper.quatMultiply(mQuats[q1],mQuats[q2]);
168
169
    float rX = result.get0();
170
    float rY = result.get1();
171
    float rZ = result.get2();
172
    float rW = result.get3();
173
174
    final float MAX_ERROR = 0.1f;
175
    float dX,dY,dZ,dW;
176
177
    for(int i=0; i<mNumQuats; i++)
178
      {
179
      dX = mQuats[i].get0() - rX;
180
      dY = mQuats[i].get1() - rY;
181
      dZ = mQuats[i].get2() - rZ;
182
      dW = mQuats[i].get3() - rW;
183
184
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
185
          dY<MAX_ERROR && dY>-MAX_ERROR &&
186
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
187
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
188
189
      dX = mQuats[i].get0() + rX;
190
      dY = mQuats[i].get1() + rY;
191
      dZ = mQuats[i].get2() + rZ;
192
      dW = mQuats[i].get3() + rW;
193
194
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
195
          dY<MAX_ERROR && dY>-MAX_ERROR &&
196
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
197
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
198
      }
199
200
    return -1;
201
    }
202
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204
205
  private int getMultQuat(int index1, int index2)
206
    {
207
    if( mQuatMult==null )
208
      {
209
      mQuatMult = new int[mNumQuats][mNumQuats];
210
211
      for(int i=0; i<mNumQuats; i++)
212
        for(int j=0; j<mNumQuats; j++) mQuatMult[i][j] = -1;
213
      }
214
215
    if( index1<mNumQuats && index2<mNumQuats )
216
      {
217
      if( mQuatMult[index1][index2]==-1 ) mQuatMult[index1][index2] = mulQuat(index1,index2);
218
      return mQuatMult[index1][index2];
219
      }
220
221
    return -2;
222
    }
223
224
///////////////////////////////////////////////////////////////////////////////////////////////////
225
// assumption: all layers have the same basicAngles!
226
227
  private int insertAllChildren(int index, byte level)
228
    {
229
    int ret = 0;
230
    int[] quats = getQuats(index);
231
    int numQuats = quats.length;
232
    int[] tmpQuats = new int[numQuats];
233
    byte newLevel = (byte)(level+1);
234
    int quatBasis = 0;
235
236 ce7202ef Leszek Koltunski
    for(int ax=0; ax<mNumAxis; ax++)
237
      for(int cubit=0; cubit<mNumCubits; cubit++)
238
        mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax);
239
240 a110ebe1 Leszek Koltunski
    for(int ax=0; ax<mNumAxis; ax++)
241
      {
242
      for(int layer=0; layer<mNumLayers[ax]; layer++)
243
        {
244 b4111717 Leszek Koltunski
        if( !mRotatable[ax][layer] ) continue;
245
        int bitLayer = (1<<layer);
246 a110ebe1 Leszek Koltunski
        int maxAngle = mAngles[ax][layer];
247
248
        for(int angle=1; angle<maxAngle; angle++ )
249
          {
250
          System.arraycopy(quats, 0, tmpQuats, 0, numQuats);
251
          int quat = quatBasis + angle;
252
253
          for(int cubit=0; cubit<mNumCubits; cubit++)
254 ce7202ef Leszek Koltunski
            if( mRotRow[cubit][ax]==bitLayer )
255 a110ebe1 Leszek Koltunski
              {
256
              int currQuat = tmpQuats[cubit];
257 b4111717 Leszek Koltunski
              int newQuat = getMultQuat(quat,currQuat);
258 a110ebe1 Leszek Koltunski
              tmpQuats[cubit] = newQuat;
259
              }
260
261
          int childIndex = getIndex(tmpQuats);
262
          if( mTablebase.insertUnpacked(childIndex,newLevel) ) ret++;
263
          }
264
        }
265
266
      quatBasis += (mAngles[ax][0]-1);
267
      }
268
269
    return ret;
270
    }
271
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273
274
  public void createTablebase()
275
    {
276
    mTablebase = new Tablebase(mSize);
277
    mTablebase.insertUnpacked(0,(byte)0);
278
279 f9980f6a Leszek Koltunski
    int numInserted, totalInserted=1;
280 a110ebe1 Leszek Koltunski
    byte insertingLevel = 0;
281
282 462911fd Leszek Koltunski
    android.util.Log.e("D", "creating tablebase of size "+mSize);
283
284 a110ebe1 Leszek Koltunski
    do
285
      {
286
      numInserted = 0;
287
288
      for(int i=0; i<mSize; i++)
289
        {
290
        byte level = mTablebase.retrieveUnpacked(i);
291
        if( level==insertingLevel ) numInserted += insertAllChildren(i,level);
292
        }
293
294
      insertingLevel++;
295 f9980f6a Leszek Koltunski
      totalInserted += numInserted;
296 bf5c802b Leszek Koltunski
      android.util.Log.e("D", "inserted "+numInserted+" positions at level "+insertingLevel);
297 a110ebe1 Leszek Koltunski
      }
298
    while( numInserted>0 );
299 bf5c802b Leszek Koltunski
300 f9980f6a Leszek Koltunski
    android.util.Log.e("D", "total Inserted: "+totalInserted);
301 462911fd Leszek Koltunski
    android.util.Log.e("D", "packing...");
302 bf5c802b Leszek Koltunski
    mTablebase.pack();
303 462911fd Leszek Koltunski
    android.util.Log.e("D", "all done");
304 5e501d98 Leszek Koltunski
    mInitialized = true;
305 462911fd Leszek Koltunski
    }
306
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308
309
  public byte[] getPacked()
310
    {
311
    return mTablebase.getPacked();
312 a110ebe1 Leszek Koltunski
    }
313 3ee79c9c Leszek Koltunski
314
///////////////////////////////////////////////////////////////////////////////////////////////////
315
316 bf5c802b Leszek Koltunski
  private void addMove(ArrayList<int[]> moves, int axis, int layer, int angle)
317 3ee79c9c Leszek Koltunski
    {
318
    int maxAngle = mAngles[axis][layer];
319
    angle = maxAngle-angle;
320
    if( angle> 0.5f*maxAngle ) angle -= maxAngle;
321
322 bf5c802b Leszek Koltunski
    int[] move = new int[] { axis, (1<<layer), angle };
323
    moves.add(move);
324
    }
325
326 462911fd Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
327
328
  private void addMove(int[] moves, int axis, int layer, int angle)
329
    {
330
    int maxAngle = mAngles[axis][layer];
331
    angle = maxAngle-angle;
332
    if( angle> 0.5f*maxAngle ) angle -= maxAngle;
333
334
    moves[0] = axis;
335
    moves[1] = (1<<layer);
336
    moves[2] = angle;
337
    }
338
339 bf5c802b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
340
341
  private int[][] convertMoves(ArrayList<int[]> moves)
342
    {
343
    int len = moves.size();
344
    int[][] ret = new int[len][];
345
    for(int i=0; i<len; i++) ret[i] = moves.get(i);
346
    return ret;
347 3ee79c9c Leszek Koltunski
    }
348
349 3addecce Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
350
351 971a184e Leszek Koltunski
  private void getNextAxisLayerAngleQuat(int[] data)
352 3addecce Leszek Koltunski
    {
353
    int axis = data[0];
354
    int layer= data[1];
355
    int angle= data[2];
356
357
    if( angle< mAngles[axis][layer]-1 ) data[2]++;
358
    else
359
      {
360
      data[2] = 1;
361
362
      if( layer< mNumLayers[axis]-1 ) data[1]++;
363
      else
364
        {
365
        data[1] = 0;
366
        data[0] = (axis<mNumAxis-1) ? axis+1 : 0;
367
        }
368
      }
369 971a184e Leszek Koltunski
370
    data[3] = data[2];
371
    for(int i=0; i<data[0]; i++) data[3] += (mAngles[i][0]-1);
372 3addecce Leszek Koltunski
    }
373
374 3ee79c9c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
375
376
  public int[][] solution(int index)
377
    {
378 352b3356 Leszek Koltunski
    if( !mInitialized ) return null;
379
380 971a184e Leszek Koltunski
    int[] data = new int[4];
381 431ee33b Leszek Koltunski
    byte level = mTablebase.retrievePacked(index);
382 bf5c802b Leszek Koltunski
    ArrayList<int[]> moves = new ArrayList<>();
383 3ee79c9c Leszek Koltunski
    int[] quats = getQuats(index);
384
    int numQuats = quats.length;
385
    int[] tmpQuats = new int[numQuats];
386
387 bf5c802b Leszek Koltunski
    while(index!=0)
388 3ee79c9c Leszek Koltunski
      {
389 7c1a110c Leszek Koltunski
      boolean found = false;
390
391 3addecce Leszek Koltunski
      data[0]=0;
392
      data[1]=0;
393
      data[2]=1;
394 971a184e Leszek Koltunski
      data[3]=1;
395 3addecce Leszek Koltunski
396 ce7202ef Leszek Koltunski
      for(int ax=0; ax<mNumAxis; ax++)
397
        for(int cubit=0; cubit<mNumCubits; cubit++)
398
          mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax);
399
400 3addecce Leszek Koltunski
      for(int s=0; s<mScalingFactor && !found; s++)
401 3ee79c9c Leszek Koltunski
        {
402 3addecce Leszek Koltunski
        int ax    = data[0];
403
        int layer = data[1];
404
        int angle = data[2];
405 971a184e Leszek Koltunski
        int quat  = data[3];
406 3ee79c9c Leszek Koltunski
407 3addecce Leszek Koltunski
        if( mRotatable[ax][layer] )
408 3ee79c9c Leszek Koltunski
          {
409
          int bitLayer = (1<<layer);
410 3addecce Leszek Koltunski
          System.arraycopy(quats, 0, tmpQuats, 0, numQuats);
411 3ee79c9c Leszek Koltunski
412 3addecce Leszek Koltunski
          for(int cubit=0; cubit<mNumCubits; cubit++)
413
            if( mRotRow[cubit][ax]==bitLayer )
414 3ee79c9c Leszek Koltunski
              {
415 3addecce Leszek Koltunski
              int currQuat = tmpQuats[cubit];
416
              int newQuat = getMultQuat(quat,currQuat);
417
              tmpQuats[cubit] = newQuat;
418 3ee79c9c Leszek Koltunski
              }
419 3addecce Leszek Koltunski
420
          int childIndex = getIndex(tmpQuats);
421
          byte newLevel = mTablebase.retrievePacked(childIndex);
422
423
          if( ((newLevel-level+1)%3) == 0 )
424
            {
425
            addMove(moves,ax,layer,angle);
426
            index = childIndex;
427
            level = (level==0 ? 2 : (byte)(level-1));
428
            found = true;
429 3ee79c9c Leszek Koltunski
            }
430
          }
431
432 971a184e Leszek Koltunski
        getNextAxisLayerAngleQuat(data);
433 3ee79c9c Leszek Koltunski
        }
434
435
      quats = getQuats(index);
436 7c1a110c Leszek Koltunski
437
      if( !found )
438
        {
439 74cc695a Leszek Koltunski
        android.util.Log.e("D", "----> solution error: no move found!");
440 7c1a110c Leszek Koltunski
        return null;
441
        }
442 3ee79c9c Leszek Koltunski
      }
443
444 bf5c802b Leszek Koltunski
    return convertMoves(moves);
445 3ee79c9c Leszek Koltunski
    }
446 462911fd Leszek Koltunski
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448
449 3addecce Leszek Koltunski
  public int[][] scramble(Random rnd, int depth)
450 462911fd Leszek Koltunski
    {
451 3addecce Leszek Koltunski
    if( !mInitialized ) return null;
452
453 971a184e Leszek Koltunski
    int[] data = new int[4];
454 462911fd Leszek Koltunski
    int level=0;
455 3addecce Leszek Koltunski
    int[][] moves = new int[depth][3];
456 462911fd Leszek Koltunski
    int[] quats = getQuats(0);
457
    int numQuats = quats.length;
458
    int[] tmpQuats = new int[numQuats];
459
460
    while(level<depth)
461
      {
462
      boolean found = false;
463
464 3addecce Leszek Koltunski
      data[0]=0;
465
      data[1]=0;
466
      data[2]=1;
467 971a184e Leszek Koltunski
      data[3]=1;
468 3addecce Leszek Koltunski
469
      int random = rnd.nextInt(mScalingFactor);
470 971a184e Leszek Koltunski
      for(int i=0; i<random; i++) getNextAxisLayerAngleQuat(data);
471 3addecce Leszek Koltunski
472 ce7202ef Leszek Koltunski
      for(int ax=0; ax<mNumAxis; ax++)
473
        for(int cubit=0; cubit<mNumCubits; cubit++)
474
          mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax);
475
476 3addecce Leszek Koltunski
      for(int s=0; s<mScalingFactor && !found; s++)
477 462911fd Leszek Koltunski
        {
478 3addecce Leszek Koltunski
        int ax    = data[0];
479
        int layer = data[1];
480
        int angle = data[2];
481 971a184e Leszek Koltunski
        int quat  = data[3];
482 462911fd Leszek Koltunski
483 3addecce Leszek Koltunski
        if( mRotatable[ax][layer] )
484 462911fd Leszek Koltunski
          {
485
          int bitLayer = (1<<layer);
486 3addecce Leszek Koltunski
          System.arraycopy(quats, 0, tmpQuats, 0, numQuats);
487 462911fd Leszek Koltunski
488 3addecce Leszek Koltunski
          for(int cubit=0; cubit<mNumCubits; cubit++)
489
            if( mRotRow[cubit][ax]==bitLayer )
490 462911fd Leszek Koltunski
              {
491 3addecce Leszek Koltunski
              int currQuat = tmpQuats[cubit];
492
              int newQuat = getMultQuat(quat,currQuat);
493
              tmpQuats[cubit] = newQuat;
494 462911fd Leszek Koltunski
              }
495 3addecce Leszek Koltunski
496
          int childIndex = getIndex(tmpQuats);
497
          byte newLevel = mTablebase.retrievePacked(childIndex);
498
499
          if( ((newLevel-level-1)%3) == 0 )
500
            {
501
            addMove(moves[level],ax,layer,angle);
502
            level++;
503
            quats = getQuats(childIndex);
504
            found = true;
505 462911fd Leszek Koltunski
            }
506
          }
507
508 971a184e Leszek Koltunski
        getNextAxisLayerAngleQuat(data);
509 462911fd Leszek Koltunski
        }
510
511
      if( !found )
512
        {
513 f9980f6a Leszek Koltunski
        android.util.Log.e("D", "scramble error: no move found!");
514 462911fd Leszek Koltunski
        return null;
515
        }
516
      }
517
518
    return moves;
519
    }
520 74cc695a Leszek Koltunski
521
///////////////////////////////////////////////////////////////////////////////////////////////////
522
523
  public boolean test(int index)
524
    {
525
    if( !mInitialized ) return false;
526
527
    int[] data = new int[4];
528
    byte level = mTablebase.retrievePacked(index);
529
    int[] quats = getQuats(index);
530
    int numQuats = quats.length;
531
    int[] tmpQuats = new int[numQuats];
532
533
    data[0]=0;
534
    data[1]=0;
535
    data[2]=1;
536
    data[3]=1;
537
538
    for(int ax=0; ax<mNumAxis; ax++)
539
      for(int cubit=0; cubit<mNumCubits; cubit++)
540
        mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax);
541
542
    for(int s=0; s<mScalingFactor; s++)
543
      {
544
      int ax    = data[0];
545
      int layer = data[1];
546
      int quat  = data[3];
547
548
      if( mRotatable[ax][layer] )
549
        {
550
        int bitLayer = (1<<layer);
551
        System.arraycopy(quats, 0, tmpQuats, 0, numQuats);
552
553
        for(int cubit=0; cubit<mNumCubits; cubit++)
554
          if( mRotRow[cubit][ax]==bitLayer )
555
            {
556
            int currQuat = tmpQuats[cubit];
557
            int newQuat = getMultQuat(quat,currQuat);
558
            tmpQuats[cubit] = newQuat;
559
            }
560
561
        int childIndex = getIndex(tmpQuats);
562
        byte newLevel = mTablebase.retrievePacked(childIndex);
563
564
        if( ((newLevel-level+1)%3) == 0 ) return true;
565
        }
566
567
      getNextAxisLayerAngleQuat(data);
568
      }
569
570
    return false;
571
    }
572 a110ebe1 Leszek Koltunski
}