commit 3ede7593a7aa22acff2fa5a6f8b2646514df9044
Author: leszek <leszek@koltunski.pl>
Date:   Wed Sep 6 23:13:12 2023 +0200

    progress with TwistyBandagedMegaminx.

diff --git a/src/main/java/org/distorted/objectlib/bandaged/BandagedObjectMegaminx.java b/src/main/java/org/distorted/objectlib/bandaged/BandagedObjectMegaminx.java
index 4c44560c..f5437d78 100644
--- a/src/main/java/org/distorted/objectlib/bandaged/BandagedObjectMegaminx.java
+++ b/src/main/java/org/distorted/objectlib/bandaged/BandagedObjectMegaminx.java
@@ -141,42 +141,20 @@ public class BandagedObjectMegaminx extends BandagedObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  float[][][] getPositions()
-    {
-    FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
-    return factory.getPositions(mSize);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  float getDist2D()
-    {
-    return (SIN54/COS54)/2;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  int[] getColors()
-    {
-    return ShapeDodecahedron.FACE_COLORS;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  boolean isAdjacent(float dx, float dy, float dz)
+  public static boolean isAdjacent(int size, float dx, float dy, float dz)
     {
     float len = dx*dx + dy*dy + dz*dz;
     float MAXERR = 0.01f;
 
-    switch(mSize[0])
+    switch(size)
       {
-      case 2: float x2_0 = 3.01f;
+      case 2: float x2_0 = 2.01f;
               return len<=x2_0*x2_0;
 
       case 3: float x3_0 = 1.51f*(SIN54/COS54);
               return len<=x3_0*x3_0;
 
-      case 4: float x4_0 = 1.00f;
+      case 4: float x4_0 = 1.0f;
               float x4_1 = 2.00f;
               float x4_2 = 2.00f*(1+SIN18);
               float d4_0 = len-x4_0*x4_0;
@@ -208,6 +186,36 @@ public class BandagedObjectMegaminx extends BandagedObject
     return false;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  float[][][] getPositions()
+    {
+    FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
+    return factory.getPositions(mSize);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  float getDist2D()
+    {
+    return (SIN54/COS54)/2;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  int[] getColors()
+    {
+    return ShapeDodecahedron.FACE_COLORS;
+    }
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  boolean isAdjacent(float dx, float dy, float dz)
+    {
+    return isAdjacent(mSize[0],dx,dy,dz);
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   MeshBase createMesh(float[] pos, boolean round)
diff --git a/src/main/java/org/distorted/objectlib/helpers/ObjectSignature.java b/src/main/java/org/distorted/objectlib/helpers/ObjectSignature.java
index a689cb1d..9a306eef 100644
--- a/src/main/java/org/distorted/objectlib/helpers/ObjectSignature.java
+++ b/src/main/java/org/distorted/objectlib/helpers/ObjectSignature.java
@@ -11,13 +11,26 @@ package org.distorted.objectlib.helpers;
 
 import java.util.ArrayList;
 
+import static org.distorted.objectlib.bandaged.BandagedObjectMegaminx.MEGA_D;
+import static org.distorted.objectlib.bandaged.BandagedObjectMegaminx.SIN18;
 import static org.distorted.objectlib.main.TwistyObject.SQ2;
 import static org.distorted.objectlib.main.TwistyObject.SQ3;
 import static org.distorted.objectlib.main.TwistyObject.SQ6;
+import static org.distorted.objectlib.objects.TwistyBandagedMegaminx.KILOMINX3;
+import static org.distorted.objectlib.objects.TwistyBandagedMegaminx.KILOMINX5;
+import static org.distorted.objectlib.objects.TwistyBandagedMegaminx.MEGAMINX3;
+import static org.distorted.objectlib.objects.TwistyBandagedMegaminx.MEGAMINX5;
 import static org.distorted.objectlib.scrambling.ScrambleStateLocallyBandaged.MAX_SUPPORTED_SIZE;
+import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.C2;
+import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.COS54;
+import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.LEN;
+import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.SIN54;
 
 import org.distorted.library.helpers.QuatHelper;
+import org.distorted.objectlib.bandaged.BandagedObjectMegaminx;
+import org.distorted.objectlib.bandaged.FactoryBandagedMegaminx;
 import org.distorted.objectlib.bandaged.FactoryBandagedPyraminx;
+import org.distorted.objectlib.touchcontrol.TouchControlDodecahedron;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -41,6 +54,26 @@ public class ObjectSignature implements Comparable<ObjectSignature>
                 {-SQ2/2,  0.5f,      0, 0.5f },
         };
 
+  private static final float[][] mRotAxisMegaminx =
+        {
+                {    C2/LEN, SIN54/LEN,    0      },
+                {   -C2/LEN, SIN54/LEN,    0      },
+                { 0        ,    C2/LEN, SIN54/LEN },
+                { 0        ,   -C2/LEN, SIN54/LEN },
+                { SIN54/LEN,    0     ,    C2/LEN },
+                { SIN54/LEN,    0     ,   -C2/LEN }
+        };
+
+  private static final float[][] mQuatsMegaminx =
+        {
+                {  COS54*   C2/LEN, COS54*SIN54/LEN, 0              , SIN54 },
+                { -COS54*   C2/LEN, COS54*SIN54/LEN, 0              , SIN54 },
+                {  0              , COS54*   C2/LEN, COS54*SIN54/LEN, SIN54 },
+                {  0              ,-COS54*   C2/LEN, COS54*SIN54/LEN, SIN54 },
+                {  COS54*SIN54/LEN, 0              , COS54*   C2/LEN, SIN54 },
+                {  COS54*SIN54/LEN, 0              ,-COS54*   C2/LEN, SIN54 }
+        };
+
   private long[] mSignature;
   private int[] mLayer;
   private int[][][][] mCycles;
@@ -52,16 +85,22 @@ public class ObjectSignature implements Comparable<ObjectSignature>
   private int[] mNumInneCyclesPerLayer;
   private String mName=null;
   private float[] mTmp;
+  private int mParam;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // a cube of size N has 12*(N-1)^2 possible places two adjacent cubies can be 'glued'; therefore
 // the signature must contain ceil( 12*(N-1)^2 / 64 ) bytes.
 // a pyraminx of size N has 4 + 6*(N-1)(N-2) places two adjacent cubies can be 'glued' so much less.
 
+// Gigaminx has 480 such places (so more if N<=7)
+
   private static int computeNum()
     {
     int max = MAX_SUPPORTED_SIZE-1;
-    return (int)(0.95f + (3*max*max)/16.0f);
+    int ret = (int)(0.99f + (12*max*max)/64.0f);
+    int giga= (int)(0.99f + (       480)/64.0f);
+
+    return Math.max(ret,giga);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -93,6 +132,7 @@ public class ObjectSignature implements Comparable<ObjectSignature>
     mTouchRows  = sig.mTouchRows;
     mName       = sig.mName;
     mTmp        = sig.mTmp;
+    mParam      = sig.mParam;
 
     mNumCubitTouches       = sig.mNumCubitTouches;
     mNumCentCyclesPerLayer = sig.mNumCentCyclesPerLayer;
@@ -111,32 +151,53 @@ public class ObjectSignature implements Comparable<ObjectSignature>
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // locally created bandaged cuboids created from JSON (version2)
-// or locally created bandaged pyraminxes.
-// How to tell apart: pyraminx's shortName starts with a 'P'.
+// or locally created bandaged pyraminxes, or locally bandaged megaminxes.
+// How to tell apart: pyraminx's shortName starts with a 'P'; megaminx's shortName starts with a 'M'.
 
   public ObjectSignature(String shortName, long[] signature)
     {
     setUpSignature(signature);
 
-    if( shortName.charAt(0) != 'P' )
-      {
-      int x=shortName.charAt(0)-'0';
-      int y=shortName.charAt(1)-'0';
-      int z=shortName.charAt(2)-'0';
-      mLayer=new int[]{x, y, z};
-      prepareCubitTouch();
-      prepareTouchRows();
-      prepareAllCycles();
-      }
-    else
+    char name = shortName.charAt(0);
+
+    if( name == 'P' )
       {
       mTmp = new float[4];
       int x=shortName.charAt(1)-'0';
-      mLayer=new int[]{x, x, x, x};
+      mLayer=new int[] {x,x,x,x};
       prepareCubitTouchPyraminx();
       prepareTouchRowsPyraminx();
       prepareAllCyclesPyraminx();
       }
+    else if( name == 'M' )
+      {
+      mTmp = new float[4];
+      mParam=shortName.charAt(1)-'0';
+      int x=-1;
+
+      switch(mParam)
+        {
+        case 2:
+        case 3: x = 3; break;
+        case 4:
+        case 5: x = 5; break;
+        }
+
+      mLayer=new int[] {x,x,x,x,x,x};
+      prepareCubitTouchMegaminx();
+      prepareTouchRowsMegaminx();
+      prepareAllCyclesMegaminx();
+      }
+    else
+      {
+      int x=shortName.charAt(0)-'0';
+      int y=shortName.charAt(1)-'0';
+      int z=shortName.charAt(2)-'0';
+      mLayer=new int[] {x,y,z};
+      prepareCubitTouchCuboid();
+      prepareTouchRowsCuboid();
+      prepareAllCyclesCuboid();
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -148,9 +209,9 @@ public class ObjectSignature implements Comparable<ObjectSignature>
 
     mLayer = new int[] {size,size,size};
 
-    prepareCubitTouch();
-    prepareTouchRows();
-    prepareAllCycles();
+    prepareCubitTouchCuboid();
+    prepareTouchRowsCuboid();
+    prepareAllCyclesCuboid();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -171,9 +232,9 @@ public class ObjectSignature implements Comparable<ObjectSignature>
     mLayer = new int[] {lenx,leny,lenz};
     mSignature = new long[SIZE];
 
-    prepareCubitTouch();
-    prepareTouchRows();
-    prepareAllCycles();
+    prepareCubitTouchCuboid();
+    prepareTouchRowsCuboid();
+    prepareAllCyclesCuboid();
 
     for(float[] pos : position)
       {
@@ -191,7 +252,7 @@ public class ObjectSignature implements Comparable<ObjectSignature>
           float yj = pos[3*j+1];
           float zj = pos[3*j+2];
 
-          if(areNeighbours(xi-xj,yi-yj,zi-zj))
+          if(areNeighboursCuboid(xi-xj,yi-yj,zi-zj))
             {
             float xc = (xi+xj)/2;
             float yc = (yi+yj)/2;
@@ -260,6 +321,60 @@ public class ObjectSignature implements Comparable<ObjectSignature>
       }
     }
 
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Locally created bandaged megaminxes size 2<=N<=5
+
+  public ObjectSignature(float[][] position, int param)
+    {
+    int size = -1;
+
+    switch(param)
+      {
+      case KILOMINX3: size = 2; break;
+      case MEGAMINX3: size = 3; break;
+      case KILOMINX5: size = 4; break;
+      case MEGAMINX5: size = 5; break;
+      }
+
+    mLayer = new int[] {size,size,size,size,size,size};
+    mSignature = new long[SIZE];
+    mTmp = new float[4];
+
+    prepareCubitTouchMegaminx();
+    prepareTouchRowsMegaminx();
+    prepareAllCyclesMegaminx();
+
+    for(float[] pos : position)
+      {
+      int numCenters = pos.length/3;
+
+      for(int i=0; i<numCenters; i++)
+        {
+        float xi = pos[3*i  ];
+        float yi = pos[3*i+1];
+        float zi = pos[3*i+2];
+
+        for(int j=i+1; j<numCenters; j++)
+          {
+          float xj = pos[3*j  ];
+          float yj = pos[3*j+1];
+          float zj = pos[3*j+2];
+
+          if( areNeighboursMegaminx(param,xi-xj,yi-yj,zi-zj) )
+            {
+            float xc = (xi+xj)/2;  // TODO
+            float yc = (yi+yj)/2;
+            float zc = (zi+zj)/2;
+
+            int bitIndex = getIndexOfCubitTouch(xc,yc,zc);
+            setBit(bitIndex,1);
+            }
+          }
+        }
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void setSignature(int signature)
@@ -328,8 +443,16 @@ public class ObjectSignature implements Comparable<ObjectSignature>
   public boolean isUnblockedFromLeft(int axis, int layer)
     {
     if(layer>0)
-      for(int index=0; index<mNumCubitTouches; index++)
-        if( getBit(index)!=0 && mTouchRows[index][axis]==layer ) return false;
+      {
+      int[] touch = mTouchRows[axis];
+
+      for( int index=0; index<mNumCubitTouches; index++)
+        if( touch[index]==layer && getBit(index)!=0 )
+          {
+          android.util.Log.e("D", "axis "+axis+" layer "+layer+" is blocked from Left");
+          return false;
+          }
+      }
 
     return true;
     }
@@ -348,9 +471,10 @@ public class ObjectSignature implements Comparable<ObjectSignature>
       // it can happen that there are no cycles in this layer: 2x1x2 axis 0 layer 0.
       if( cycles!=null && cycles.length>0 && cycles[0]!=null )
         {
-             if( cycles[0].length==4 ) for(int[] cyc : cycles) ret.cycle4(turn,cyc);
+             if( cycles[0].length==5 ) for(int[] cyc : cycles) ret.cycle5(turn,cyc);
+        else if( cycles[0].length==4 ) for(int[] cyc : cycles) ret.cycle4(turn,cyc);
         else if( cycles[0].length==3 ) for(int[] cyc : cycles) ret.cycle3(turn,cyc);
-        else                           for(int[] cyc : cycles) ret.cycle2(cyc);
+        else if( cycles[0].length==2 ) for(int[] cyc : cycles) ret.cycle2(cyc);
         }
       }
 
@@ -432,7 +556,52 @@ public class ObjectSignature implements Comparable<ObjectSignature>
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void prepareCubitTouch()
+  private void cycle5(int turn, int[] cyc)
+    {
+    int index0 = cyc[0];
+    int index1 = cyc[1];
+    int index2 = cyc[2];
+    int index3 = cyc[3];
+    int index4 = cyc[4];
+
+    long b0 = getBit(index0);
+    long b1 = getBit(index1);
+    long b2 = getBit(index2);
+    long b3 = getBit(index3);
+    long b4 = getBit(index4);
+
+    switch(turn)
+      {
+      case 1: setBit(index0,b4);
+              setBit(index1,b0);
+              setBit(index2,b1);
+              setBit(index3,b2);
+              setBit(index4,b3);
+              break;
+      case 2: setBit(index0,b3);
+              setBit(index1,b4);
+              setBit(index2,b0);
+              setBit(index3,b1);
+              setBit(index4,b2);
+              break;
+      case 3: setBit(index0,b2);
+              setBit(index1,b3);
+              setBit(index2,b4);
+              setBit(index3,b0);
+              setBit(index4,b1);
+              break;
+      case 4: setBit(index0,b1);
+              setBit(index1,b2);
+              setBit(index2,b3);
+              setBit(index3,b4);
+              setBit(index4,b0);
+              break;
+    }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void prepareCubitTouchCuboid()
     {
     int numCenters = mLayer[0]*mLayer[1]*mLayer[2];
     if( mLayer[0]>1 && mLayer[1]>1 && mLayer[2]>1 ) numCenters -= (mLayer[0]-2)*(mLayer[1]-2)*(mLayer[2]-2);
@@ -463,7 +632,7 @@ public class ObjectSignature implements Comparable<ObjectSignature>
         float y2 = c1[1];
         float z2 = c1[2];
 
-        if( areNeighbours(x1-x2,y1-y2,z1-z2) )
+        if( areNeighboursCuboid(x1-x2,y1-y2,z1-z2) )
           {
           float xc = (x1+x2)/2;
           float yc = (y1+y2)/2;
@@ -506,9 +675,9 @@ public class ObjectSignature implements Comparable<ObjectSignature>
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void prepareTouchRows()
+  private void prepareTouchRowsCuboid()
     {
-    mTouchRows = new int[mNumCubitTouches][3];
+    mTouchRows = new int[3][mNumCubitTouches];
 
     for(int i=0; i<mNumCubitTouches; i++)
       {
@@ -517,14 +686,14 @@ public class ObjectSignature implements Comparable<ObjectSignature>
       for(int a=0; a<3; a++)
         {
         int l = (int)(2*touch[a] + mLayer[a] + 0.01f);
-        mTouchRows[i][a] = ( (l%2)==0 ) ? l/2 : -1;
+        mTouchRows[a][i] = ( (l%2)==0 ) ? l/2 : -1;
         }
       }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void prepareAllCycles()
+  private void prepareAllCyclesCuboid()
     {
     ArrayList<float[][]> cycles0 = new ArrayList<>();
     ArrayList<float[][]> cycles1 = new ArrayList<>();
@@ -698,7 +867,7 @@ public class ObjectSignature implements Comparable<ObjectSignature>
           float yc=(2*ty+oy)/3;
           float zc=(2*tz+oz)/3;
 
-          float[] touch=new float[]{xc, yc, zc};
+          float[] touch = new float[] {xc, yc, zc};
           mTouch.add(touch);
           }
         }
@@ -712,7 +881,7 @@ public class ObjectSignature implements Comparable<ObjectSignature>
 
   private void prepareTouchRowsPyraminx()
     {
-    mTouchRows = new int[mNumCubitTouches][4];
+    mTouchRows = new int[4][mNumCubitTouches];
     int num = mLayer[0];
     final int N = 10;
 
@@ -725,7 +894,7 @@ public class ObjectSignature implements Comparable<ObjectSignature>
         float[] ax = mRotAxisPyraminx[a];
         float l = whichLayerPyraminx(touch,ax,num);
         int ll = (int)(N*l);
-        mTouchRows[i][a] = ( (ll%N)==0 ) ? ll/N : -1;
+        mTouchRows[a][i] = ( (ll%N)==0 ) ? ll/N : -1;
         }
       }
     }
@@ -826,6 +995,232 @@ public class ObjectSignature implements Comparable<ObjectSignature>
     return getIndexOfCubitTouch(mTmp[0],mTmp[1],mTmp[2]);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private float[] getPosition(int index, float[][][] centers, int len)
+    {
+    int num = 0, i1=0, i2=0;
+
+    for(int i=0; i<len; i++)
+      {
+      int t = centers[i].length;
+
+      if( t > index-num )
+        {
+        i1 = i;
+        i2 = index-num;
+        break;
+        }
+      else
+        {
+        num += t;
+        }
+      }
+
+    return centers[i1][i2];
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void prepareCubitTouchMegaminx()
+    {
+    FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
+    float[][][] centers = factory.getPositions(mLayer);
+    int size = mLayer[0];
+
+    int numCubits=0;
+    int numVariants = centers.length;
+    for(float[][] center : centers) numCubits += center.length;
+
+    ArrayList<float[]> mTouch = new ArrayList<>();
+
+    for(int i=0; i<numCubits; i++)
+      {
+      float[] first = getPosition(i,centers,numVariants);
+
+      for(int j = i+1; j<numCubits; j++)
+        {
+        float[] second = getPosition(j,centers,numVariants);
+
+        float ox = first[0];
+        float oy = first[1];
+        float oz = first[2];
+        float tx = second[0];
+        float ty = second[1];
+        float tz = second[2];
+
+        if( areNeighboursMegaminx(size, ox-tx, oy-ty, oz-tz) )
+          {
+          float xc = (tx+ox)/2;  // TODO; wrong
+          float yc = (ty+oy)/2;
+          float zc = (tz+oz)/2;
+
+          float[] touch = new float[] {xc, yc, zc};
+          mTouch.add(touch);
+          }
+        }
+      }
+
+    mNumCubitTouches = mTouch.size();
+    mCubitTouch = new float[mNumCubitTouches][];
+    for(int i=0; i<mNumCubitTouches; i++) mCubitTouch[i] = mTouch.remove(0);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void prepareTouchRowsMegaminx()
+    {
+    mTouchRows = new int[6][mNumCubitTouches];
+    int num = mLayer[0];
+    final int N = 10;
+
+    for(int i=0; i<mNumCubitTouches; i++)
+      {
+      float[] touch = mCubitTouch[i];
+
+      for(int a=0; a<6; a++)
+        {
+        float[] ax = mRotAxisMegaminx[a];
+        float l = whichLayerMegaminx(touch,ax,num);
+        int ll = (int)(N*l);
+        mTouchRows[a][i] = ( (ll%N)==0 ) ? ll/N : -1;
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void prepareAllCyclesMegaminx()
+    {
+    ArrayList<float[][]> cycles0 = new ArrayList<>();
+    ArrayList<float[][]> cycles1 = new ArrayList<>();
+    ArrayList<float[][]> cycles2 = new ArrayList<>();
+    ArrayList<float[][]> cycles3 = new ArrayList<>();
+    ArrayList<float[][]> cycles4 = new ArrayList<>();
+    ArrayList<float[][]> cycles5 = new ArrayList<>();
+
+    generate5CyclesMegaminx(cycles0,0);
+    generate5CyclesMegaminx(cycles1,1);
+    generate5CyclesMegaminx(cycles2,2);
+    generate5CyclesMegaminx(cycles3,3);
+    generate5CyclesMegaminx(cycles4,4);
+    generate5CyclesMegaminx(cycles5,5);
+
+    mCycles = new int[6][][][];
+
+    int numLayers = mLayer[0];
+    mCycles[0] = fillUpCyclesMegaminx(cycles0,0,numLayers);
+    mCycles[1] = fillUpCyclesMegaminx(cycles1,1,numLayers);
+    mCycles[2] = fillUpCyclesMegaminx(cycles2,2,numLayers);
+    mCycles[3] = fillUpCyclesMegaminx(cycles3,3,numLayers);
+    mCycles[4] = fillUpCyclesMegaminx(cycles4,4,numLayers);
+    mCycles[5] = fillUpCyclesMegaminx(cycles5,5,numLayers);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void generate5CyclesMegaminx(ArrayList<float[][]> cycles, int ax)
+    {
+    for(int i=0; i<mNumCubitTouches; i++)
+      {
+      int i0 = rotateIndex5(ax,i);
+      if( i0<=i ) continue;
+      int i1 = rotateIndex5(ax,i0);
+      if( i1<=i ) continue;
+      int i2 = rotateIndex5(ax,i1);
+      if( i2<=i ) continue;
+      int i3 = rotateIndex5(ax,i2);
+      if( i3<=i ) continue;
+
+      float[] f0 = getCubitTouchOfIndex(i);
+      float[] f1 = getCubitTouchOfIndex(i0);
+      float[] f2 = getCubitTouchOfIndex(i1);
+      float[] f3 = getCubitTouchOfIndex(i2);
+      float[] f4 = getCubitTouchOfIndex(i3);
+
+      float[][] cycle = new float[][] { f0,f1,f2,f3,f4 };
+      cycles.add(cycle);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int[][][] fillUpCyclesMegaminx(ArrayList<float[][]> cyc, int axis, int numLayers)
+    {
+    int numCycles = cyc.size();
+    int[] index = new int[numLayers];
+    int[] numC = new int[numLayers];
+    float[] ax = mRotAxisMegaminx[axis];
+
+    for(int i=0; i<numCycles; i++)
+      {
+      float[][] cycle = cyc.get(i);
+      int layer = (int)whichLayerMegaminx(cycle[0],ax,numLayers);
+      numC[layer]++;
+      }
+
+    int[][][] ret = new int[numLayers][][];
+    for(int i=0; i<numLayers; i++) ret[i] = new int[numC[i]][];
+
+    for(int i=0; i<numCycles; i++)
+      {
+      float[][] cycle = cyc.remove(0);
+      int layer = (int)whichLayerMegaminx(cycle[0],ax,numLayers);
+
+      int i0 = getIndexOfCubitTouch(cycle[0][0],cycle[0][1],cycle[0][2]);
+      int i1 = getIndexOfCubitTouch(cycle[1][0],cycle[1][1],cycle[1][2]);
+      int i2 = getIndexOfCubitTouch(cycle[2][0],cycle[2][1],cycle[2][2]);
+      int i3 = getIndexOfCubitTouch(cycle[3][0],cycle[3][1],cycle[3][2]);
+      int i4 = getIndexOfCubitTouch(cycle[4][0],cycle[4][1],cycle[4][2]);
+
+      ret[layer][index[layer]] = new int[] {i0,i1,i2,i3,i4};
+      index[layer]++;
+      }
+
+    return ret;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private float whichLayerMegaminx(float[] point, float[] ax, int numLayers)
+    {
+    float d = point[0]*ax[0] + point[1]*ax[1] + point[2]*ax[2];
+    float C = 0.85f;
+
+    switch(numLayers)
+      {
+      case 2: return d<0 ? 0:1;
+      case 3: float D3 = 3*TouchControlDodecahedron.DIST3D;
+              float X3 = 2*D3/(2+SIN18);
+              float G3 = X3*(0.5f-MEGA_D);
+              float cut3 = -D3 + C*G3;
+              return d<-cut3 ? 0 : d<cut3 ? 1:2;
+      case 4: float D4 = 5*TouchControlDodecahedron.DIST3D;
+              float X4 = 2*D4/(2+SIN18);
+              float G4 = X4*0.25f;
+              float cut41 = -D4 + C*G4;
+              float cut42 = -D4 + (1+C)*G4;
+              return d<-cut41 ? 0 : d<-cut42 ? 1: d<cut42 ? 2: d<cut41 ? 3:4;
+      case 5: float D5 = 5*TouchControlDodecahedron.DIST3D;
+              float X5 = 2*D5/(2+SIN18);
+              float G5 = X5*(0.5f-MEGA_D)/2;
+              float cut51 = -D5 + C*G5;
+              float cut52 = -D5 + (1+C)*G5;
+              return d<-cut51 ? 0 : d<-cut52 ? 1: d<cut52 ? 2: d<cut51 ? 3:4;
+      }
+
+    return 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int rotateIndex5(int ax, int index)
+    {
+    float[] touch = getCubitTouchOfIndex(index);
+    QuatHelper.rotateVectorByQuat(mTmp, touch[0], touch[1], touch[2], 1.0f, mQuatsMegaminx[ax]);
+    return getIndexOfCubitTouch(mTmp[0],mTmp[1],mTmp[2]);
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private int getIndexOfCubitTouch(float x, float y, float z)
@@ -853,7 +1248,7 @@ public class ObjectSignature implements Comparable<ObjectSignature>
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private boolean areNeighbours(float dx, float dy, float dz)
+  private boolean areNeighboursCuboid(float dx, float dy, float dz)
     {
     return dx*dx+dy*dy+dz*dz < 1.01f;
     }
@@ -865,6 +1260,19 @@ public class ObjectSignature implements Comparable<ObjectSignature>
     return dx*dx+dy*dy+dz*dz < SQ6/4 + 0.01f;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private boolean areNeighboursMegaminx(int size, float dx, float dy, float dz)
+    {
+    float fact = size==2 ? 1.5f : (size==4 ? 1.25f : 1.0f);
+
+    dx /= fact;
+    dy /= fact;
+    dz /= fact;
+
+    return BandagedObjectMegaminx.isAdjacent(size,dx,dy,dz);
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private long getBit(int index)
diff --git a/src/main/java/org/distorted/objectlib/json/JsonReader.java b/src/main/java/org/distorted/objectlib/json/JsonReader.java
index 7551b3cd..f20916e6 100644
--- a/src/main/java/org/distorted/objectlib/json/JsonReader.java
+++ b/src/main/java/org/distorted/objectlib/json/JsonReader.java
@@ -10,6 +10,7 @@
 package org.distorted.objectlib.json;
 
 import static org.distorted.objectlib.objects.TwistyBandagedCuboid.OBJECT_NAME_CUBOID;
+import static org.distorted.objectlib.objects.TwistyBandagedMegaminx.OBJECT_NAME_MEGAMINX;
 import static org.distorted.objectlib.objects.TwistyBandagedPyraminx.OBJECT_NAME_PYRAMINX;
 import static org.distorted.objectlib.scrambling.ScrambleStateLocallyBandaged.MAX_SUPPORTED_SIZE;
 
@@ -99,7 +100,8 @@ public class JsonReader
       }
 
     if( longName.equals(OBJECT_NAME_CUBOID)   ||
-        longName.equals(OBJECT_NAME_PYRAMINX)  ) return new ObjectSignature(shortName,signature);
+        longName.equals(OBJECT_NAME_PYRAMINX) ||
+        longName.equals(OBJECT_NAME_MEGAMINX)  ) return new ObjectSignature(shortName,signature);
 
     return new ObjectSignature(signature);
     }
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyBandagedMegaminx.java b/src/main/java/org/distorted/objectlib/objects/TwistyBandagedMegaminx.java
index a142ed38..30528a54 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyBandagedMegaminx.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyBandagedMegaminx.java
@@ -28,9 +28,9 @@ import org.distorted.objectlib.scrambling.ObjectScrambler;
 
 public class TwistyBandagedMegaminx extends TwistyDodecahedron
 {
-  public static final int KILOMINX3 = 2;
-  public static final int MEGAMINX3 = 3;
-  public static final int KILOMINX5 = 4;
+  public static final int KILOMINX3 = 2; // don't change those values
+  public static final int MEGAMINX3 = 3; // ( see ObjectSignature.areNeighboursMegaminx() )
+  public static final int KILOMINX5 = 4; // ( and getShortName() here )
   public static final int MEGAMINX5 = 5;
 
   public static final String OBJECT_NAME_MEGAMINX = "LOCAL_MEGAMINX";
@@ -411,14 +411,13 @@ public class TwistyBandagedMegaminx extends TwistyDodecahedron
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// TODO
 
   public ObjectSignature getSignature()
     {
     if( mSignature==null )
       {
       int param = getInitData().getParam();
-      mSignature = new ObjectSignature(param,mPosition);
+      mSignature = new ObjectSignature(mPosition,param);
       }
     return mSignature;
     }
diff --git a/src/main/java/org/distorted/objectlib/scrambling/ObjectScrambler.java b/src/main/java/org/distorted/objectlib/scrambling/ObjectScrambler.java
index e7d51a56..9870dc70 100644
--- a/src/main/java/org/distorted/objectlib/scrambling/ObjectScrambler.java
+++ b/src/main/java/org/distorted/objectlib/scrambling/ObjectScrambler.java
@@ -617,7 +617,7 @@ public class ObjectScrambler
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// TYPE 2   (locally-created bandaged cuboids)
+// TYPE 2   (locally-created bandaged cuboids, pyraminxes & dodecahedrons)
 
   private void randomizeNewScramble2(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
     {
diff --git a/src/main/java/org/distorted/objectlib/scrambling/ScrambleStateLocallyBandaged.java b/src/main/java/org/distorted/objectlib/scrambling/ScrambleStateLocallyBandaged.java
index 8f613323..34bb6579 100644
--- a/src/main/java/org/distorted/objectlib/scrambling/ScrambleStateLocallyBandaged.java
+++ b/src/main/java/org/distorted/objectlib/scrambling/ScrambleStateLocallyBandaged.java
@@ -57,6 +57,15 @@ public class ScrambleStateLocallyBandaged
       mTurns[2] = 2;
       mTurns[3] = 2;
       }
+    else if( mNumAxis==6 )
+      {
+      mTurns[0] = 4;
+      mTurns[1] = 4;
+      mTurns[2] = 4;
+      mTurns[3] = 4;
+      mTurns[4] = 4;
+      mTurns[5] = 4;
+      }
 
     int numMoves = 0;
 
