commit 3f3ff476e42fe3c9daca64deb0a7b3a79e476276
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed Oct 14 16:21:02 2020 +0100

    Beginnings of support for any-sized Skewb.

diff --git a/src/main/java/org/distorted/objects/ObjectList.java b/src/main/java/org/distorted/objects/ObjectList.java
index f0c9d1d0..550d84e6 100644
--- a/src/main/java/org/distorted/objects/ObjectList.java
+++ b/src/main/java/org/distorted/objects/ObjectList.java
@@ -84,15 +84,6 @@ public enum ObjectList
          2
        ),
 
-  SKEW (
-         new int[][] {
-                       {2 , 11, R.raw.skewb, R.drawable.ui_small_skewb, R.drawable.ui_medium_skewb, R.drawable.ui_big_skewb, R.drawable.ui_huge_skewb} ,
-                     },
-         TwistySkewb.class,
-         new MovementSkewb(),
-         2
-       ),
-
   REDI (
          new int[][] {
                        {3 , 14, R.raw.redi, R.drawable.ui_small_redi, R.drawable.ui_medium_redi, R.drawable.ui_big_redi, R.drawable.ui_huge_redi} ,
@@ -108,6 +99,17 @@ public enum ObjectList
                      },
          TwistyHelicopter.class,
          new MovementHelicopter(),
+         2
+       ),
+
+  SKEW (
+         new int[][] {
+                       {2 , 11, R.raw.skewb, R.drawable.ui_small_skewb, R.drawable.ui_medium_skewb, R.drawable.ui_big_skewb, R.drawable.ui_huge_skewb} ,
+                       {3 , 15, R.raw.skewb, R.drawable.ui_small_skewb, R.drawable.ui_medium_skewb, R.drawable.ui_big_skewb, R.drawable.ui_huge_skewb} ,
+                       {4 , 20, R.raw.skewb, R.drawable.ui_small_skewb, R.drawable.ui_medium_skewb, R.drawable.ui_big_skewb, R.drawable.ui_huge_skewb} ,
+                     },
+         TwistySkewb.class,
+         new MovementSkewb(),
          3
        ),
   ;
@@ -487,9 +489,9 @@ public enum ObjectList
       case 2: return new TwistyDiamond   (size, quat, texture, mesh, effects, moves, res, scrWidth);
       case 3: return new TwistyDino6     (size, quat, texture, mesh, effects, moves, res, scrWidth);
       case 4: return new TwistyDino4     (size, quat, texture, mesh, effects, moves, res, scrWidth);
-      case 5: return new TwistySkewb     (size, quat, texture, mesh, effects, moves, res, scrWidth);
-      case 6: return new TwistyRedi      (size, quat, texture, mesh, effects, moves, res, scrWidth);
-      case 7: return new TwistyHelicopter(size, quat, texture, mesh, effects, moves, res, scrWidth);
+      case 5: return new TwistyRedi      (size, quat, texture, mesh, effects, moves, res, scrWidth);
+      case 6: return new TwistyHelicopter(size, quat, texture, mesh, effects, moves, res, scrWidth);
+      case 7: return new TwistySkewb     (size, quat, texture, mesh, effects, moves, res, scrWidth);
       }
 
     return null;
