commit 7764a67a19c6b6c07d7a7882cdb8d5775663e9bf
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Apr 1 12:23:21 2021 +0200

    Progress with any size Kilominx.

diff --git a/src/main/java/org/distorted/objects/FactoryCubit.java b/src/main/java/org/distorted/objects/FactoryCubit.java
index 526a9fe8..e41fa743 100644
--- a/src/main/java/org/distorted/objects/FactoryCubit.java
+++ b/src/main/java/org/distorted/objects/FactoryCubit.java
@@ -672,13 +672,13 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  MeshBase createFacesKilominxCorner()
+  MeshBase createFacesKilominxCenter()
     {
     MeshBase[] meshes = new MeshPolygon[6];
 
-    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 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);
@@ -1354,34 +1354,32 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  VertexEffect[] createVertexEffectsKilominxCorner()
+  VertexEffect[] createVertexEffectsKilominxCenter(float width)
     {
     VertexEffect[] effect = new VertexEffect[10];
 
-    float H = 0.5f*(SIN54 /COS54  );
-    float Y1= (float)(Math.sqrt(2+0.4f*SQ5)/4);
+    float H = 0.5f*(SIN54/COS54);
+    float Y1= 0.5f*SIN_HALFD;
     float Y2= H/(2*COS_HALFD);
-    float A = (float)(Math.acos(-SQ5/5)*180/Math.PI);  // dihedral angle of a dedecahedron in degrees
-    float sin18 = SIN18;
     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 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 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(A/2+18);
+    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-A/2);
+    Static1D angle6 = new Static1D(90-DIHEDRAL1/2);
 
     effect[0] = new VertexEffectMove(move1);
     effect[1] = new VertexEffectScale(1/MINX_SC);
