commit 5e06e92f1b4431127330a974a2178127bb8b2c3b
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Apr 19 19:39:16 2021 +0200

    New cubit engine: convert Kiliminx & some Megaminx.

diff --git a/src/main/java/org/distorted/helpers/FactoryCubit.java b/src/main/java/org/distorted/helpers/FactoryCubit.java
index 17c89213..bd630f5e 100644
--- a/src/main/java/org/distorted/helpers/FactoryCubit.java
+++ b/src/main/java/org/distorted/helpers/FactoryCubit.java
@@ -41,7 +41,6 @@ import java.util.ArrayList;
 public class FactoryCubit
   {
   private static final float SQ2 = (float)Math.sqrt(2);
-  private static final float SQ3 = (float)Math.sqrt(3);
   private static final float SQ5 = (float)Math.sqrt(5);
 
   private static final Static1D RADIUS = new Static1D(1);
@@ -65,8 +64,6 @@ public class FactoryCubit
   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);
-  public static final float MINX_SC  = 0.5f;
-
 
   private static final double[] mBuffer = new double[3];
   private static final double[] mQuat1  = new double[4];
@@ -391,119 +388,6 @@ public class FactoryCubit
     return new MeshJoined(meshes);
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  MeshBase createFacesKilominxCenter()
-    {
-    MeshBase[] meshes = new MeshPolygon[6];
-
-    float X1= 0.5f*SIN54;
-    float Y1= 0.5f*SIN_HALFD;
-    float Y2= Y1 - 0.5f*COS54;
-    float H = 0.5f* SIN54 /COS54  ;
-    float X2= MINX_SC*H* SIN_HALFD;
-    float Y3= MINX_SC*H/(2*COS_HALFD);
-    float Y4= MINX_SC*H*(1/(2*COS_HALFD) - COS_HALFD);
-
-    float[] vertices0 = { -X1, Y2, 0, -Y1, X1, Y2, 0, Y1 };
-    float[] bands0 = computeBands(0.04f,17,0.3f,0.2f,5);
-    float[] vertices1 = { -X2, Y4, 0, -Y3, X2, Y4, 0, Y3 };
-    float[] bands1 = computeBands(0.00f, 0,0.25f,0.5f,2);
-
-    meshes[0] = new MeshPolygon(vertices0, bands0, 1, 1);
-    meshes[0].setEffectAssociation(0, 1,0);
-    meshes[1] = meshes[0].copy(true);
-    meshes[1].setEffectAssociation(0, 2,0);
-    meshes[2] = meshes[0].copy(true);
-    meshes[2].setEffectAssociation(0, 4,0);
-    meshes[3] = new MeshPolygon(vertices1, bands1, 0, 0);
-    meshes[3].setEffectAssociation(0, 8,0);
-    meshes[4] = meshes[3].copy(true);
-    meshes[4].setEffectAssociation(0,16,0);
-    meshes[5] = meshes[3].copy(true);
-    meshes[5].setEffectAssociation(0,32,0);
-
-    return new MeshJoined(meshes);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  MeshBase createFacesMinxCorner(int numLayers)
-    {
-    MeshBase[] meshes = new MeshPolygon[6];
-
-    float Y = COS54/(2*SIN54);
-
-    float[] vertices0 = { -0.5f, 0.0f, 0.0f, -Y, 0.5f, 0.0f, 0.0f, Y };
-
-    int numBands0 = numLayers==3 ? 5 : 3;
-    int numBands1 = numLayers==3 ? 2 : 2;
-    float h       = numLayers==3 ? 0.04f : 0.03f;
-    int   e       = numLayers==3 ? 4 : 1;
-
-    float[] bands0 = computeBands(h    ,34,0.3f,0.2f, numBands0);
-    float[] bands1 = computeBands(0.00f,34,0.3f,0.2f, numBands1);
-
-    meshes[0] = new MeshPolygon(vertices0, bands0, 1, 1);
-    meshes[0].setEffectAssociation(0, 1,0);
-    meshes[1] = meshes[0].copy(true);
-    meshes[1].setEffectAssociation(0, 2,0);
-    meshes[2] = meshes[0].copy(true);
-    meshes[2].setEffectAssociation(0, 4,0);
-    meshes[3] = new MeshPolygon(vertices0, bands1, 1, e);
-    meshes[3].setEffectAssociation(0, 8,0);
-    meshes[4] = meshes[3].copy(true);
-    meshes[4].setEffectAssociation(0,16,0);
-    meshes[5] = meshes[3].copy(true);
-    meshes[5].setEffectAssociation(0,32,0);
-
-    return new MeshJoined(meshes);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  MeshBase createFacesKilominxEdge(int numLayers, float width, float height)
-    {
-     MeshBase[] meshes = new MeshPolygon[6];
-
-    float D = height/COS18;
-    float W = D*SIN18;
-    float X1 = height/2;
-    float Y1 = width/2;
-    float Y2 = (width+W)/2;
-    float X3 = D*SIN54;
-    float Y3 = D*COS54;
-    float X4 = height*SIN_HALFD;
-    float Y4 = height*COS_HALFD;
-
-    float[] vertices0 = { -X1,-Y1, X1, -Y1, X1, Y1+W,-X1, Y1 };
-    float[] vertices1 = { -X1,-Y2, X1, -Y2, X1, Y2+W,-X1, Y2 };
-    float[] vertices2 = { -X3, 0.0f, 0.0f, -Y3, X3, 0.0f, 0.0f, Y3 };
-    float[] vertices3 = { -X4, 0.0f, 0.0f, -Y4, X4, 0.0f, 0.0f, Y4 };
-
-    int numBands0 = numLayers<=5 ? 5 : 3;
-    int numBands1 = numLayers<=5 ? 3 : 2;
-    float h       = numLayers<=5 ? 0.03f : 0.03f;
-
-    float[] bands0 = computeBands(h    ,34,0.2f,0.2f,numBands0);
-    float[] bands1 = computeBands(0.01f,34,0.3f,0.2f,numBands1);
-
-    meshes[0] = new MeshPolygon(vertices0, bands0, 1, 1);
-    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] = new MeshPolygon(vertices3, bands1, 0, 0);
-    meshes[5].setEffectAssociation(0,32,0);
-
-    return new MeshJoined(meshes);
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   MeshBase createFacesMegaminxEdge(int numLayers, float width, float height)
@@ -718,174 +602,6 @@ public class FactoryCubit
     return effect;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  VertexEffect[] createVertexEffectsKilominxCenter(float width)
-    {
-    VertexEffect[] effect = new VertexEffect[11];
-
-    float H = 0.5f*(SIN54/COS54);
-    float Y1= 0.5f*SIN_HALFD;
-    float Y2= H/(2*COS_HALFD);
-    float cos18 = (float)(Math.sqrt(1- SIN18 * SIN18));
-    float LEN   = (float)Math.sqrt(H*H/(COS_HALFD*COS_HALFD) + 0.25f);
-
-    Static3D axisZ = new Static3D(0.0f  , 0.0f , 1.0f);
-    Static3D axisY = new Static3D(0.0f  , 1.0f , 0.0f);
-    Static3D axisA = new Static3D(-SIN18, cos18, 0.0f);
-    Static3D axisC = new Static3D( H/LEN, -0.5f/LEN,-H* SIN_HALFD /(COS_HALFD*LEN));
-
-    Static3D move1 = new Static3D(0,-Y1,0);
-    Static3D move2 = new Static3D(0,-Y2,0);
-    Static3D move3 = new Static3D(0.5f*cos18,0.5f*SIN18,0);
-    Static3D center= new Static3D(0.0f, 0.0f, 0.0f);
-
-    Static1D angle1 = new Static1D(54);
-    Static1D angle2 = new Static1D(DIHEDRAL1/2+18);
-    Static1D angle3 = new Static1D(90);
-    Static1D angle4 = new Static1D(120);
-    Static1D angle5 = new Static1D(240);
-    Static1D angle6 = new Static1D(90-DIHEDRAL1/2);
-
-    effect[0] = new VertexEffectMove(move1);
-    effect[1] = new VertexEffectScale(1/MINX_SC);
-    effect[2] = new VertexEffectMove(move2);
-    effect[3] = new VertexEffectRotate(angle1, axisZ, center);
-    effect[4] = new VertexEffectRotate(angle2, axisZ, center);
-    effect[5] = new VertexEffectRotate(angle3, axisA, center);
-    effect[6] = new VertexEffectMove(move3);
-    effect[7] = new VertexEffectRotate(angle4, axisC, center);
-    effect[8] = new VertexEffectRotate(angle5, axisC, center);
-    effect[9] = new VertexEffectRotate(angle6, axisY, center);
-    effect[10]= new VertexEffectScale(width/0.5f);
-
-    effect[0].setMeshAssociation( 7,-1);  // meshes 0,1,2
-    effect[1].setMeshAssociation(56,-1);  // meshes 3,4,5
-    effect[2].setMeshAssociation(56,-1);  // meshes 3,4,5
-    effect[3].setMeshAssociation( 7,-1);  // meshes 0,1,2
-    effect[4].setMeshAssociation(56,-1);  // meshes 3,4,5
-    effect[5].setMeshAssociation(56,-1);  // meshes 3,4,5
-    effect[6].setMeshAssociation(56,-1);  // meshes 3,4,5
-    effect[7].setMeshAssociation(18,-1);  // meshes 1,4
-    effect[8].setMeshAssociation(36,-1);  // meshes 2,5
-
-    return effect;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  VertexEffect[] createVertexEffectsMinxCorner(float width)
-    {
-    VertexEffect[] effect = new VertexEffect[9];
-
-    float Y = COS54/(2*SIN54);
-
-    float sinA = (2*SIN54*SIN54-1)/COS54;
-    float cosA = (float)Math.sqrt(1-sinA*sinA);
-    float LEN  = 0.5f/SIN54;
-    float scale= width/LEN;
-
-    Static3D axisA = new Static3D( SIN54, COS54, 0.0f);
-    Static3D axisB = new Static3D(-SIN54, COS54, 0.0f);
-    Static3D axisX = new Static3D(  1.0f,  0.0f, 0.0f);
-
-    Static3D centerU = new Static3D( 0.0f, Y, 0.0f);
-    Static3D centerD = new Static3D( 0.0f,-Y, 0.0f);
-
-    Static3D move1= new Static3D(0.0f, -sinA*LEN, -cosA*LEN );
-    Static3D move2= new Static3D(0.0f, Y , 0.0f );
-
-    Static1D angleD = new Static1D(DIHEDRAL1);
-    Static1D angleE = new Static1D(360-DIHEDRAL1);
-    Static1D angleF = new Static1D(DIHEDRAL2);
-
-    effect[0] = new VertexEffectScale ( new Static3D( 1, 1,-1) );
-    effect[1] = new VertexEffectRotate(angleE, axisA, centerU);
-    effect[2] = new VertexEffectRotate(angleD, axisB, centerU);
-    effect[3] = new VertexEffectMove(move1);
-    effect[4] = new VertexEffectRotate(angleE, axisA, centerD);
-    effect[5] = new VertexEffectRotate(angleD, axisB, centerD);
-    effect[6] = new VertexEffectRotate(angleF, axisX, centerD);
-    effect[7] = new VertexEffectMove(move2);
-    effect[8] = new VertexEffectScale(scale);
-
-    effect[0].setMeshAssociation(  3,-1);  // meshes 0,1
-    effect[1].setMeshAssociation( 16,-1);  // mesh 4
-    effect[2].setMeshAssociation( 32,-1);  // mesh 5
-    effect[3].setMeshAssociation( 56,-1);  // meshes 3,4,5
-    effect[4].setMeshAssociation(  1,-1);  // mesh 0
-    effect[5].setMeshAssociation(  2,-1);  // mesh 1
-
-    return effect;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  VertexEffect[] createVertexEffectsKilominxEdge(float width, float height, boolean left)
-    {
-    VertexEffect[] effect = new VertexEffect[11 + (left ? 0:1)];
-
-    float D = height/COS18;
-    float W = D*SIN18;
-    float X1 = height/2;
-    float Y1 = width/2;
-    float Y2 = (width+W)/2;
-    float Y3 = D*COS54;
-    float Y4 = height*COS_HALFD;
-    float Z = 2*height*COS_HALFD;
-    float alpha = 90-DIHEDRAL1/2;
-
-    Static1D angle1 = new Static1D(alpha);
-    Static1D angle2 = new Static1D(180-alpha);
-    Static1D angle3 = new Static1D(DIHEDRAL2);
-    Static1D angle4 = new Static1D(90);
-
-    Static3D move1 = new Static3D(+X1,-Y1,0);
-    Static3D move2 = new Static3D(-X1,-Y2+W,-Z);
-    Static3D move3 = new Static3D(0,+Y3,0);
-    Static3D move4 = new Static3D(0,-Y4-width,0);
-    Static3D scale = new Static3D(+1,+1,-1);
-
-    Static3D axisXplus = new Static3D(+1, 0, 0);
-    Static3D axisYplus = 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);
-
-    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, axisYplus , center2);
-    effect[ 8] = new VertexEffectRotate(angle2, axisYplus , center2);
-    effect[ 9] = new VertexEffectRotate(angle3, axisXplus , center1);
-    effect[10] = new VertexEffectRotate(angle4, axisXplus , center3);
-
-    if( !left )
-      {
-      Static3D scale1 = new Static3D(+1,-1,+1);
-      effect[11] = new VertexEffectScale(scale1);
-      }
-
-    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[] createVertexEffectsMegaminxEdge(float width, float height)
@@ -1114,83 +830,6 @@ public class FactoryCubit
     return mesh;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public MeshBase createKilominxCenterMesh(float width)
-    {
-    MeshBase mesh = createFacesKilominxCenter();
-    VertexEffect[] effects = createVertexEffectsKilominxCenter(width);
-    for( VertexEffect effect : effects ) mesh.apply(effect);
-
-    float A = (2*SQ3/3)* SIN54;
-    float B = 0.4f;
-    float X = SIN_HALFD * SIN54 *COS54  ;
-    float Y = SIN54 * SIN54 - 0.5f;
-    float Z = COS_HALFD* SIN54 *COS54  ;
-
-    Static3D center = new Static3D(0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B);
-
-    Static3D[] vertices = new Static3D[4];
-    vertices[0] = new Static3D( 0.0f, 0.0f, 0.0f);
-    vertices[1] = new Static3D( 0.0f,-0.5f, 0.0f);
-    vertices[2] = new Static3D(-X   , Y   ,-Z   );
-    vertices[3] = new Static3D(+X   , Y   ,-Z   );
-
-    roundCorners(mesh,center,vertices,0.03f,0.10f);
-
-    mesh.mergeEffComponents();
-
-    return mesh;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// numLayers==3 --> index=0; numLayers=5 --> index=1 ...
-// type: 0,1,... 0 --> edge, 1 --> 1 layer deeper, etc
-
-  public MeshBase createKilominxEdgeMesh(int numLayers, float width, float height, boolean left)
-    {
-    MeshBase mesh = createFacesKilominxEdge(numLayers,width,height);
-    VertexEffect[] effects = createVertexEffectsKilominxEdge(width,height,left);
-    for( VertexEffect effect : effects ) mesh.apply(effect);
-
-// round...
-
-    mesh.mergeEffComponents();
-
-    return mesh;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public MeshBase createMinxCornerMesh(int numLayers, float width)
-    {
-    MeshBase mesh = createFacesMinxCorner(numLayers);
-    VertexEffect[] effects = createVertexEffectsMinxCorner(width);
-    for( VertexEffect effect : effects ) mesh.apply(effect);
-
-    float A = (2*SQ3/3)* SIN54;
-    float B = 0.4f;
-/*
-    float X = SIN_HALFD* SIN54 * COS54;
-    float Y = SIN54 * SIN54 - 0.5f;
-    float Z = COS_HALFD* SIN54 * COS54;
-    float S = 2*width;
-*/
-    Static3D center = new Static3D(0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B);
-    Static3D[] vertices = new Static3D[1];
-    vertices[0] = new Static3D( 0.0f, 0.0f  , 0.0f);
-/*
-    vertices[1] = new Static3D( 0.0f,-0.5f*S, 0.0f);
-    vertices[2] = new Static3D(-X*S , Y*S   ,-Z*S );
-    vertices[3] = new Static3D(+X*S , Y*S   ,-Z*S );
-*/
-    roundCorners(mesh,center,vertices,0.04f,0.10f);
-
-    mesh.mergeEffComponents();
-
-    return mesh;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // numLayers==3 --> index=0; numLayers=5 --> index=1 ...
 // type: 0,1,... 0 --> edge, 1 --> 1 layer deeper, etc
@@ -1278,9 +917,6 @@ public class FactoryCubit
     return mesh;
     }
 
-
-
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private boolean areColinear(double[][] vertices, int index1, int index2, int index3)
@@ -1899,6 +1535,8 @@ public class FactoryCubit
 
       mNewFaceTransf.add(newT);
       }
+
+    printStickerCoords();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyBandaged2Bar.java b/src/main/java/org/distorted/objects/TwistyBandaged2Bar.java
index 2e87a4a5..1ac8bcba 100644
--- a/src/main/java/org/distorted/objects/TwistyBandaged2Bar.java
+++ b/src/main/java/org/distorted/objects/TwistyBandaged2Bar.java
@@ -69,13 +69,6 @@ class TwistyBandaged2Bar extends TwistyBandagedAbstract
     super(size, quat, texture, mesh, effects, moves, ObjectList.BAN2, res, scrWidth);
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  int getNumCubitTypes(int numLayers)
-    {
-    return 2;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   float[][] getPositions()
diff --git a/src/main/java/org/distorted/objects/TwistyKilominx.java b/src/main/java/org/distorted/objects/TwistyKilominx.java
index 34befa71..03f41af4 100644
--- a/src/main/java/org/distorted/objects/TwistyKilominx.java
+++ b/src/main/java/org/distorted/objects/TwistyKilominx.java
@@ -37,8 +37,10 @@ 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;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -323,6 +325,138 @@ public class TwistyKilominx extends TwistyMinx
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private MeshBase createCenterMesh(float width)
+    {
+    double X = width*COS18*SIN_HALFD;
+    double Y = width*SIN18;
+    double Z = width*COS18*COS_HALFD;
+    double H = width*(SIN54/COS54);
+    double H3= H/COS_HALFD;
+    double X3= H*SIN_HALFD;
+    double Z3= H*COS_HALFD;;
+    double C = 1/(COS54*Math.sqrt(2-2*SIN18));
+
+    double[][] vertices = new double[][]
+        {
+            { 0.0, 0.0  ,   0.0 },
+            {   X,   Y  ,    -Z },
+            { 0.0,C*2*Y ,-2*C*Z },
+            {  -X,   Y  ,    -Z },
+            { 0.0,-width,   0.0 },
+            {  X3,-width,   -Z3 },
+            { 0.0,-width,   -H3 },
+            { -X3,-width,   -Z3 }
+        };
+
+    int[][] vertIndexes = new int[][]
+        {
+            {4,5,1,0},
+            {7,4,0,3},
+            {0,1,2,3},
+            {7,6,2,3},
+            {6,5,1,2},
+            {4,5,6,7}
+        };
+
+    float[][] bands     = new float[][]
+      {
+         {0.04f,17,0.3f,0.2f,5,1,1},
+         {0.00f, 0,0.0f,0.5f,2,0,0}
+      };
+
+    float A = (2*SQ3/3)*SIN54;
+    float B = 0.4f;
+
+    int[] bandIndexes   = new int[] { 0,0,0,1,1,1};
+    float[][] corners   = new float[][] { {0.03f,0.10f} };
+    int[] cornerIndexes = new int[] { 0, 0,-1, 0, 0,-1,-1,-1 };
+    float[][] centers   = new float[][] { {0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B} };
+    int[] centerIndexes = new int[] { 0, 0,-1, 0, 0,-1,-1,-1 };
+
+    FactoryCubit factory = FactoryCubit.getInstance();
+    factory.createNewFaceTransform(vertices,vertIndexes);
+
+    return factory.createRoundedSolid(vertices, vertIndexes,
+                                      bands, bandIndexes,
+                                      corners, cornerIndexes,
+                                      centers, centerIndexes,
+                                      getNumCubitFaces() );
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private MeshBase createEdgeMesh(int numLayers, float width, float height, boolean left)
+    {
+    double X = height*SIN_HALFD;
+    double Y = height*SIN18/COS18;
+    double Z = height*COS_HALFD;
+
+    double[][] vertices = new double[][]
+        {
+            { 0.0, 0.0   , 0.0 },
+            {   X,   Y   ,  -Z },
+            { 0.0, 2*Y   ,-2*Z },
+            {  -X,   Y   ,  -Z },
+            { 0.0, -width, 0.0 },
+            {   X, -width,  -Z },
+            { 0.0, -width,-2*Z },
+            {  -X, -width,  -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}
+        };
+
+    if( !left )
+      {
+      int tmp, len = vertices.length;
+      for(int i=0; i<len; i++) vertices[i][1] = -vertices[i][1];
+
+      len = vertIndexes.length;
+      for(int i=0; i<len; i++)
+        {
+        tmp = vertIndexes[i][0];
+        vertIndexes[i][0] = vertIndexes[i][3];
+        vertIndexes[i][3] = tmp;
+
+        tmp = vertIndexes[i][1];
+        vertIndexes[i][1] = vertIndexes[i][2];
+        vertIndexes[i][2] = tmp;
+        }
+      }
+
+    int numBands0 = numLayers<=5 ? 5 : 3;
+    int numBands1 = numLayers<=5 ? 3 : 2;
+
+    float[][] bands     = new float[][]
+      {
+         {0.04f,34,0.2f,0.2f,numBands0,1,1},
+         {0.00f, 0,0.0f,0.0f,numBands1,0,0}
+      };
+    int[] bandIndexes   = new int[] { 0,0,1,1,1,1};
+    float[][] corners   = new float[][] { {0.04f,0.10f} };
+    int[] cornerIndexes = new int[] { 0,-1,-1,-1, 0,-1,-1,-1 };
+    float[][] centers   = new float[][] { {0.0f, -width/2, (float)(-2*Z)} };
+    int[] centerIndexes = new int[] { 0,-1,-1,-1, 0,-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)
@@ -349,7 +483,7 @@ public class TwistyKilominx extends TwistyMinx
       if( mCornerMeshes[indexCornerEdge]==null )
         {
         float width = (numLayers/3.0f)/(numLayers-1);
-        mCornerMeshes[indexCornerEdge] = FactoryCubit.getInstance().createMinxCornerMesh(numLayers,width);
+        mCornerMeshes[indexCornerEdge] = createCornerMesh(numLayers,width);
         }
       mesh = mCornerMeshes[indexCornerEdge].copy(true);
       }
@@ -363,7 +497,7 @@ public class TwistyKilominx extends TwistyMinx
         float height= tmp*COS18;
         float width = tmp + (type/2)*tmp*SIN18;
 
-        mEdgeMeshes[indexCornerEdge][type] = FactoryCubit.getInstance().createKilominxEdgeMesh(numLayers,width,height, (type%2)==0 );
+        mEdgeMeshes[indexCornerEdge][type] = createEdgeMesh(numLayers,width,height, (type%2)==0 );
         }
 
       mesh = mEdgeMeshes[indexCornerEdge][type].copy(true);
@@ -375,7 +509,7 @@ public class TwistyKilominx extends TwistyMinx
       if( mCenterMeshes[indexCenter]==null )
         {
         float width = (1+0.5f*(numLayers-3)*SIN18)*(numLayers/3.0f)/(numLayers-1);
-        mCenterMeshes[indexCenter] = FactoryCubit.getInstance().createKilominxCenterMesh(width);
+        mCenterMeshes[indexCenter] = createCenterMesh(width);
         }
 
       mesh = mCenterMeshes[indexCenter].copy(true);
@@ -487,49 +621,36 @@ public class TwistyKilominx extends TwistyMinx
     int variant = face/COLORS;
     int numLayers = getNumLayers();
 
-    if( variant == (numLayers-1)/2 || numLayers==3 )
+    if( variant == (numLayers-1)/2 || numLayers==3 ) // center
       {
-      float S = 0.07f;
-      float R = 0.09f;
-
-      float A = 0.86f;
-      float X1= (SQ5+1)/8;
-      float Y1= (float)(Math.sqrt(2+0.4f*SQ5)/4);
-      float Y2= Y1 - (float)(Math.sqrt(10-2*SQ5)/8);
+      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[] vertices = { -X1, Y2, 0, -A*Y1, X1, Y2, 0, Y1 };
+      float cx = vertices[2];
+      float cy = vertices[3];
+      vertices[2] *= A;
+      vertices[3] *= A;
 
       FactorySticker factory = FactorySticker.getInstance();
       factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face%NUM_FACES], R);
-
-      float MID = TEXTURE_HEIGHT*0.5f;
-      float WID = TEXTURE_HEIGHT*0.1f;
-      float HEI = TEXTURE_HEIGHT*(0.47f+Y1);
-      canvas.drawLine(left+MID-WID,top+HEI,left+MID+WID,top+HEI,paint);
+      canvas.drawCircle(left+(0.5f+cx)*TEXTURE_HEIGHT, top+(0.5f-cy)*TEXTURE_HEIGHT, 0.05f*TEXTURE_HEIGHT, paint);
       }
-    else if( variant==0 )
+    else if( variant==0 ) // corner
       {
-      float Y = COS54/(2*SIN54);
-      float R = 0.09f;
-      float S = 0.09f;
-      float[] vertices = { -0.5f, 0.0f, 0.0f, -Y, 0.5f, 0.0f, 0.0f, Y };
+      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);
       }
-    else
+    else  // edge
       {
-      float R = 0.07f;
-      float S = 0.07f;
-
-      float tmp   = (numLayers/3.0f)/(numLayers-1);
-      float height= tmp*COS18;
-      float width = tmp + (variant-1)*tmp*SIN18;
-      float D = height/COS18;
-      float W = D*SIN18;
-      float X1 = height/2;
-      float Y1 = width/2;
-      float[] vertices = { -X1,-Y1, X1, -Y1, X1, Y1+W,-X1, Y1 };
+      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);
diff --git a/src/main/java/org/distorted/objects/TwistyMegaminx.java b/src/main/java/org/distorted/objects/TwistyMegaminx.java
index 66372391..bee17265 100644
--- a/src/main/java/org/distorted/objects/TwistyMegaminx.java
+++ b/src/main/java/org/distorted/objects/TwistyMegaminx.java
@@ -286,7 +286,7 @@ public class TwistyMegaminx extends TwistyMinx
       if( mCornerMeshes[index]==null )
         {
         float width = (numLayers/3.0f)*(0.5f-MEGA_D)/(0.5f*(numLayers-1));
-        mCornerMeshes[index] = FactoryCubit.getInstance().createMinxCornerMesh(numLayers, width);
+        mCornerMeshes[index] = createCornerMesh(numLayers, width);
         }
       mesh = mCornerMeshes[index].copy(true);
       }
@@ -418,10 +418,9 @@ public class TwistyMegaminx extends TwistyMinx
 
     if( variant==0 )
       {
-      float Y = COS54/(2*SIN54);
-      R = 0.070f;
-      S = 0.08f;
-      vertices = new float[] { -0.5f, 0.0f, 0.0f, -Y, 0.5f, 0.0f, 0.0f, Y };
+      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 };
       }
     else
       {
@@ -436,8 +435,8 @@ public class TwistyMegaminx extends TwistyMinx
         float Y1 = 0.5f*width;
         float Y2 = 0.5f*width + W;
 
-        R = 0.05f;
-        S = 0.06f;
+        R = 0.045f;
+        S = 0.055f;
         vertices = new float[] { -X1, Y1, -X1, -Y1, X1, -Y2, X1, Y2 };
         }
       else