diff --git a/src/main/java/org/distorted/objects/TwistyCube.java b/src/main/java/org/distorted/objects/TwistyCube.java
index 8c98660b..0fe5f20d 100644
--- a/src/main/java/org/distorted/objects/TwistyCube.java
+++ b/src/main/java/org/distorted/objects/TwistyCube.java
@@ -39,8 +39,6 @@ import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
 
 class TwistyCube extends TwistyObject
 {
-  static final float SQ2 = (float)Math.sqrt(2);
-
   // the three rotation axis of a RubikCube. Must be normalized.
   static final Static3D[] ROT_AXIS = new Static3D[]
          {
diff --git a/src/main/java/org/distorted/objects/TwistyDiamond.java b/src/main/java/org/distorted/objects/TwistyDiamond.java
index 1bc333c0..4a537e6a 100644
--- a/src/main/java/org/distorted/objects/TwistyDiamond.java
+++ b/src/main/java/org/distorted/objects/TwistyDiamond.java
@@ -40,10 +40,6 @@ import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
 
 public class TwistyDiamond extends TwistyObject
 {
-  private static final float SQ2 = (float)Math.sqrt(2);
-  private static final float SQ3 = (float)Math.sqrt(3);
-  private static final float SQ6 = (float)Math.sqrt(6);
-
   private static final int FACES_PER_CUBIT =8;
 
   // the four rotation axis of a Diamond. Must be normalized.
@@ -365,7 +361,7 @@ public class TwistyDiamond extends TwistyObject
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // The Diamond is solved if and only if:
 //
-// 1) all 5 octahedrons are rotated with the same quat
+// 1) all 6 octahedrons are rotated with the same quat
 // 2) the 8 tetrahedrons are rotated with the quat and, optionally, the can also be rotated
 //    by multitudes of 120 degrees along the face they are the center of.
 //
diff --git a/src/main/java/org/distorted/objects/TwistyDino.java b/src/main/java/org/distorted/objects/TwistyDino.java
index 6b8a1e5a..122c1e48 100644
--- a/src/main/java/org/distorted/objects/TwistyDino.java
+++ b/src/main/java/org/distorted/objects/TwistyDino.java
@@ -40,8 +40,6 @@ import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
 
 public abstract class TwistyDino extends TwistyObject
 {
-  private static final float SQ3 = (float)Math.sqrt(3);
-
   // the four rotation axis of a RubikDino. Must be normalized.
   static final Static3D[] ROT_AXIS = new Static3D[]
          {
diff --git a/src/main/java/org/distorted/objects/TwistyHelicopter.java b/src/main/java/org/distorted/objects/TwistyHelicopter.java
index 6f919da7..731a9012 100644
--- a/src/main/java/org/distorted/objects/TwistyHelicopter.java
+++ b/src/main/java/org/distorted/objects/TwistyHelicopter.java
@@ -40,8 +40,6 @@ import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
 
 public class TwistyHelicopter extends TwistyObject
 {
-  private static final float SQ2 = (float)Math.sqrt(2);
-
   private static final int FACES_PER_CUBIT =6;
 
   // the six rotation axis of a Helicopter. Must be normalized.
diff --git a/src/main/java/org/distorted/objects/TwistyObject.java b/src/main/java/org/distorted/objects/TwistyObject.java
index 3c490cf6..647a87aa 100644
--- a/src/main/java/org/distorted/objects/TwistyObject.java
+++ b/src/main/java/org/distorted/objects/TwistyObject.java
@@ -65,11 +65,15 @@ public abstract class TwistyObject extends DistortedNode
   static final int COLOR_VIOLET = 0xff7700bb;
   static final int COLOR_BLACK  = 0xff000000;
 
+  static final float SQ2 = (float)Math.sqrt(2);
+  static final float SQ3 = (float)Math.sqrt(3);
+  static final float SQ6 = (float)Math.sqrt(6);
+
   private static final float NODE_RATIO = 1.40f;
   private static final float MAX_SIZE_CHANGE = 1.35f;
   private static final float MIN_SIZE_CHANGE = 0.8f;
 
-  private static boolean mCreateFromDMesh = true;
+  private static boolean mCreateFromDMesh = false;
 
   private static final Static3D CENTER = new Static3D(0,0,0);
   private static final int POST_ROTATION_MILLISEC = 500;
@@ -123,6 +127,7 @@ public abstract class TwistyObject extends DistortedNode
 
     resizeFBO(mNodeSize, (int)(NODE_RATIO*mNodeSize));
 
+    mSize = size;
     mList = list;
     mOrigPos = getCubitPositions(size);
 
@@ -139,7 +144,6 @@ public abstract class TwistyObject extends DistortedNode
     if( mObjectScreenRatio>MAX_SIZE_CHANGE) mObjectScreenRatio = MAX_SIZE_CHANGE;
     if( mObjectScreenRatio<MIN_SIZE_CHANGE) mObjectScreenRatio = MIN_SIZE_CHANGE;
 
-    mSize = size;
     computeStartAndStep(mOrigPos);
     mNodeScale= new Static3D(1,NODE_RATIO,1);
     mQuat = quat;
diff --git a/src/main/java/org/distorted/objects/TwistyPyraminx.java b/src/main/java/org/distorted/objects/TwistyPyraminx.java
index f156c496..c5099a95 100644
--- a/src/main/java/org/distorted/objects/TwistyPyraminx.java
+++ b/src/main/java/org/distorted/objects/TwistyPyraminx.java
@@ -39,10 +39,6 @@ import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
 
 public class TwistyPyraminx extends TwistyObject
 {
-  private static final float SQ2 = (float)Math.sqrt(2);
-  private static final float SQ3 = (float)Math.sqrt(3);
-  private static final float SQ6 = (float)Math.sqrt(6);
-
   static final Static3D[] ROT_AXIS = new Static3D[]
          {
            new Static3D(     0,-SQ3/3,-SQ6/3),
diff --git a/src/main/java/org/distorted/objects/TwistyRedi.java b/src/main/java/org/distorted/objects/TwistyRedi.java
index c1f439c9..438b0f79 100644
--- a/src/main/java/org/distorted/objects/TwistyRedi.java
+++ b/src/main/java/org/distorted/objects/TwistyRedi.java
@@ -40,9 +40,6 @@ import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
 
 public class TwistyRedi extends TwistyObject
 {
-  private static final float SQ2 = (float)Math.sqrt(2);
-  private static final float SQ3 = (float)Math.sqrt(3);
-
   private static final int FACES_PER_CUBIT =6;
 
   // the four rotation axis of a RubikRedi. Must be normalized.
diff --git a/src/main/java/org/distorted/objects/TwistySkewb.java b/src/main/java/org/distorted/objects/TwistySkewb.java
index 287469fd..17d16698 100644
--- a/src/main/java/org/distorted/objects/TwistySkewb.java
+++ b/src/main/java/org/distorted/objects/TwistySkewb.java
@@ -23,7 +23,9 @@ import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 
+import org.distorted.library.effect.MatrixEffect;
 import org.distorted.library.effect.MatrixEffectQuaternion;
+import org.distorted.library.effect.MatrixEffectScale;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.mesh.MeshBase;
@@ -40,9 +42,6 @@ import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
 
 public class TwistySkewb extends TwistyObject
 {
-  private static final float SQ2 = (float)Math.sqrt(2);
-  private static final float SQ3 = (float)Math.sqrt(3);
-
   private static final int FACES_PER_CUBIT =6;
 
   // the four rotation axis of a RubikSkewb. Must be normalized.
@@ -79,51 +78,45 @@ public class TwistySkewb extends TwistyObject
            new Static4D(  0.5f, -0.5f, -0.5f, -0.5f )
          };
 
-  private static final float DIST_CORNER = 0.50f;
-  private static final float DIST_CENTER = 0.49f;
+  private static final int[][] mCornerMap =
+         {
+           {  4, 2, 0, 18,18,18 },
+           {  2, 5, 0, 18,18,18 },
+           {  3, 4, 0, 18,18,18 },
+           {  5, 3, 0, 18,18,18 },
+           {  1, 2, 4, 18,18,18 },
+           {  5, 2, 1, 18,18,18 },
+           {  4, 3, 1, 18,18,18 },
+           {  1, 3, 5, 18,18,18 },
+         };
 
-  // centers of the 8 corners + 6 sides ( i.e. of the all 14 cubits)
-  private static final Static3D[] CENTERS = new Static3D[]
+  private static final int[][] mEdgeMap =
          {
-           new Static3D( DIST_CORNER, DIST_CORNER, DIST_CORNER ),
-           new Static3D( DIST_CORNER, DIST_CORNER,-DIST_CORNER ),
-           new Static3D( DIST_CORNER,-DIST_CORNER, DIST_CORNER ),
-           new Static3D( DIST_CORNER,-DIST_CORNER,-DIST_CORNER ),
-           new Static3D(-DIST_CORNER, DIST_CORNER, DIST_CORNER ),
-           new Static3D(-DIST_CORNER, DIST_CORNER,-DIST_CORNER ),
-           new Static3D(-DIST_CORNER,-DIST_CORNER, DIST_CORNER ),
-           new Static3D(-DIST_CORNER,-DIST_CORNER,-DIST_CORNER ),
-
-           new Static3D( DIST_CENTER,        0.0f,        0.0f ),
-           new Static3D(-DIST_CENTER,        0.0f,        0.0f ),
-           new Static3D(        0.0f, DIST_CENTER,        0.0f ),
-           new Static3D(        0.0f,-DIST_CENTER,        0.0f ),
-           new Static3D(        0.0f,        0.0f, DIST_CENTER ),
-           new Static3D(        0.0f,        0.0f,-DIST_CENTER ),
+           { 10, 8, 18,18,18,18 },
+           {  6,10, 18,18,18,18 },
+           { 10, 9, 18,18,18,18 },
+           {  7,10, 18,18,18,18 },
+           {  8, 6, 18,18,18,18 },
+           {  9, 6, 18,18,18,18 },
+           {  9, 7, 18,18,18,18 },
+           {  8, 7, 18,18,18,18 },
+           { 11, 8, 18,18,18,18 },
+           {  6,11, 18,18,18,18 },
+           { 11, 9, 18,18,18,18 },
+           {  7,11, 18,18,18,18 }
          };
 
-  // Colors of the faces of cubits. Each cubit, even the face pyramid, has 6 faces
-  // (the face has one extra 'fake' face so that everything would have the same number)
-  private static final int[][] mFaceMap = new int[][]
+  private static final int[][] mCenterMap =
          {
-           { 4,2,0, 12,12,12 },
-           { 2,5,0, 12,12,12 },
-           { 3,4,0, 12,12,12 },
-           { 5,3,0, 12,12,12 },
-           { 1,2,4, 12,12,12 },
-           { 5,2,1, 12,12,12 },
-           { 4,3,1, 12,12,12 },
-           { 1,3,5, 12,12,12 },
-
-           { 6 , 12,12,12,12,12 },
-           { 7 , 12,12,12,12,12 },
-           { 8 , 12,12,12,12,12 },
-           { 9 , 12,12,12,12,12 },
-           { 10, 12,12,12,12,12 },
-           { 11, 12,12,12,12,12 },
+           { 12, 18,18,18,18,18 },
+           { 13, 18,18,18,18,18 },
+           { 14, 18,18,18,18,18 },
+           { 15, 18,18,18,18,18 },
+           { 16, 18,18,18,18,18 },
+           { 17, 18,18,18,18,18 },
          };
 
-  private static MeshBase mCornerMesh, mFaceMesh;
+  private static MeshBase mCornerMesh, mFaceMesh, mEdgeMesh;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -133,11 +126,33 @@ public class TwistySkewb extends TwistyObject
     super(size, 60, quat, texture, mesh, effects, moves, ObjectList.SKEW, res, scrWidth);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int getNumCorners(int size)
+    {
+    return 8;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int getNumEdges(int size)
+    {
+    return (size-2)*12;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int getNumCenters(int size)
+    {
+    return ((size-2)*(size-2) + (size-1)*(size-1))*6;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   float getScreenRatio()
     {
-    return 1.0f;
+    int size = getSize();
+    return size/ (2.0f*(size-1));
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -162,11 +177,10 @@ public class TwistySkewb extends TwistyObject
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// Each face has two types of a texture: the central square and the triangle in the corner.
 
   int getNumStickerTypes()
     {
-    return 2;
+    return 3;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -187,29 +201,184 @@ public class TwistySkewb extends TwistyObject
 
   Static3D[] getCubitPositions(int size)
     {
+    final float DIST_CORNER = (size-1)*0.50f;
+    final float DIST_EDGE   = (size-1)*0.50f;
+    final float DIST_CENTER = (size-1)*0.50f;
+
+    final int numCorners = getNumCorners(size);
+    final int numEdges   = getNumEdges(size);
+    final int numCenters = getNumCenters(size);
+
+    final Static3D[] CENTERS = new Static3D[numCorners+numEdges+numCenters];
+
+    /// CORNERS //////////////////////////////////////////////
+
+    CENTERS[0] = new Static3D( DIST_CORNER, DIST_CORNER, DIST_CORNER );
+    CENTERS[1] = new Static3D( DIST_CORNER, DIST_CORNER,-DIST_CORNER );
+    CENTERS[2] = new Static3D( DIST_CORNER,-DIST_CORNER, DIST_CORNER );
+    CENTERS[3] = new Static3D( DIST_CORNER,-DIST_CORNER,-DIST_CORNER );
+    CENTERS[4] = new Static3D(-DIST_CORNER, DIST_CORNER, DIST_CORNER );
+    CENTERS[5] = new Static3D(-DIST_CORNER, DIST_CORNER,-DIST_CORNER );
+    CENTERS[6] = new Static3D(-DIST_CORNER,-DIST_CORNER, DIST_CORNER );
+    CENTERS[7] = new Static3D(-DIST_CORNER,-DIST_CORNER,-DIST_CORNER );
+
+    /// EDGES ///////////////////////////////////////////////
+
+    final float[][]  edgeTable =
+        {
+            {0,+DIST_EDGE,+DIST_EDGE},
+            {+DIST_EDGE,0,+DIST_EDGE},
+            {0,-DIST_EDGE,+DIST_EDGE},
+            {-DIST_EDGE,0,+DIST_EDGE},
+            {+DIST_EDGE,+DIST_EDGE,0},
+            {+DIST_EDGE,-DIST_EDGE,0},
+            {-DIST_EDGE,-DIST_EDGE,0},
+            {-DIST_EDGE,+DIST_EDGE,0},
+            {0,+DIST_EDGE,-DIST_EDGE},
+            {+DIST_EDGE,0,-DIST_EDGE},
+            {0,-DIST_EDGE,-DIST_EDGE},
+            {-DIST_EDGE,0,-DIST_EDGE}
+        };
+
+    int index=8;
+
+    for (float[] edges : edgeTable)
+      {
+      float c = (3-size)*0.5f;
+
+      for (int j=0; j<size-2; j++, c+=1.0f, index++)
+        {
+        CENTERS[index] = new Static3D( edges[0]==0 ? c : edges[0] ,
+                                       edges[1]==0 ? c : edges[1] ,
+                                       edges[2]==0 ? c : edges[2] );
+        }
+      }
+
+    /// CENTERS //////////////////////////////////////////////
+
+    final float X= -1000.0f;
+    final float Y= -1001.0f;
+
+    final float[][]  centerTable =
+        {
+            {+DIST_CENTER,X,Y},
+            {-DIST_CENTER,X,Y},
+            {X,+DIST_CENTER,Y},
+            {X,-DIST_CENTER,Y},
+            {X,Y,+DIST_CENTER},
+            {X,Y,-DIST_CENTER}
+        };
+
+    float x,y, cen0, cen1, cen2;
+
+    for( float[] centers : centerTable )
+      {
+      x = (2-size)*0.5f;
+
+      for(int i=0; i<size-1; i++, x+=1.0f)
+        {
+        y = (2-size)*0.5f;
+
+        for(int j=0; j<size-1; j++, y+=1.0f, index++)
+          {
+               if( centers[0]==Y ) cen0 = y;
+          else if( centers[0]==X ) cen0 = x;
+          else                     cen0 = centers[0];
+
+               if( centers[1]==Y ) cen1 = y;
+          else if( centers[1]==X ) cen1 = x;
+          else                     cen1 = centers[1];
+
+               if( centers[2]==Y ) cen2 = y;
+          else if( centers[2]==X ) cen2 = x;
+          else                     cen2 = centers[2];
+
+          CENTERS[index] = new Static3D(cen0,cen1,cen2);
+          }
+        }
+
+      x = (3-size)*0.5f;
+
+      for(int i=0; i<size-2; i++, x+=1.0f)
+        {
+        y = (3-size)*0.5f;
+
+        for(int j=0; j<size-2; j++, y+=1.0f, index++)
+          {
+               if( centers[0]==Y ) cen0 = y;
+          else if( centers[0]==X ) cen0 = x;
+          else                     cen0 = centers[0];
+
+               if( centers[1]==Y ) cen1 = y;
+          else if( centers[1]==X ) cen1 = x;
+          else                     cen1 = centers[1];
+
+               if( centers[2]==Y ) cen2 = y;
+          else if( centers[2]==X ) cen2 = x;
+          else                     cen2 = centers[2];
+
+          CENTERS[index] = new Static3D(cen0,cen1,cen2);
+          }
+        }
+      }
+
     return CENTERS;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private Static4D getQuat(int cubit)
+  private Static4D getQuat(int cubit, int size)
     {
-    switch(cubit)
+    int numCorners = getNumCorners(size);
+    int numEdges   = getNumEdges(size);
+
+    if( cubit<numCorners )
+      {
+      switch(cubit)
+        {
+        case  0: return QUATS[0];                          //  unit quat
+        case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
+        case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
+        case  3: return QUATS[1];                          // 180 along X
+        case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
+        case  5: return QUATS[2];                          // 180 along Y
+        case  6: return QUATS[3];                          // 180 along Z
+        case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
+        }
+      }
+    else if( cubit<numCorners+numEdges )
+      {
+      int edge = (cubit-numCorners)/(size-2);
+
+      switch(edge)
+        {
+        case  0: return QUATS[ 0];
+        case  1: return QUATS[ 5];
+        case  2: return QUATS[ 3];
+        case  3: return QUATS[11];
+        case  4: return QUATS[ 4];
+        case  5: return QUATS[ 7];
+        case  6: return QUATS[ 9];
+        case  7: return QUATS[10];
+        case  8: return QUATS[ 2];
+        case  9: return QUATS[ 8];
+        case 10: return QUATS[ 1];
+        case 11: return QUATS[ 6];
+        }
+      }
+    else
       {
-      case  0: return QUATS[0];                          //  unit quat
-      case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
-      case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
-      case  3: return QUATS[1];                          // 180 along X
-      case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
-      case  5: return QUATS[2];                          // 180 along Y
-      case  6: return QUATS[3];                          // 180 along Z
-      case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
-      case  8: return new Static4D(0,-SQ2/2,0,SQ2/2);    // -90 along Y
-      case  9: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
-      case 10: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
-      case 11: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
-      case 12: return QUATS[0];                          //  unit quaternion
-      case 13: return QUATS[1];                          // 180 along X
+      int center = (cubit-numCorners-numEdges)/((size-2)*(size-2)+(size-1)*(size-1));
+
+      switch(center)
+        {
+        case 0: return new Static4D(0,-SQ2/2,0,SQ2/2);    // -90 along Y
+        case 1: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
+        case 2: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
+        case 3: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
+        case 4: return QUATS[0];                          //  unit quaternion
+        case 5: return QUATS[1];                          // 180 along X
+        }
       }
 
     return null;
@@ -221,18 +390,34 @@ public class TwistySkewb extends TwistyObject
     {
     MeshBase mesh;
 
-    if( cubit<8 )
+    int size = getSize();
+    int numCorners = getNumCorners(size);
+    int numEdges   = getNumEdges(size);
+
+    if( cubit<numCorners )
       {
       if( mCornerMesh==null ) mCornerMesh = CubitFactory.getInstance().createSkewbCornerMesh();
       mesh = mCornerMesh.copy(true);
       }
+    else if( cubit<numCorners+numEdges )
+      {
+      if( mEdgeMesh==null )
+        {
+        mEdgeMesh = CubitFactory.getInstance().createDinoMesh();
+        MatrixEffect effect = new MatrixEffectScale(1.0f/3);
+        mEdgeMesh.apply(effect,-1,0);
+        mEdgeMesh.addEmptyTexComponent();
+        mEdgeMesh.addEmptyTexComponent();
+        }
+      mesh = mEdgeMesh.copy(true);
+      }
     else
       {
       if( mFaceMesh==null ) mFaceMesh = CubitFactory.getInstance().createSkewbFaceMesh();
       mesh = mFaceMesh.copy(true);
       }
 
-    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
+    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit,size), new Static3D(0,0,0) );
     mesh.apply(quat,0xffffffff,0);
 
     return mesh;
@@ -242,7 +427,23 @@ public class TwistySkewb extends TwistyObject
 
   int getFaceColor(int cubit, int cubitface, int size)
     {
-    return mFaceMap[cubit][cubitface];
+    int numCorners = getNumCorners(size);
+    int numEdges   = getNumEdges(size);
+
+    if( cubit<numCorners )
+      {
+      return mCornerMap[cubit][cubitface];
+      }
+    else if( cubit<numCorners+numEdges )
+      {
+      int edge = (cubit-numCorners)/(size-2);
+      return mEdgeMap[edge][cubitface];
+      }
+    else
+      {
+      int center = (cubit-numCorners-numEdges)/((size-2)*(size-2)+(size-1)*(size-1));
+      return mCenterMap[center][cubitface];
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -259,13 +460,22 @@ public class TwistySkewb extends TwistyObject
       float[] vertices = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
       drawRoundedPolygon(canvas, paint, left, vertices, S, FACE_COLORS[face], R);
       }
+    else if( face<2*COLORS )
+      {
+      float F = 0.5f;
+      float R = 0.025f;
+      float S = 0.05f;
+      float[] vertices = { -F,F/3, 0,-2*F/3, +F,F/3 };
+
+      drawRoundedPolygon(canvas, paint, left, vertices, S, FACE_COLORS[face-COLORS], R);
+      }
     else
       {
       float R = 0.055f;
       float S = 0.035f;
       float E = SQ2/4;
       float[] vertices = { -E,-E, +E,-E, +E,+E, -E,+E };
-      drawRoundedPolygon(canvas, paint, left, vertices, S, FACE_COLORS[face-COLORS], R);
+      drawRoundedPolygon(canvas, paint, left, vertices, S, FACE_COLORS[face-2*COLORS], R);
       }
     }
 
@@ -280,10 +490,13 @@ public class TwistySkewb extends TwistyObject
 
   float[] getRowChances()
     {
-    float[] chances = new float[2];
+    int size = getSize();
+    float[] chances = new float[size];
 
-    chances[0] = 0.5f;
-    chances[1] = 1.0f;
+    for(int i=0; i<size; i++)
+      {
+      chances[i] = (float)(i+1)/size;
+      }
 
     return chances;
     }
@@ -378,7 +591,7 @@ public class TwistySkewb extends TwistyObject
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // The Skewb is solved if and only if:
 //
-// 1) all of its corner cubits are rotated with the same quat
+// 1) all of its corner and edge cubits are rotated with the same quat
 // 2) all its face cubits are rotated with the same quat like the corner ones,
 //    and optionally they also might be upside down.
 //
