commit bb11be2a31d503a3d96f175c3aa2061561000751
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Apr 19 23:51:53 2021 +0200

    New cubit engine: finish converting Kilominx & Megaminx.

diff --git a/src/main/java/org/distorted/helpers/FactoryCubit.java b/src/main/java/org/distorted/helpers/FactoryCubit.java
index bd630f5e..ac101273 100644
--- a/src/main/java/org/distorted/helpers/FactoryCubit.java
+++ b/src/main/java/org/distorted/helpers/FactoryCubit.java
@@ -41,8 +41,6 @@ import java.util.ArrayList;
 public class FactoryCubit
   {
   private static final float SQ2 = (float)Math.sqrt(2);
-  private static final float SQ5 = (float)Math.sqrt(5);
-
   private static final Static1D RADIUS = new Static1D(1);
   private static FactoryCubit mThis;
 
@@ -55,16 +53,6 @@ public class FactoryCubit
   // REX
   public static final float REX_D = 0.2f;
 
-  // KILO / MEGAMINX
-  public static final float SIN54    = (SQ5+1)/4;
-  public static final float COS54    = (float)(Math.sqrt(10-2*SQ5)/4);
-  public static final float SIN18    = (SQ5-1)/4;
-  public static final float COS18    = (float)(0.25f*Math.sqrt(10.0f+2.0f*SQ5));
-  public static final float COS_HALFD= (float)(Math.sqrt(0.5f-0.1f*SQ5)); // cos(half the dihedral angle)
-  public static final float SIN_HALFD= (float)(Math.sqrt(0.5f+0.1f*SQ5)); // sin(half the dihedral angle)
-  public static final float DIHEDRAL1= (float)(Math.acos(-SQ5/5)*180/Math.PI);
-  public static final float DIHEDRAL2= (float)((180/Math.PI)*Math.asin((2*SIN54*SIN54-1)/COS54) - 90);
-
   private static final double[] mBuffer = new double[3];
   private static final double[] mQuat1  = new double[4];
   private static final double[] mQuat2  = new double[4];
@@ -388,78 +376,6 @@ public class FactoryCubit
     return new MeshJoined(meshes);
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  MeshBase createFacesMegaminxEdge(int numLayers, float width, float height)
-    {
-    MeshBase[] meshes = new MeshPolygon[6];
-
-    float D = height/COS18;
-    float W = D*SIN18;
-
-    float Y1 = 0.5f*width;
-    float Y2 = 0.5f*width + W;
-    float Y3 = 0.5f*width + 2*W;
-    float X2 = D*SIN54;
-    float X1 = 0.5f*height;
-    float Y4 = D*COS54;
-
-    float[] vertices0 = { -X1, Y1, -X1, -Y1, X1, -Y2, X1, Y2 };
-    float[] vertices1 = { -X1, Y3, -X1, -Y3, X1, -Y2, X1, Y2 };
-    float[] vertices2 = { -X2, 0.0f, 0.0f, -Y4, X2, 0.0f, 0.0f, Y4 };
-
-    int numBands0 = numLayers==3 ? 5 : 3;
-    int numBands1 = numLayers==3 ? 2 : 2;
-    float h       = numLayers==3 ? 0.03f : 0.03f;
-
-    float[] bands0 = computeBands(h    ,34,0.2f,0.2f,numBands0);
-    float[] bands1 = computeBands(0.00f,34,0.3f,0.2f,numBands1);
-
-    meshes[0] = new MeshPolygon(vertices0, bands0, 0, 0);
-    meshes[0].setEffectAssociation(0, 1,0);
-    meshes[1] = meshes[0].copy(true);
-    meshes[1].setEffectAssociation(0, 2,0);
-    meshes[2] = new MeshPolygon(vertices1, bands1, 0, 0);
-    meshes[2].setEffectAssociation(0, 4,0);
-    meshes[3] = meshes[2].copy(true);
-    meshes[3].setEffectAssociation(0, 8,0);
-    meshes[4] = new MeshPolygon(vertices2, bands1, 0, 0);
-    meshes[4].setEffectAssociation(0,16,0);
-    meshes[5] = meshes[4].copy(true);
-    meshes[5].setEffectAssociation(0,32,0);
-
-    return new MeshJoined(meshes);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  MeshBase createFacesMegaminxCenter(int numLayers)
-    {
-    MeshBase[] meshes = new MeshPolygon[2];
-
-    float R  = 0.5f;
-    float X1 = R*COS54;
-    float Y1 = R*SIN54;
-    float X2 = R*COS18;
-    float Y2 = R*SIN18;
-
-    float[] vertices0 = { -X1,+Y1, -X2,-Y2, 0.0f,-R, +X2,-Y2, +X1,+Y1 };
-
-    int numBands0 = numLayers==3 ? 4 : 3;
-    int numBands1 = numLayers==3 ? 2 : 2;
-    float h       = numLayers==3 ? 0.04f : 0.04f;
-
-    float[] bands0 = computeBands( h    ,45, R/3,0.2f, numBands0);
-    float[] bands1 = computeBands( 0.00f,34, R/3,0.2f, numBands1);
-
-    meshes[0] = new MeshPolygon(vertices0, bands0, 0, 0);
-    meshes[0].setEffectAssociation(0,1,0);
-    meshes[1] = new MeshPolygon(vertices0, bands1, 0, 0);
-    meshes[1].setEffectAssociation(0,2,0);
-
-    return new MeshJoined(meshes);
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private float[] createVertices(int A, int B)
@@ -602,82 +518,6 @@ public class FactoryCubit
     return effect;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  VertexEffect[] createVertexEffectsMegaminxEdge(float width, float height)
-    {
-    VertexEffect[] effect = new VertexEffect[11];
-
-    float X = 0.5f*height;
-    float Y = height*(COS54/COS18) + width*0.5f;
-    float Z = 2*height*COS_HALFD;
-
-    float alpha = 90-DIHEDRAL1/2;
-    float beta  = DIHEDRAL2;
-
-    Static1D angle1 = new Static1D(alpha);
-    Static1D angle2 = new Static1D(180-alpha);
-    Static1D angle3 = new Static1D(beta);
-
-    Static3D move1 = new Static3D(X,0,0);
-    Static3D move2 = new Static3D(X,0,-Z);
-    Static3D move3 = new Static3D(0,+Y,0);
-    Static3D move4 = new Static3D(0,-Y,0);
-    Static3D scale = new Static3D(+1,+1,-1);
-
-    Static3D axisXplus = new Static3D(+1, 0, 0);
-    Static3D axisXminus= new Static3D(-1, 0, 0);
-    Static3D axisYplus = new Static3D( 0,+1, 0);
-    Static3D axisYminus= new Static3D( 0,-1, 0);
-
-    Static3D center1= new Static3D( 0, 0, 0);
-    Static3D center2= new Static3D( 0, 0,-Z);
-    Static3D center3= new Static3D( 0,+width*0.5f, 0);
-    Static3D center4= new Static3D( 0,-width*0.5f, 0);
-
-    effect[ 0] = new VertexEffectMove(move1);
-    effect[ 1] = new VertexEffectMove(move2);
-    effect[ 2] = new VertexEffectMove(move3);
-    effect[ 3] = new VertexEffectMove(move4);
-    effect[ 4] = new VertexEffectScale(scale);
-    effect[ 5] = new VertexEffectRotate(angle1, axisYplus , center1);
-    effect[ 6] = new VertexEffectRotate(angle2, axisYplus , center1);
-    effect[ 7] = new VertexEffectRotate(angle1, axisYminus, center2);
-    effect[ 8] = new VertexEffectRotate(angle2, axisYminus, center2);
-    effect[ 9] = new VertexEffectRotate(angle3, axisXplus , center3);
-    effect[10] = new VertexEffectRotate(angle3, axisXminus, center4);
-
-    effect[ 0].setMeshAssociation( 3,-1);  // meshes 0,1
-    effect[ 1].setMeshAssociation(12,-1);  // meshes 2,3
-    effect[ 2].setMeshAssociation(16,-1);  // mesh 4
-    effect[ 3].setMeshAssociation(32,-1);  // mesh 5
-    effect[ 4].setMeshAssociation( 2,-1);  // mesh 1
-    effect[ 5].setMeshAssociation( 1,-1);  // mesh 0
-    effect[ 6].setMeshAssociation( 2,-1);  // mesh 1
-    effect[ 7].setMeshAssociation( 4,-1);  // mesh 2
-    effect[ 8].setMeshAssociation( 8,-1);  // mesh 3
-    effect[ 9].setMeshAssociation(16,-1);  // mesh 4
-    effect[10].setMeshAssociation(32,-1);  // mesh 5
-
-    return effect;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  VertexEffect[] createVertexEffectsMegaminxCenter(float width)
-    {
-    VertexEffect[] effect = new VertexEffect[2];
-
-    Static1D angle = new Static1D(DIHEDRAL2);
-    Static3D axisX = new Static3D( 1.0f, 0.0f, 0.0f);
-    Static3D center= new Static3D( 0, 0, 0);
-
-    effect[0] = new VertexEffectScale(width/COS54);
-    effect[1] = new VertexEffectRotate(angle, axisX, center);
-
-    return effect;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   VertexEffect[] createCuboidEffects(int[] dimensions)
@@ -830,38 +670,6 @@ public class FactoryCubit
     return mesh;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// numLayers==3 --> index=0; numLayers=5 --> index=1 ...
-// type: 0,1,... 0 --> edge, 1 --> 1 layer deeper, etc
-
-  public MeshBase createMegaminxEdgeMesh(int numLayers, float width, float height)
-    {
-    MeshBase mesh = createFacesMegaminxEdge(numLayers,width,height);
-    VertexEffect[] effects = createVertexEffectsMegaminxEdge(width,height);
-    for( VertexEffect effect : effects ) mesh.apply(effect);
-
-    mesh.mergeEffComponents();
-
-    return mesh;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public MeshBase createMegaminxCenterMesh(int numLayers, float width)
-    {
-    MeshBase mesh = createFacesMegaminxCenter(numLayers);
-    VertexEffect[] effects = createVertexEffectsMegaminxCenter(width);
-    for( VertexEffect effect : effects ) mesh.apply(effect);
-
-    mesh.mergeEffComponents();
-    mesh.addEmptyTexComponent();
-    mesh.addEmptyTexComponent();
-    mesh.addEmptyTexComponent();
-    mesh.addEmptyTexComponent();
-
-    return mesh;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public MeshBase createCuboidMesh(int[] dimensions)
@@ -1535,8 +1343,6 @@ public class FactoryCubit
 
       mNewFaceTransf.add(newT);
       }
-
-    printStickerCoords();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/MovementMinx.java b/src/main/java/org/distorted/objects/MovementMinx.java
index 80ff2e91..b005f7e9 100644
--- a/src/main/java/org/distorted/objects/MovementMinx.java
+++ b/src/main/java/org/distorted/objects/MovementMinx.java
@@ -20,11 +20,10 @@
 package org.distorted.objects;
 
 import org.distorted.library.type.Static3D;
-import static org.distorted.objects.TwistyKilominx.C1;
-import static org.distorted.objects.TwistyKilominx.C2;
-import static org.distorted.objects.TwistyKilominx.LEN;
-import static org.distorted.helpers.FactoryCubit.SIN54;
-import static org.distorted.helpers.FactoryCubit.COS54;
+import static org.distorted.objects.TwistyMinx.C2;
+import static org.distorted.objects.TwistyMinx.LEN;
+import static org.distorted.objects.TwistyMinx.SIN54;
+import static org.distorted.objects.TwistyMinx.COS54;
 import static org.distorted.objects.TwistyObject.SQ5;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -36,18 +35,18 @@ class MovementMinx extends Movement
 
   static final Static3D[] FACE_AXIS = new Static3D[]
          {
-           new Static3D( C2/LEN, C1/LEN, 0      ),
-           new Static3D( C2/LEN,-C1/LEN, 0      ),
-           new Static3D(-C2/LEN, C1/LEN, 0      ),
-           new Static3D(-C2/LEN,-C1/LEN, 0      ),
-           new Static3D( 0     , C2/LEN, C1/LEN ),
-           new Static3D( 0     , C2/LEN,-C1/LEN ),
-           new Static3D( 0     ,-C2/LEN, C1/LEN ),
-           new Static3D( 0     ,-C2/LEN,-C1/LEN ),
-           new Static3D( C1/LEN, 0     , C2/LEN ),
-           new Static3D( C1/LEN, 0     ,-C2/LEN ),
-           new Static3D(-C1/LEN, 0     , C2/LEN ),
-           new Static3D(-C1/LEN, 0     ,-C2/LEN )
+           new Static3D(    C2/LEN, SIN54/LEN,    0      ),
+           new Static3D(    C2/LEN,-SIN54/LEN,    0      ),
+           new Static3D(   -C2/LEN, SIN54/LEN,    0      ),
+           new Static3D(   -C2/LEN,-SIN54/LEN,    0      ),
+           new Static3D( 0        ,    C2/LEN, SIN54/LEN ),
+           new Static3D( 0        ,    C2/LEN,-SIN54/LEN ),
+           new Static3D( 0        ,   -C2/LEN, SIN54/LEN ),
+           new Static3D( 0        ,   -C2/LEN,-SIN54/LEN ),
+           new Static3D( SIN54/LEN,    0     ,    C2/LEN ),
+           new Static3D( SIN54/LEN,    0     ,   -C2/LEN ),
+           new Static3D(-SIN54/LEN,    0     ,    C2/LEN ),
+           new Static3D(-SIN54/LEN,    0     ,   -C2/LEN )
          };
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyKilominx.java b/src/main/java/org/distorted/objects/TwistyKilominx.java
index 03f41af4..cef3ff0d 100644
--- a/src/main/java/org/distorted/objects/TwistyKilominx.java
+++ b/src/main/java/org/distorted/objects/TwistyKilominx.java
@@ -35,13 +35,6 @@ import org.distorted.library.type.Static4D;
 import org.distorted.main.R;
 import org.distorted.main.RubikSurfaceView;
 
-import static org.distorted.helpers.FactoryCubit.COS18;
-import static org.distorted.helpers.FactoryCubit.COS54;
-import static org.distorted.helpers.FactoryCubit.COS_HALFD;
-import static org.distorted.helpers.FactoryCubit.SIN18;
-import static org.distorted.helpers.FactoryCubit.SIN54;
-import static org.distorted.helpers.FactoryCubit.SIN_HALFD;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistyKilominx extends TwistyMinx
@@ -65,6 +58,15 @@ public class TwistyKilominx extends TwistyMinx
         2,2,2,2,2
       };
 
+  private static final float CENTER_CORR = 0.87f;
+
+  private static final float[][] STICKERS = new float[][]
+      {
+        { -0.36616942f, -0.36327124f, 0.5f, -0.36327124f, 0.23233888f, 0.4605048f, -0.36616942f, 0.26603764f },
+        { -0.36327127f, -0.5f, 0.36327127f, -0.26393202f, 0.36327127f, 0.5f, -0.36327127f, 0.26393202f },
+        { -0.3249197f, -0.39442718f, 0.3249197f, -0.39442718f, 0.3249197f, 0.5f, -0.3249197f, 0.2888544f }
+      };
+
   private static final int mNumCornerEdgeVariants;
 
   static
@@ -72,6 +74,9 @@ public class TwistyKilominx extends TwistyMinx
     int[] sizes = ObjectList.KILO.getSizes();
     int variants = sizes.length;
     mNumCornerEdgeVariants = sizes[0]==3 ? variants-1 : variants;
+
+    STICKERS[0][2] *= CENTER_CORR;
+    STICKERS[0][3] *= CENTER_CORR;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -116,7 +121,7 @@ public class TwistyKilominx extends TwistyMinx
     {
     float[] cuts = new float[numLayers-1];
     float D = numLayers*MovementMinx.DIST3D;
-    float E = 2*C1;           // 2*cos(36 deg)
+    float E = 2*SIN54;
     float X = 2*D*E/(1+2*E);  // height of the 'upper' part of a dodecahedron, i.e. put it on a table,
                               // its height is then D*2*DIST3D, it has one 'lower' part of height X, one
                               // 'middle' part of height Y and one upper part of height X again.
@@ -625,35 +630,26 @@ public class TwistyKilominx extends TwistyMinx
       {
       float R = 0.10f;
       float S = 0.09f;
-      float A = 0.87f;
-      float[] vertices = { -0.36616942f, -0.36327124f, 0.5f, -0.36327124f, 0.23233888f, 0.4605048f, -0.36616942f, 0.26603764f };
-
-      float cx = vertices[2];
-      float cy = vertices[3];
-      vertices[2] *= A;
-      vertices[3] *= A;
+      float cx = STICKERS[0][2]/CENTER_CORR;
+      float cy = STICKERS[0][3]/CENTER_CORR;
 
       FactorySticker factory = FactorySticker.getInstance();
-      factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face%NUM_FACES], R);
+      factory.drawRoundedPolygon(canvas, paint, left, top, STICKERS[0], S, FACE_COLORS[face%NUM_FACES], R);
       canvas.drawCircle(left+(0.5f+cx)*TEXTURE_HEIGHT, top+(0.5f-cy)*TEXTURE_HEIGHT, 0.05f*TEXTURE_HEIGHT, paint);
       }
     else if( variant==0 ) // corner
       {
       float R = 0.10f;
       float S = 0.11f;
-      float[] vertices = { -0.36327127f, -0.5f, 0.36327127f, -0.26393202f, 0.36327127f, 0.5f, -0.36327127f, 0.26393202f };
-
       FactorySticker factory = FactorySticker.getInstance();
-      factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face%COLORS], R);
+      factory.drawRoundedPolygon(canvas, paint, left, top, STICKERS[1], S, FACE_COLORS[face%COLORS], R);
       }
     else  // edge
       {
       float R = 0.10f;
       float S = 0.10f;
-      float[] vertices = { -0.3249197f, -0.39442718f, 0.3249197f, -0.39442718f, 0.3249197f, 0.5f, -0.3249197f, 0.2888544f };
-
       FactorySticker factory = FactorySticker.getInstance();
-      factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face%COLORS], R);
+      factory.drawRoundedPolygon(canvas, paint, left, top, STICKERS[2], S, FACE_COLORS[face%COLORS], R);
       }
     }
 