@@ -1934,10 +1932,10 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  MeshBase createKilominxCornerMesh()
+  MeshBase createKilominxCenterMesh(float width)
     {
-    MeshBase mesh = createFacesKilominxCorner();
-    VertexEffect[] effects = createVertexEffectsKilominxCorner();
+    MeshBase mesh = createFacesKilominxCenter();
+    VertexEffect[] effects = createVertexEffectsKilominxCenter(width);
     for( VertexEffect effect : effects ) mesh.apply(effect);
 
     float A = (2*SQ3/3)* SIN54;
@@ -1961,9 +1959,25 @@ class FactoryCubit
     return mesh;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// numLayers==3 --> index=0; numLayers=5 --> index=1 ...
+// type: 0,1,... 0 --> edge, 1 --> 1 layer deeper, etc
+// TODO
+
+  MeshBase createKilominxEdgeMesh(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;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  MeshBase createMegaminxCornerMesh(int numLayers)
+  MeshBase createMinxCornerMesh(ObjectList object, int numLayers)
     {
     MeshBase mesh = createFacesMegaminxCorner(numLayers);
     VertexEffect[] effects = createVertexEffectsMegaminxCorner(numLayers);
diff --git a/src/main/java/org/distorted/objects/TwistyKilominx.java b/src/main/java/org/distorted/objects/TwistyKilominx.java
index 3bbfd88f..e36d6d9c 100644
--- a/src/main/java/org/distorted/objects/TwistyKilominx.java
+++ b/src/main/java/org/distorted/objects/TwistyKilominx.java
@@ -35,12 +35,23 @@ import org.distorted.main.RubikSurfaceView;
 
 import static org.distorted.objects.FactoryCubit.COS18;
 import static org.distorted.objects.FactoryCubit.COS54;
+import static org.distorted.objects.FactoryCubit.SIN18;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TwistyKilominx extends TwistyMinx
 {
-  private static MeshBase mMesh;
+  private static MeshBase[] mCenterMeshes, mCornerMeshes;
+  private static MeshBase[][] mEdgeMeshes;
+
+  private static final int mNumCornerEdgeVariants;
+
+  static
+    {
+    int[] sizes = ObjectList.KILO.getSizes();
+    int variants = sizes.length;
+    mNumCornerEdgeVariants = sizes[0]==3 ? variants-1 : variants;
+    }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -169,7 +180,7 @@ public class TwistyKilominx extends TwistyMinx
   private int computeEdgeType(int cubit, int numCubitsPerCorner, int numCubitsPerEdge)
     {
     int part = (cubit - NUM_CORNERS*numCubitsPerCorner) % numCubitsPerEdge;
-    return (part+1)/2;
+    return part - 2*(part/4);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -251,22 +262,96 @@ public class TwistyKilominx extends TwistyMinx
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// TODO
 
-  private int getQuat(int cubit)
+  private int getQuat(int cubit, int numCubitsPerCorner, int numCubitsPerEdge)
     {
-    return ( cubit>=0 && cubit<20 ) ? QUAT_CORNER_INDICES[cubit] : 0;
+    if( cubit < NUM_CORNERS*numCubitsPerCorner )
+      {
+      int corner = cubit/numCubitsPerCorner;
+      return QUAT_CORNER_INDICES[corner];
+      }
+
+    if( cubit < NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge )
+      {
+      int edge = (cubit-NUM_CORNERS*numCubitsPerCorner)/numCubitsPerEdge;
+      return QUAT_EDGE_INDICES[edge];
+      }
+
+    if( numCubitsPerCorner==0 )
+      {
+      return QUAT_CORNER_INDICES[cubit];
+      }
+    else
+      {
+      cubit -= (NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge);
+      int numCubitsPerCenter = 5;
+      int face = cubit/numCubitsPerCenter;
+      int index= cubit%numCubitsPerCenter;
+      int corner=mCenterMap[face][index];
+
+      return QUAT_CORNER_INDICES[corner];
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// TODO
 
   MeshBase createCubitMesh(int cubit, int numLayers)
     {
-    if( mMesh==null ) mMesh = FactoryCubit.getInstance().createKilominxCornerMesh();
-    MeshBase mesh = mMesh.copy(true);
+    int numCubitsPerCorner = numCubitsPerCorner(numLayers);
+    int numCubitsPerEdge   = numCubitsPerEdge(numLayers);
+    int[] sizes = ObjectList.KILO.getSizes();
+    int variants = sizes.length;
+    int highestSize = sizes[variants-1];
+    int lowestSize = sizes[0];
+    int indexCornerEdge = (numLayers-lowestSize)/2 - (lowestSize==3 ? 1:0);
+    MeshBase mesh;
+
+    if( mNumCornerEdgeVariants>0 )
+      {
+      if( mCornerMeshes==null ) mCornerMeshes = new MeshBase[mNumCornerEdgeVariants];
+      if( mEdgeMeshes  ==null ) mEdgeMeshes   = new MeshBase[mNumCornerEdgeVariants][(highestSize-3)/2];
+      }
+
+    if( mCenterMeshes==null ) mCenterMeshes = new MeshBase[variants];
+
+    if( cubit < NUM_CORNERS*numCubitsPerCorner )
+      {
+      if( mCornerMeshes[indexCornerEdge]==null )
+        {
+        mCornerMeshes[indexCornerEdge] = FactoryCubit.getInstance().createMinxCornerMesh(ObjectList.KILO,numLayers);
+        }
+      mesh = mCornerMeshes[indexCornerEdge].copy(true);
+      }
+    else if( cubit<NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge )
+      {
+      int type = computeEdgeType(cubit,numCubitsPerCorner,numCubitsPerEdge);  // left-top, right-top, left-second, right-second, left-third...
+
+      if( mEdgeMeshes[indexCornerEdge][type]==null )
+        {
+        float tmp   = (numLayers/3.0f)/(numLayers-1);
+        float height= tmp*COS18;
+        float width = tmp + type*height*SIN18/COS18;
+
+        mEdgeMeshes[indexCornerEdge][type] = FactoryCubit.getInstance().createKilominxEdgeMesh(numLayers,width,height);
+        }
+
+      mesh = mEdgeMeshes[indexCornerEdge][type].copy(true);
+      }
+    else
+      {
+      int indexCenter = (numLayers-3)/2;
+
+      if( mCenterMeshes[indexCenter]==null )
+        {
+        float width = (1+0.5f*(numLayers-3)*SIN18)*(numLayers/3.0f)/(numLayers-1);
+        mCenterMeshes[indexCenter] = FactoryCubit.getInstance().createKilominxCenterMesh(width);
+        }
+
+      mesh = mCenterMeshes[indexCenter].copy(true);
+      }
 
-    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[getQuat(cubit)], new Static3D(0,0,0) );
+    Static4D q = QUATS[getQuat(cubit,numCubitsPerCorner,numCubitsPerEdge)];
+    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( q, new Static3D(0,0,0) );
     mesh.apply(quat,0xffffffff,0);
 
     return mesh;
diff --git a/src/main/java/org/distorted/objects/TwistyMegaminx.java b/src/main/java/org/distorted/objects/TwistyMegaminx.java
index 77630836..c019707e 100644
--- a/src/main/java/org/distorted/objects/TwistyMegaminx.java
+++ b/src/main/java/org/distorted/objects/TwistyMegaminx.java
@@ -44,13 +44,6 @@ public class TwistyMegaminx extends TwistyMinx
 {
   static final float MEGA_D = 0.04f;
 
-  private static final int[] QUAT_EDGE_INDICES =
-      {
-        56, 40, 43, 59,  0, 55, 10, 17, 25, 49,
-        48, 57, 18,  7, 53, 32, 20, 11, 31, 38,
-        37, 30,  8, 28, 36, 44,  1, 46, 12, 14
-      };
-
   private static final int[] QUAT_CENTER_INDICES =
       {
         16, 18, 22,  1, 20, 13, 14, 15,  0, 12,  2,  3
@@ -161,7 +154,7 @@ public class TwistyMegaminx extends TwistyMinx
       Static4D pri = mCurrCornerV[index];
       Static4D sec = mCurrCornerV[(index+2)%3];
 
-      int layers= (numLayers-5)/2;
+      int layers= (numLayers-3)/2;
       int multP = (block % layers) + 1;
       int multS = (block / layers);
 
@@ -290,7 +283,7 @@ public class TwistyMegaminx extends TwistyMinx
       {
       if( mCornerMeshes[index]==null )
         {
-        mCornerMeshes[index] = FactoryCubit.getInstance().createMegaminxCornerMesh(numLayers);
+        mCornerMeshes[index] = FactoryCubit.getInstance().createMinxCornerMesh(ObjectList.MEGA,numLayers);
         }
       mesh = mCornerMeshes[index].copy(true);
       }
diff --git a/src/main/java/org/distorted/objects/TwistyMinx.java b/src/main/java/org/distorted/objects/TwistyMinx.java
index de8c68b6..68178cdf 100644
--- a/src/main/java/org/distorted/objects/TwistyMinx.java
+++ b/src/main/java/org/distorted/objects/TwistyMinx.java
@@ -194,6 +194,14 @@ abstract class TwistyMinx extends TwistyObject
            {  6, 2, 3 },
          };
 
+  static final int[] QUAT_EDGE_INDICES =
+      {
+        56, 40, 43, 59,  0, 55, 10, 17, 25, 49,
+        48, 57, 18,  7, 53, 32, 20, 11, 31, 38,
+        37, 30,  8, 28, 36, 44,  1, 46, 12, 14
+      };
+
+
   static final int[] QUAT_CORNER_INDICES =
       {
          0,  2,  3,  1, 40, 31, 41, 30, 39, 35,