@@ -448,7 +447,7 @@ public class TwistyMegaminx extends TwistyMinx
         float X2 = Z*COS18;
         float Y2 = Z*SIN18;
 
-        R = 0.10f;
+        R = 0.09f;
         S = 0.08f;
         vertices = new float[] { -X1,+Y1, -X2,-Y2, 0.0f,-Z, +X2,-Y2, +X1,+Y1 };
         }
diff --git a/src/main/java/org/distorted/objects/TwistyMinx.java b/src/main/java/org/distorted/objects/TwistyMinx.java
index 5e96a9e2..f5916397 100644
--- a/src/main/java/org/distorted/objects/TwistyMinx.java
+++ b/src/main/java/org/distorted/objects/TwistyMinx.java
@@ -21,14 +21,22 @@ package org.distorted.objects;
 
 import android.content.res.Resources;
 
+import org.distorted.helpers.FactoryCubit;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedTexture;
+import org.distorted.library.mesh.MeshBase;
 import org.distorted.library.mesh.MeshSquare;
 import org.distorted.library.type.Static3D;
 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
@@ -376,6 +384,62 @@ abstract class TwistyMinx extends TwistyObject
     return chances;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  MeshBase createCornerMesh(int numLayers, float width)
+    {
+    float A = (2*SQ3/3)*SIN54;
+    float B = 0.4f;
+    int   N = numLayers==3 ? 5 : 3;
+    int   E = numLayers==3 ? 4 : 1;
+
+    double X = width*COS18*SIN_HALFD;
+    double Y = width*SIN18;
+    double Z = width*COS18*COS_HALFD;
+
+    double[][] vertices = new double[][]
+        {
+            { 0.0, 0.0      , 0.0 },
+            {   X,   Y      ,  -Z },
+            { 0.0, 2*Y      ,-2*Z },
+            {  -X,   Y      ,  -Z },
+            { 0.0, 0.0-width, 0.0 },
+            {   X,   Y-width,  -Z },
+            { 0.0, 2*Y-width,-2*Z },
+            {  -X,   Y-width,  -Z },
+        };
+
+    int[][] vertIndexes = new int[][]
+        {
+            {4,5,1,0},
+            {7,4,0,3},
+            {0,1,2,3},
+            {4,5,6,7},
+            {6,5,1,2},
+            {7,6,2,3}
+        };
+
+    float[][] bands     = new float[][]
+      {
+         {0.04f,34,0.3f,0.2f, N, 1, 1},
+         {0.00f, 0,0.0f,0.0f, 2, 1, E}
+      };
+    int[] bandIndexes   = new int[] { 0,0,0,1,1,1};
+    float[][] corners   = new float[][] { {0.04f,0.10f} };
+    int[] cornerIndexes = new int[] { 0,-1,-1,-1,-1,-1,-1,-1 };
+    float[][] centers   = new float[][] { {0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B} };
+    int[] centerIndexes = new int[] { 0,-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() );
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 