diff --git a/src/main/java/org/distorted/objects/TwistyMegaminx.java b/src/main/java/org/distorted/objects/TwistyMegaminx.java
index bee17265..940e8597 100644
--- a/src/main/java/org/distorted/objects/TwistyMegaminx.java
+++ b/src/main/java/org/distorted/objects/TwistyMegaminx.java
@@ -35,11 +35,6 @@ import org.distorted.library.type.Static4D;
 import org.distorted.main.R;
 import org.distorted.main.RubikSurfaceView;
 
-import static org.distorted.helpers.FactoryCubit.COS18;
-import static org.distorted.helpers.FactoryCubit.COS54;
-import static org.distorted.helpers.FactoryCubit.SIN18;
-import static org.distorted.helpers.FactoryCubit.SIN54;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistyMegaminx extends TwistyMinx
@@ -54,6 +49,15 @@ public class TwistyMegaminx extends TwistyMinx
   private static MeshBase[] mCenterMeshes, mCornerMeshes;
   private static MeshBase[][] mEdgeMeshes;
 
+  private static final float[][] STICKERS = new float[][]
+      {
+        { -0.36327127f, -0.5f, 0.36327127f, -0.26393202f, 0.36327127f, 0.5f, -0.36327127f, 0.26393202f },
+        { -0.5f, -0.0914315f, 0.5f, -0.4163512f, 0.5f, 0.4163512f, -0.5f, 0.0914315f },
+        { -0.49233657f, -0.18006028f, 0.49233657f, -0.5f, 0.49233657f, 0.5f, -0.49233657f, 0.18006028f },
+        { -0.3002273f, -0.30490047f, 0.3002273f, -0.5f, 0.3002273f, 0.5f, -0.3002273f, 0.30490047f },
+        { -0.29389262f, 0.4045085f, -0.47552824f, -0.1545085f, 0.0f, -0.5f, 0.47552824f, -0.1545085f, 0.29389262f, 0.4045085f }
+      };
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   TwistyMegaminx(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
@@ -96,7 +100,7 @@ public class TwistyMegaminx extends TwistyMinx
     {
     float[] cuts = new float[numLayers-1];
     float D = numLayers*MovementMinx.DIST3D;
-    float E = 2*C1;           // 2*cos(36 deg)
+    float E = 2*SIN54;
     float X = 2*D*E/(1+2*E);  // height of the 'upper' part of a dodecahedron, i.e. put it on a table,
                               // its height is then D*2*DIST3D, it has one 'lower' part of height X, one
                               // 'middle' part of height Y and one upper part of height X again.
@@ -266,6 +270,113 @@ public class TwistyMegaminx extends TwistyMinx
     return QUAT_CENTER_INDICES[center];
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  MeshBase createEdgeMesh(int numLayers, float width, float height)
+    {
+    double W = width/2;
+    double X = height*SIN_HALFD;
+    double Y = height*SIN18/COS18;
+    double Z = height*COS_HALFD;
+
+    double[][] vertices = new double[][]
+        {
+            { 0.0,   W   , 0.0 },
+            {   X, W+Y   ,  -Z },
+            { 0.0, W+2*Y ,-2*Z },
+            {  -X, W+Y   ,  -Z },
+            { 0.0,  -W   , 0.0 },
+            {   X,-W-Y   ,  -Z },
+            { 0.0,-W-2*Y ,-2*Z },
+            {  -X,-W-Y   ,  -Z },
+        };
+
+    int[][] vertIndexes = new int[][]
+        {
+            {4,5,1,0},
+            {7,4,0,3},
+            {7,6,2,3},
+            {6,5,1,2},
+            {0,1,2,3},
+            {4,5,6,7}
+        };
+
+    int N = numLayers<=5 ? 5 : 3;
+
+    float[][] bands     = new float[][]
+      {
+         {0.04f,34,0.2f,0.2f,N,0,0},
+         {0.00f, 0,0.3f,0.2f,2,0,0}
+      };
+    int[] bandIndexes   = new int[] { 0,0,1,1,1,1};
+    float[][] corners   = new float[][] { {0.04f,0.10f} };
+    int[] cornerIndexes = new int[] { -1,-1,-1,-1, -1,-1,-1,-1 };
+    float[][] centers   = new float[][] { {0.0f, 0.0f, (float)(-2*Z)} };
+    int[] centerIndexes = new int[] { -1,-1,-1,-1, -1,-1,-1,-1 };
+
+    FactoryCubit factory = FactoryCubit.getInstance();
+    factory.createNewFaceTransform(vertices,vertIndexes);
+
+    return factory.createRoundedSolid(vertices, vertIndexes,
+                                      bands, bandIndexes,
+                                      corners, cornerIndexes,
+                                      centers, centerIndexes,
+                                      getNumCubitFaces() );
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  MeshBase createCenterMesh(int numLayers, float width)
+    {
+    final double V = 0.83;   // ??
+    final double ANGLE = V*Math.PI;
+    final double cosA  = Math.cos(ANGLE);
+    final double sinA  = Math.sin(ANGLE);
+
+    float R  = 0.5f*width/COS54;
+    float X1 = R*COS54;
+    float Y1 = R*SIN54;
+    float X2 = R*COS18;
+    float Y2 = R*SIN18;
+
+    double[][] vertices = new double[][]
+      {
+          {-X1,+Y1*sinA, Y1*cosA},
+          {-X2,-Y2*sinA,-Y2*cosA},
+          {0.0f,-R*sinA, -R*cosA},
+          {+X2,-Y2*sinA,-Y2*cosA},
+          {+X1,+Y1*sinA, Y1*cosA}
+      };
+
+    int[][] vertIndexes = new int[][]
+      {
+          {0,1,2,3,4},
+          {0,1,2,3,4}
+      };
+
+    int N = numLayers==3 ? 4 : 3;
+
+    float[][] bands = new float[][]
+      {
+         {0.04f,45, R/3,0.2f,N,0,0},
+         {0.00f, 0, R/3,0.2f,2,0,0}
+      };
+    int[] bandIndexes   = new int[] { 0,1 };
+    float[][] corners   = new float[][] { {0.04f,0.10f} };
+    int[] cornerIndexes = new int[] { -1,-1,-1,-1, -1 };
+    float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
+    int[] centerIndexes = new int[] { -1,-1,-1,-1, -1 };
+
+    FactoryCubit factory = FactoryCubit.getInstance();
+    factory.createNewFaceTransform(vertices,vertIndexes);
+
+    return factory.createRoundedSolid(vertices, vertIndexes,
+                                      bands, bandIndexes,
+                                      corners, cornerIndexes,
+                                      centers, centerIndexes,
+                                      getNumCubitFaces() );
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   MeshBase createCubitMesh(int cubit, int numLayers)
@@ -299,7 +410,7 @@ public class TwistyMegaminx extends TwistyMinx
         float height= (numLayers/3.0f)*(0.5f-MEGA_D)*COS18/((numLayers-1)*0.5f);
         float width = (numLayers/3.0f)*2*MEGA_D + 2*type*height*SIN18/COS18;
 
-        mEdgeMeshes[index][type] = FactoryCubit.getInstance().createMegaminxEdgeMesh(numLayers,width,height);
+        mEdgeMeshes[index][type] = createEdgeMesh(numLayers,width,height);
         }
 
       mesh = mEdgeMeshes[index][type].copy(true);
@@ -309,7 +420,7 @@ public class TwistyMegaminx extends TwistyMinx
       if( mCenterMeshes[index]==null )
         {
         float width = 2 * (numLayers/3.0f) * (MEGA_D+(0.5f-MEGA_D)*SIN18);
-        mCenterMeshes[index] = FactoryCubit.getInstance().createMegaminxCenterMesh(numLayers,width);
+        mCenterMeshes[index] = createCenterMesh(numLayers,width);
         }
 
       mesh = mCenterMeshes[index].copy(true);
@@ -412,49 +523,27 @@ public class TwistyMegaminx extends TwistyMinx
     {
     int COLORS = FACE_COLORS.length;
     float R,S;
-    float[] vertices;
+    int index,variant = face/COLORS;
 
-    int variant = face/COLORS;
-
-    if( variant==0 )
-      {
-      R = 0.080f;
-      S = 0.10f;
-      vertices = new float[] { -0.36327127f, -0.5f, 0.36327127f, -0.26393202f, 0.36327127f, 0.5f, -0.36327127f, 0.26393202f };
-      }
+    if( variant==0 ) { R = 0.08f; S = 0.10f; index = 0; }
     else
       {
       int numLayers = getNumLayers();
-      float height= (numLayers/3.0f)*(0.5f-MEGA_D)*COS18/((numLayers-1)*0.5f);
-      float W = height*SIN18/COS18;
-      float width = (numLayers/3.0f)*2*MEGA_D + 2*(variant-1)*W;
 
       if( variant < (numLayers+1)/2 )
         {
-        float X1 = 0.5f*height;
-        float Y1 = 0.5f*width;
-        float Y2 = 0.5f*width + W;
-
-        R = 0.045f;
-        S = 0.055f;
-        vertices = new float[] { -X1, Y1, -X1, -Y1, X1, -Y2, X1, Y2 };
-        }
-      else
-        {
-        float Z  = 0.5f;
-        float X1 = Z*COS54;
-        float Y1 = Z*SIN54;
-        float X2 = Z*COS18;
-        float Y2 = Z*SIN18;
-
-        R = 0.09f;
-        S = 0.08f;
-        vertices = new float[] { -X1,+Y1, -X2,-Y2, 0.0f,-Z, +X2,-Y2, +X1,+Y1 };
+        if( numLayers==3 ) { R = 0.12f; S = 0.12f; index = 1; }
+        else
+          {
+          if( variant==1 ) { R = 0.12f; S = 0.12f; index = 2; }
+          else             { R = 0.08f; S = 0.08f; index = 3; }
+          }
         }
+      else { R = 0.10f; S = 0.07f; index = 4; }
       }
 
     FactorySticker factory = FactorySticker.getInstance();
-    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face%COLORS], R);
+    factory.drawRoundedPolygon(canvas, paint, left, top, STICKERS[index], S, FACE_COLORS[face%COLORS], R);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyMinx.java b/src/main/java/org/distorted/objects/TwistyMinx.java
index f5916397..4d98c6a6 100644
--- a/src/main/java/org/distorted/objects/TwistyMinx.java
+++ b/src/main/java/org/distorted/objects/TwistyMinx.java
@@ -31,12 +31,6 @@ import org.distorted.library.type.Static4D;
 
 import java.util.Random;
 
-import static org.distorted.helpers.FactoryCubit.COS18;
-import static org.distorted.helpers.FactoryCubit.COS_HALFD;
-import static org.distorted.helpers.FactoryCubit.SIN18;
-import static org.distorted.helpers.FactoryCubit.SIN54;
-import static org.distorted.helpers.FactoryCubit.SIN_HALFD;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 abstract class TwistyMinx extends TwistyObject
@@ -47,20 +41,24 @@ abstract class TwistyMinx extends TwistyObject
   static final int NUM_CENTERS = 12;
   static final int NUM_EDGES   = 30;
 
-  static final float C0 = (SQ5-1)/4;                       // cos(72 deg)
-  static final float C1 = (SQ5+1)/4;                       // cos(36 deg)
-  static final float C2 = (SQ5+3)/4;
-  static final float LEN= (float)(Math.sqrt(1.25f+0.5f*SQ5));
+  static final float C2       = (SQ5+3)/4;
+  static final float LEN      = (float)(Math.sqrt(1.25f+0.5f*SQ5));
+  static final float SIN54    = (SQ5+1)/4;
+  static final float COS54    = (float)(Math.sqrt(10-2*SQ5)/4);
+  static final float SIN18    = (SQ5-1)/4;
+  static final float COS18    = (float)(0.25f*Math.sqrt(10.0f+2.0f*SQ5));
+  static final float COS_HALFD= (float)(Math.sqrt(0.5f-0.1f*SQ5)); // cos(half the dihedral angle)
+  static final float SIN_HALFD= (float)(Math.sqrt(0.5f+0.1f*SQ5)); // sin(half the dihedral angle)
 
   // the six rotation axis of a Minx. Must be normalized.
   static final Static3D[] ROT_AXIS = new Static3D[]
          {
-           new Static3D( C2/LEN, C1/LEN, 0      ),
-           new Static3D(-C2/LEN, C1/LEN, 0      ),
-           new Static3D( 0     , C2/LEN, C1/LEN ),
-           new Static3D( 0     ,-C2/LEN, C1/LEN ),
-           new Static3D( C1/LEN, 0     , C2/LEN ),
-           new Static3D( C1/LEN, 0     ,-C2/LEN )
+           new Static3D(    C2/LEN, SIN54/LEN,    0      ),
+           new Static3D(   -C2/LEN, SIN54/LEN,    0      ),
+           new Static3D( 0        ,    C2/LEN, SIN54/LEN ),
+           new Static3D( 0        ,   -C2/LEN, SIN54/LEN ),
+           new Static3D( SIN54/LEN,    0     ,    C2/LEN ),
+           new Static3D( SIN54/LEN,    0     ,   -C2/LEN )
          };
 
   private static final int MINX_LGREEN = 0xff53aa00;
@@ -100,82 +98,82 @@ abstract class TwistyMinx extends TwistyObject
            new Static4D( -0.5f, -0.5f,  0.5f,  0.5f ),
            new Static4D( -0.5f, -0.5f, -0.5f,  0.5f ),
 
-           new Static4D(  0.5f,    C1,    C0,  0.0f ), // 12
-           new Static4D(  0.5f,    C1,   -C0,  0.0f ),
-           new Static4D(  0.5f,   -C1,    C0,  0.0f ),
-           new Static4D(  0.5f,   -C1,   -C0,  0.0f ),
-           new Static4D(    C0,  0.5f,    C1,  0.0f ),
-           new Static4D(    C0,  0.5f,   -C1,  0.0f ),
-           new Static4D(   -C0,  0.5f,    C1,  0.0f ),
-           new Static4D(   -C0,  0.5f,   -C1,  0.0f ),
-           new Static4D(    C1,    C0,  0.5f,  0.0f ),
-           new Static4D(    C1,   -C0,  0.5f,  0.0f ),
-           new Static4D(   -C1,    C0,  0.5f,  0.0f ),
-           new Static4D(   -C1,   -C0,  0.5f,  0.0f ),
-
-           new Static4D(  0.0f,    C0,    C1,  0.5f ), //24
-           new Static4D(  0.0f,    C0,   -C1,  0.5f ),
-           new Static4D(  0.0f,   -C0,    C1,  0.5f ),
-           new Static4D(  0.0f,   -C0,   -C1,  0.5f ),
-           new Static4D(    C0,    C1,  0.0f,  0.5f ),
-           new Static4D(    C0,   -C1,  0.0f,  0.5f ),
-           new Static4D(   -C0,    C1,  0.0f,  0.5f ),
-           new Static4D(   -C0,   -C1,  0.0f,  0.5f ),
-           new Static4D(    C1,  0.0f,    C0,  0.5f ),
-           new Static4D(    C1,  0.0f,   -C0,  0.5f ),
-           new Static4D(   -C1,  0.0f,    C0,  0.5f ),
-           new Static4D(   -C1,  0.0f,   -C0,  0.5f ),
-
-           new Static4D(  0.0f,    C1,  0.5f,    C0 ), //36
-           new Static4D(  0.0f,    C1, -0.5f,    C0 ),
-           new Static4D(  0.0f,   -C1,  0.5f,    C0 ),
-           new Static4D(  0.0f,   -C1, -0.5f,    C0 ),
-           new Static4D(  0.5f,  0.0f,    C1,    C0 ),
-           new Static4D(  0.5f,  0.0f,   -C1,    C0 ),
-           new Static4D( -0.5f,  0.0f,    C1,    C0 ),
-           new Static4D( -0.5f,  0.0f,   -C1,    C0 ),
-           new Static4D(    C1,  0.5f,  0.0f,    C0 ),
-           new Static4D(    C1, -0.5f,  0.0f,    C0 ),
-           new Static4D(   -C1,  0.5f,  0.0f,    C0 ),
-           new Static4D(   -C1, -0.5f,  0.0f,    C0 ),
-
-           new Static4D(  0.0f,  0.5f,    C0,    C1 ), //48
-           new Static4D(  0.0f,  0.5f,   -C0,    C1 ),
-           new Static4D(  0.0f, -0.5f,    C0,    C1 ),
-           new Static4D(  0.0f, -0.5f,   -C0,    C1 ),
-           new Static4D(  0.5f,    C0,  0.0f,    C1 ),
-           new Static4D(  0.5f,   -C0,  0.0f,    C1 ),
-           new Static4D( -0.5f,    C0,  0.0f,    C1 ),
-           new Static4D( -0.5f,   -C0,  0.0f,    C1 ),
-           new Static4D(    C0,  0.0f,  0.5f,    C1 ),
-           new Static4D(    C0,  0.0f, -0.5f,    C1 ),
-           new Static4D(   -C0,  0.0f,  0.5f,    C1 ),
-           new Static4D(   -C0,  0.0f, -0.5f,    C1 ),
+           new Static4D(  0.5f, SIN54, SIN18,  0.0f ), // 12
+           new Static4D(  0.5f, SIN54,-SIN18,  0.0f ),
+           new Static4D(  0.5f,-SIN54, SIN18,  0.0f ),
+           new Static4D(  0.5f,-SIN54,-SIN18,  0.0f ),
+           new Static4D( SIN18,  0.5f, SIN54,  0.0f ),
+           new Static4D( SIN18,  0.5f,-SIN54,  0.0f ),
+           new Static4D(-SIN18,  0.5f, SIN54,  0.0f ),
+           new Static4D(-SIN18,  0.5f,-SIN54,  0.0f ),
+           new Static4D( SIN54, SIN18,  0.5f,  0.0f ),
+           new Static4D( SIN54,-SIN18,  0.5f,  0.0f ),
+           new Static4D(-SIN54, SIN18,  0.5f,  0.0f ),
+           new Static4D(-SIN54,-SIN18,  0.5f,  0.0f ),
+
+           new Static4D(  0.0f, SIN18, SIN54,  0.5f ), //24
+           new Static4D(  0.0f, SIN18,-SIN54,  0.5f ),
+           new Static4D(  0.0f,-SIN18, SIN54,  0.5f ),
+           new Static4D(  0.0f,-SIN18,-SIN54,  0.5f ),
+           new Static4D( SIN18, SIN54,  0.0f,  0.5f ),
+           new Static4D( SIN18,-SIN54,  0.0f,  0.5f ),
+           new Static4D(-SIN18, SIN54,  0.0f,  0.5f ),
+           new Static4D(-SIN18,-SIN54,  0.0f,  0.5f ),
+           new Static4D( SIN54,  0.0f, SIN18,  0.5f ),
+           new Static4D( SIN54,  0.0f,-SIN18,  0.5f ),
+           new Static4D(-SIN54,  0.0f, SIN18,  0.5f ),
+           new Static4D(-SIN54,  0.0f,-SIN18,  0.5f ),
+
+           new Static4D(  0.0f, SIN54,  0.5f, SIN18 ), //36
+           new Static4D(  0.0f, SIN54, -0.5f, SIN18 ),
+           new Static4D(  0.0f,-SIN54,  0.5f, SIN18 ),
+           new Static4D(  0.0f,-SIN54, -0.5f, SIN18 ),
+           new Static4D(  0.5f,  0.0f, SIN54, SIN18 ),
+           new Static4D(  0.5f,  0.0f,-SIN54, SIN18 ),
+           new Static4D( -0.5f,  0.0f, SIN54, SIN18 ),
+           new Static4D( -0.5f,  0.0f,-SIN54, SIN18 ),
+           new Static4D( SIN54,  0.5f,  0.0f, SIN18 ),
+           new Static4D( SIN54, -0.5f,  0.0f, SIN18 ),
+           new Static4D(-SIN54,  0.5f,  0.0f, SIN18 ),
+           new Static4D(-SIN54, -0.5f,  0.0f, SIN18 ),
+
+           new Static4D(  0.0f,  0.5f, SIN18, SIN54 ), //48
+           new Static4D(  0.0f,  0.5f,-SIN18, SIN54 ),
+           new Static4D(  0.0f, -0.5f, SIN18, SIN54 ),
+           new Static4D(  0.0f, -0.5f,-SIN18, SIN54 ),
+           new Static4D(  0.5f, SIN18,  0.0f, SIN54 ),
+           new Static4D(  0.5f,-SIN18,  0.0f, SIN54 ),
+           new Static4D( -0.5f, SIN18,  0.0f, SIN54 ),
+           new Static4D( -0.5f,-SIN18,  0.0f, SIN54 ),
+           new Static4D( SIN18,  0.0f,  0.5f, SIN54 ),
+           new Static4D( SIN18,  0.0f, -0.5f, SIN54 ),
+           new Static4D(-SIN18,  0.0f,  0.5f, SIN54 ),
+           new Static4D(-SIN18,  0.0f, -0.5f, SIN54 ),
          };
 
   // Coordinates of all 20 corners of a Minx
   static final float[][] CORNERS = new float[][]
          {
-             { 0.0f, 0.5f,   C2},
-             { 0.0f, 0.5f,  -C2},
-             { 0.0f,-0.5f,   C2},
-             { 0.0f,-0.5f,  -C2},
-             {   C2, 0.0f, 0.5f},
-             {   C2, 0.0f,-0.5f},
-             {  -C2, 0.0f, 0.5f},
-             {  -C2, 0.0f,-0.5f},
-             { 0.5f,   C2, 0.0f},
-             { 0.5f,  -C2, 0.0f},
-             {-0.5f,   C2, 0.0f},
-             {-0.5f,  -C2, 0.0f},
-             {   C1,   C1,   C1},
-             {   C1,   C1,  -C1},
-             {   C1,  -C1,   C1},
-             {   C1,  -C1,  -C1},
-             {  -C1,   C1,   C1},
-             {  -C1,   C1,  -C1},
-             {  -C1,  -C1,   C1},
-             {  -C1,  -C1,  -C1},
+             {  0.0f,  0.5f,    C2},
+             {  0.0f,  0.5f,   -C2},
+             {  0.0f, -0.5f,    C2},
+             {  0.0f, -0.5f,   -C2},
+             {    C2,  0.0f,  0.5f},
+             {    C2,  0.0f, -0.5f},
+             {   -C2,  0.0f,  0.5f},
+             {   -C2,  0.0f, -0.5f},
+             {  0.5f,    C2,  0.0f},
+             {  0.5f,   -C2,  0.0f},
+             { -0.5f,    C2,  0.0f},
+             { -0.5f,   -C2,  0.0f},
+             { SIN54, SIN54, SIN54},
+             { SIN54, SIN54,-SIN54},
+             { SIN54,-SIN54, SIN54},
+             { SIN54,-SIN54,-SIN54},
+             {-SIN54, SIN54, SIN54},
+             {-SIN54, SIN54,-SIN54},
+             {-SIN54,-SIN54, SIN54},
+             {-SIN54,-SIN54,-SIN54},
          };
 
   static final int[][] mCornerFaceMap =
