commit 0431e30830576fc1e4ff7869d0e8ea5a405e9f27
Author: leszek <leszek@koltunski.pl>
Date:   Tue Jan 30 22:41:41 2024 +0100

    Progress with Penrose - debugging solved state.

diff --git a/src/main/java/org/distorted/objectlib/main/TwistyObject.java b/src/main/java/org/distorted/objectlib/main/TwistyObject.java
index 72c45151..5bfd6413 100644
--- a/src/main/java/org/distorted/objectlib/main/TwistyObject.java
+++ b/src/main/java/org/distorted/objectlib/main/TwistyObject.java
@@ -1340,9 +1340,20 @@ public abstract class TwistyObject
     boolean error = false;
     String key = getShortName();
 
+    int[] qu =
+      {
+      0,0,
+      0,0,0,0,0,0,
+      0,0,0,
+      0,0,0,0,0,0,0,0,0,
+      0,0,0,0,0,0
+      };
+
+    android.util.Log.e("D", "RESTORING PREFERENCES");
+
     for(int i=0; i<mNumCubits; i++)
       {
-      mQuatDebug[i] = mCubits[i].restorePreferences(key,os);
+      mQuatDebug[i] = i<qu.length ? qu[i] : mCubits[i].restorePreferences(key,os);
 
       if( mQuatDebug[i]>=0 && mQuatDebug[i]<mNumQuats )
         {
diff --git a/src/main/java/org/distorted/objectlib/metadata/MetadataCU_242.java b/src/main/java/org/distorted/objectlib/metadata/MetadataCU_242.java
index 3929cb4c..ec7e56d8 100644
--- a/src/main/java/org/distorted/objectlib/metadata/MetadataCU_242.java
+++ b/src/main/java/org/distorted/objectlib/metadata/MetadataCU_242.java
@@ -20,7 +20,7 @@ public class MetadataCU_242 extends Metadata
   public MetadataCU_242()         { super( TwistyCuboid.class, new int[] {2,4,2}, 0, null, INDEX ); }
   public int numScrambles()       { return 21; }
   public int icon()               { return R.drawable.cu_242; }
-  public boolean getActive()      { return false; }
+ // public boolean getActive()      { return false; }
   public int price()              { return 40; }
   public int extrasJson()         { return R.raw.cu_242_extras; }
   public int objectJson()         { return R.raw.cu_242_object; }
diff --git a/src/main/java/org/distorted/objectlib/metadata/MetadataCU_424.java b/src/main/java/org/distorted/objectlib/metadata/MetadataCU_424.java
index 4868d8aa..96089f1b 100644
--- a/src/main/java/org/distorted/objectlib/metadata/MetadataCU_424.java
+++ b/src/main/java/org/distorted/objectlib/metadata/MetadataCU_424.java
@@ -20,7 +20,7 @@ public class MetadataCU_424 extends Metadata
   public MetadataCU_424()         { super( TwistyCuboid.class, new int[] {4,2,4}, 0, null, INDEX ); }
   public int numScrambles()       { return 27; }
   public int icon()               { return R.drawable.cu_424; }
-  public boolean getActive()      { return false; }
+  //public boolean getActive()      { return false; }
   public int price()              { return 40; }
   public int extrasJson()         { return R.raw.cu_424_extras; }
   public int objectJson()         { return R.raw.cu_424_object; }
diff --git a/src/main/java/org/distorted/objectlib/metadata/MetadataCU_432.java b/src/main/java/org/distorted/objectlib/metadata/MetadataCU_432.java
index 99df4bc8..5b84e905 100644
--- a/src/main/java/org/distorted/objectlib/metadata/MetadataCU_432.java
+++ b/src/main/java/org/distorted/objectlib/metadata/MetadataCU_432.java
@@ -20,7 +20,7 @@ public class MetadataCU_432 extends Metadata
   public MetadataCU_432()         { super( TwistyCuboid.class, new int[] {4,3,2}, 0, null, INDEX ); }
   public int numScrambles()       { return 35; }
   public int icon()               { return R.drawable.cu_432; }
-  public boolean getActive()      { return false; }
+ // public boolean getActive()      { return false; }
   public int price()              { return 40; }
   public int extrasJson()         { return R.raw.cu_432_extras; }
   public int objectJson()         { return R.raw.cu_432_object; }
diff --git a/src/main/java/org/distorted/objectlib/metadata/MetadataMJIN_3.java b/src/main/java/org/distorted/objectlib/metadata/MetadataMJIN_3.java
index e327869e..9698b833 100644
--- a/src/main/java/org/distorted/objectlib/metadata/MetadataMJIN_3.java
+++ b/src/main/java/org/distorted/objectlib/metadata/MetadataMJIN_3.java
@@ -21,7 +21,7 @@ public class MetadataMJIN_3 extends Metadata
   public MetadataMJIN_3()         { super( TwistyMirrorJing.class, new int[] {2,2,2,2}, 0, null, INDEX ); }
   public int numScrambles()       { return 11; }
   public int icon()               { return R.drawable.mjin_2; }
-  public boolean getActive()      { return false; }
+ // public boolean getActive()      { return false; }
   public int price()              { return 30; }
   public int extrasJson()         { return 0; }
   public int objectJson()         { return R.raw.mjin_2_object; }
diff --git a/src/main/java/org/distorted/objectlib/metadata/MetadataMPYR_3.java b/src/main/java/org/distorted/objectlib/metadata/MetadataMPYR_3.java
index 7b092975..3ccc9486 100644
--- a/src/main/java/org/distorted/objectlib/metadata/MetadataMPYR_3.java
+++ b/src/main/java/org/distorted/objectlib/metadata/MetadataMPYR_3.java
@@ -21,7 +21,7 @@ public class MetadataMPYR_3 extends Metadata
   public MetadataMPYR_3()         { super( TwistyMirrorPyraminx.class, new int[] {3,3,3,3}, 0, null, INDEX); }
   public int numScrambles()       { return 11; }
   public int icon()               { return R.drawable.mpyr_3; }
-  public boolean getActive()      { return false; }
+ // public boolean getActive()      { return false; }
   public int price()              { return 30; }
   public int extrasJson()         { return 0; }
   public int objectJson()         { return R.raw.mpyr_3_object; }
diff --git a/src/main/java/org/distorted/objectlib/metadata/MetadataMSKE_2.java b/src/main/java/org/distorted/objectlib/metadata/MetadataMSKE_2.java
index f3f3974f..93ac9026 100644
--- a/src/main/java/org/distorted/objectlib/metadata/MetadataMSKE_2.java
+++ b/src/main/java/org/distorted/objectlib/metadata/MetadataMSKE_2.java
@@ -21,7 +21,7 @@ public class MetadataMSKE_2 extends Metadata
   public MetadataMSKE_2()         { super( TwistyMirrorSkewb.class, new int[] {2,2,2,2}, 0, null, INDEX ); }
   public int numScrambles()       { return 11; }
   public int icon()               { return R.drawable.mske_2; }
-  public boolean getActive()      { return false; }
+ // public boolean getActive()      { return false; }
   public int price()              { return 30; }
   public int extrasJson()         { return 0; }
   public int objectJson()         { return R.raw.mske_2_object; }
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyPenrose.java b/src/main/java/org/distorted/objectlib/objects/TwistyPenrose.java
index e6e8e86a..a1a0c4f9 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyPenrose.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyPenrose.java
@@ -12,6 +12,8 @@ package org.distorted.objectlib.objects;
 import static org.distorted.objectlib.touchcontrol.TouchControl.TC_CHANGING_MIRROR;
 import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
 
+import org.distorted.library.effect.EffectName;
+import org.distorted.library.helpers.QuatHelper;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 import org.distorted.objectlib.helpers.FactoryCubit;
@@ -29,8 +31,6 @@ import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
 
 public class TwistyPenrose extends ShapeHexahedron
 {
-  private static final int N = 8; // has to be >=3
-
   static final Static3D[] ROT_AXIS = new Static3D[]
          {
            new Static3D(1,0,0),
@@ -43,77 +43,38 @@ public class TwistyPenrose extends ShapeHexahedron
   private float[][] mCuts;
   private int[] mQuatIndex;
   private int[][] mFaceMap;
+  private int[][] mQuatDivided;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public TwistyPenrose(int iconMode, Static4D quat, Static3D move, float scale, Metadata meta, InitAssets asset)
     {
     super(iconMode, meta.getNumLayers()[0], quat, move, scale, meta, asset);
-
-    FactoryCubit f = FactoryCubit.getInstance();
-    f.printStickerCoords();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// { -0.5f, -0.49999997f, 0.5f, -0.49999997f, 0.5f, 0.49999997f, -0.5f, 0.49999997f}
+// { -0.24999999f, 0.5f, -0.24999999f, -0.24999999f, 0.5f, -0.24999999f}
+// { -0.5f, -0.08578644f, -0.08578644f, -0.49999997f, 0.5f, 0.08578644f, 0.085786454f, 0.5f}
 
-  @Override
-  public int getInternalColor()
-    {
-    return 0xff222222;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/*
-{ -0.5f, -0.49999997f, 0.5f, -0.49999997f, 0.5f, 0.49999997f, -0.5f, 0.49999997f}
-{ -0.49659738f, 0.46088853f, -0.49659738f, -0.5f, 0.4642912f, -0.5f, 0.42613786f, -0.23192067f, 0.28489703f, 0.05908255f, 0.05509505f, 0.28672886f, -0.23722643f, 0.42522076f}
-{ -0.4642912f, -0.5f, 0.49659738f, -0.5f, 0.49659738f, 0.46088853f, 0.23722643f, 0.42522076f, -0.05509505f, 0.28672886f, -0.28489703f, 0.05908255f, -0.42613786f, -0.23192067f}
-{ -0.5f, -0.06705149f, 0.46144003f, -0.20388463f, 0.5f, 0.06705155f, -0.46144003f, 0.20388466f}
-{ -0.5f, 0.06391828f, 0.35955805f, -0.3532754f, 0.49999994f, -0.06391831f, -0.35955808f, 0.3532754f}
-{ -0.19758901f, 0.46388432f, -0.0650391f, -0.5f, 0.19758904f, -0.46388432f, 0.06503913f, 0.5f}
-*/
-
-/*
-{ -0.5f, -0.49999997f, 0.5f, -0.49999997f, 0.5f, 0.49999997f, -0.5f, 0.49999997f}
-{ -0.49759144f, 0.39903626f, -0.49759144f, -0.5f, 0.40144485f, -0.5f, 0.38744375f, -0.34195277f, 0.33711463f, -0.1660358f, 0.25221044f, -0.0039522364f, 0.13624811f, 0.13758421f, -0.0059688925f, 0.25271076f, -0.16854979f, 0.33665872f, -0.34476027f, 0.3859508f}
-{ -0.40144485f, -0.5f, 0.49759144f, -0.5f, 0.49759144f, 0.39903626f, 0.34476027f, 0.3859508f, 0.16854979f, 0.33665872f, 0.0059688925f, 0.25271076f, -0.13624811f, 0.13758421f, -0.25221044f, -0.0039522364f, -0.33711463f, -0.1660358f, -0.38744375f, -0.34195277f}
-{ -0.5f, -0.0432719f, 0.48460624f, -0.13049613f, 0.49999994f, 0.043271806f, -0.48460624f, 0.13049607f}
-{ -0.5f, 0.03901463f, 0.44497663f, -0.23133945f, 0.5f, -0.0390146f, -0.44497663f, 0.23133945f}
-{ -0.12627374f, 0.4856021f, -0.04188615f, -0.5f, 0.1262737f, -0.4856021f, 0.04188612f, 0.5f}
-
- */
   @Override
   public void adjustStickerCoords()
     {
-    /* N=5
-    final float A = 0.50f;
-    final float B = 0.49659738f;
-    final float C = 0.4642912f;
-    final float D = 0.06705149f;
-    final float E = 0.20388463f;
-    final float F = 0.35955805f;
-    final float G = 0.19758901f;
-    */
-
-    // N=8
     final float A = 0.50f;
-    final float B = 0.4975f;
-    final float C = 0.40f;
-    final float D = 0.0432f;
-    final float H = 0.4846f;
-    final float I = 0.1305f;
-    final float J = 0.0390f;
-    final float K = 0.4449f;
-    final float L = 0.23134f;
-    final float M = 0.12627f;
-    final float O = 0.04188f;
+    final float B = 0.25f;
+    final float C = 0.08578644f;
+    final float D = 0.23f;
+
+    final float E = (A+D)/5;
+    final float F = 0.005f;
+    final float G = (A+D)/2;
+    final float H = 0.002f;
 
     mStickerCoords = new float[][][][]
           {
             { { {-A,-A},{ A,-A},{ A, A},{-A, A} } },
-            { { {-C,-A},{ B,-A},{ B, C} } },
-            { { {-A,-D},{ H,-I},{ A, D},{-H, I} } },
-            { { {-A, J},{ K,-L},{ A,-J},{-K, L} } },
-            { { {-M, H},{-O,-A},{ M,-H},{ O, A} } },
+            { { {-B, A},{-B,-B},{ A,-B},{ A,-D},{A-E+F,-D+E+F},{A-2*E,-D+2*E},{A-G+H,-D+G+H},{-D+2*E,A-2*E},{-D+E+F,A-E+F},{-D, A} } },
+            { { {-A,-C},{-C,-A},{ A, C},{ C, A} } }
           };
     }
 
@@ -123,32 +84,138 @@ public class TwistyPenrose extends ShapeHexahedron
   protected float[][][] getStickerRadii()
     {
     float R = getStickerRadius();
+    float R2 = 1.3f*R;
 
     return new float[][][]
       {
         { { R, R, R, R } },
-        { { R, R, R } },
-        { { R, R, 0, 0 } },
-        { { 0, 0, 0, 0 } },
-        { { 0, 0, R, R } },
+        { { R2, R, R2, 0, 0,0,0,0,0, 0 } },
+        { { R, R, R, R } },
       };
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// remember about the double cover or unit quaternions!
+
+  private int mulQuat(int q1, int q2)
+    {
+    Static4D result = QuatHelper.quatMultiply(mObjectQuats[q1],mObjectQuats[q2]);
+    return findQuatIndex(result);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// remember about the double cover or unit quaternions!
+
+  private int findQuatIndex(Static4D quat)
+    {
+    int numQ = mObjectQuats.length;
+
+    float rX = quat.get0();
+    float rY = quat.get1();
+    float rZ = quat.get2();
+    float rW = quat.get3();
+
+    final float MAX_ERROR = 0.1f;
+    float dX,dY,dZ,dW;
+
+    for(int i=0; i<numQ; i++)
+      {
+      dX = mObjectQuats[i].get0() - rX;
+      dY = mObjectQuats[i].get1() - rY;
+      dZ = mObjectQuats[i].get2() - rZ;
+      dW = mObjectQuats[i].get3() - rW;
+
+      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
+          dY<MAX_ERROR && dY>-MAX_ERROR &&
+          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
+          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
+
+      dX = mObjectQuats[i].get0() + rX;
+      dY = mObjectQuats[i].get1() + rY;
+      dZ = mObjectQuats[i].get2() + rZ;
+      dW = mObjectQuats[i].get3() + rW;
+
+      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
+          dY<MAX_ERROR && dY>-MAX_ERROR &&
+          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
+          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
+      }
+
+    return -1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// QDivided[i][j] = ObjectQ[i]/ObjectQ[j] -> QDivided[i][j] * ObjectQ[j] = ObjectQ[i]
+
+  private void createQuatDivided()
+    {
+    int numQ = mObjectQuats.length;
+
+    mQuatDivided = new int[numQ][numQ];
+
+    for(int i=0; i<numQ; i++)
+      for(int j=0; j<numQ; j++) mQuatDivided[i][j] = -3;
+
+    for(int i=0; i<numQ; i++)
+      for(int j=0; j<numQ; j++)
+        {
+        int q = mulQuat(i,j);
+        mQuatDivided[q][j] = i;
+        }
+
+    for(int i=0; i<numQ; i++)
+      for(int j=0; j<numQ; j++)
+        if( mQuatDivided[i][j] == -3 )
+          android.util.Log.e("D", "quat divided: "+i+" "+j);
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   @Override
-  protected float[][][] getStickerStrokes()
+  public int[][] getSolvedQuats()
     {
-    float S = getStickerStroke();
+    if( mQuatDivided==null ) createQuatDivided();
 
-    return new float[][][]
+    int[][] ret =  new int[][]
       {
-        { { S, S, S, S } },
-        { { S, S, S } },
-        { { S, S, S, 0 } },
-        { { S, 0, S, 0 } },
-        { { S, 0, S, S } },
+              { 1, 12, mQuatDivided[15][12], mQuatDivided[17][12] },  // triplet of full edges 12<-->15<-->17
+              { 1, 15, mQuatDivided[12][15], mQuatDivided[17][15] },
+              { 1, 17, mQuatDivided[12][17], mQuatDivided[15][17] },
+              { 1, 13, mQuatDivided[16][13], mQuatDivided[19][13] },  // triplet of full edges 13<-->16<-->19
+              { 1, 16, mQuatDivided[13][16], mQuatDivided[19][16] },
+              { 1, 19, mQuatDivided[13][19], mQuatDivided[16][19] },
+              { 1, 11, mQuatDivided[14][11], mQuatDivided[18][11] },  // triplet of full edges 11<-->14<-->18
+              { 1, 14, mQuatDivided[11][14], mQuatDivided[18][14] },
+              { 1, 18, mQuatDivided[11][18], mQuatDivided[14][18] },
+
+              { 1, 20, 1, 2, 3 },  // +X center; in-face rotations.
+              { 1, 21, 1, 2, 3 },  // -X center
+              { 1, 22, 4, 5, 6 },  // +Y center
+              { 1, 23, 4, 5, 6 },  // -Y center
+              { 1, 24, 7, 8, 9 },  // +Z center
+              { 1, 25, 7, 8, 9 }   // -Z center
       };
+
+    StringBuilder sb = new StringBuilder();
+    int l = ret.length;
+    sb.append("SOLVED QUATS");
+
+    for(int i=0; i<l; i++)
+      {
+      sb.append("\ngroup ");
+      sb.append(i);
+      sb.append(" : ");
+
+      for( int s : ret[i] )
+        {
+        sb.append(' ');
+        sb.append(s);
+        }
+      }
+
+    android.util.Log.e("D", sb.toString() );
+
+    return ret;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -159,25 +226,25 @@ public class TwistyPenrose extends ShapeHexahedron
     {
     if( mFaceMap==null )
       {
-      int C1 = 0;
-      int C2 = 2;
-      int C3 = 4;
+      final int C1 = 1;
+      final int C2 = 2;
+      final int C3 = 4;
 
       mFaceMap = new int[][]
          {
                  {-1,C2,-1,C1,-1,C3},
                  {-1,C1,-1,C2,-1,C3},
 
-                 {-1,C1,-1,-1,C2},
-                 {-1,C3,-1,-1,C2},
-                 {-1,C2,-1,-1,C3},
-                 {-1,C2,-1,-1,C1},
-                 {-1,C3,-1,-1,C1},
-                 {-1,C1,-1,-1,C3},
+                 {-1,C1,C2,-1,-1,-1},
+                 {-1,C3,C2,-1,-1,-1},
+                 {-1,C2,C3,-1,-1,-1},
+                 {-1,C2,C1,-1,-1,-1},
+                 {-1,C3,C1,-1,-1,-1},
+                 {-1,C1,C3,-1,-1,-1},
 
-                 {-1,-1,-1,-1,C3},
-                 {-1,-1,-1,-1,C1},
-                 {-1,-1,-1,-1,C2},
+                 {-1,-1,C3,-1,-1,-1},
+                 {-1,-1,C1,-1,-1,-1},
+                 {-1,-1,C2,-1,-1,-1},
 
                  {-1,-1,-1,C2,-1,C1},
                  {-1,-1,-1,C3,-1,C2},
@@ -198,15 +265,6 @@ public class TwistyPenrose extends ShapeHexahedron
          };
       }
 
-    if( cubit>=2 && cubit<=10 )
-      {
-      if( face>4 ) return mFaceMap[cubit][4];
-      }
-    else
-      {
-      if( face>5 ) return -1;
-      }
-
     return mFaceMap[cubit][face];
     }
 
@@ -377,34 +435,15 @@ public class TwistyPenrose extends ShapeHexahedron
     {
     if( variant==1 || variant==2 )
       {
-      float[][] ret = new float[4+2*N][];
-      ret[0] = new float[] {-0.5f,-0.5f,-0.5f };
-      ret[1] = new float[] {+0.5f,-0.5f,-0.5f };
-      ret[2] = new float[] {+0.5f,+0.5f,-0.5f };
-      ret[3] = new float[] {-0.5f,-0.5f,+0.5f };
-      ret[4] = new float[] {+0.5f,-0.5f,+0.5f };
-      ret[5] = new float[] {+0.5f,+0.5f,+0.5f };
-
-      final float PIH = (float)Math.PI/2;
-      final float P = 0.90f;           // in order to avoid collapsing all of those into one sticker,
-      final float O = 0.87f;           // we need to make the first and last a bit different size
-      final float K = (N-(P+O))/(N-2); // (the middles can collapse, they all have the same strokes)
-                                       // now P + K+K+..+K + O = N   (K is repeated N-2 times)
-      float segment = P;
-
-      for(int v=6; v<4+2*N; v++)
-        {
-        boolean even = (v%2==0);
-        float alpha = segment*PIH/N;
-        if( !even ) segment += K;
-        float x = 0.5f - (float)Math.cos(alpha);
-        float y = (float)Math.sin(alpha) - 0.5f;
-        float z = even ? -0.5f : 0.5f;
-
-        ret[v] = new float[] { x,y,z };
-        }
-
-      return ret;
+      return new float[][]
+          {
+              {-0.5f,-0.5f,-0.5f },
+              {+0.5f,-0.5f,-0.5f },
+              {+0.5f,+0.5f,-0.5f },
+              {-0.5f,-0.5f,+0.5f },
+              {+0.5f,-0.5f,+0.5f },
+              {+0.5f,+0.5f,+0.5f },
+          };
       }
     else
       {
@@ -428,27 +467,14 @@ public class TwistyPenrose extends ShapeHexahedron
     {
     if( variant==1 || variant==2 )
       {
-      int[][] indices = new int[4+N][];
-
-      indices[0] = new int[N+2];
-      indices[0][0] = 2;
-      indices[0][1] = 1;
-      indices[0][2] = 0;
-      for(int v=3; v<N+2; v++) indices[0][v] = 2*v;
-
-      indices[1] = new int[N+2];
-      indices[1][0] = 3;
-      indices[1][1] = 4;
-      indices[1][2] = 5;
-      for(int v=3; v<N+2; v++) indices[1][v] = 2*N-2*v+9;
-
-      indices[2] = new int[] {0,1,4,3};
-      indices[3] = new int[] {5,4,1,2};
-      indices[4] = new int[] {0,3,7,6};
-
-      for(int f=5; f<3+N; f++) indices[f] = new int[] { 2*f-4, 2*f-3, 2*f-1, 2*f-2 };
-
-      indices[3+N] = new int[] { 2*N+2, 2*N+3, 5, 2 };
+      int[][] indices =
+          {
+              {2,1,0},
+              {3,4,5},
+              {0,3,5,2},
+              {0,1,4,3},
+              {5,4,1,2}
+          };
 
       return new ObjectShape(getVertices(variant), indices);
       }
@@ -487,31 +513,27 @@ public class TwistyPenrose extends ShapeHexahedron
     int angle = 35;
     float R = 0.5f;
     float S = 0.7f;
-    int[] bandIndices = null;
 
     float[][] bands  =
          {
              {    h1,angle,R,S,n1,extraI,extraV},
              {0.001f,angle,R,S, 2,  n1-2,extraV},
-             {0.000f,angle,R,S, 2,     0,     0},
+             {0.001f,angle,R,S, 2,     0,     0},
              {0.001f,angle,R,S,n1,extraI,extraV},
              {    h2,angle,R,S,n2,extraI,extraV},
+             {0.001f,angle,R,S,n2,extraI,extraV},
          };
 
     switch(variant)
       {
-      case 0: bandIndices = new int[] {3,0,3,0,3,0}; break;
-      case 1:
-      case 2: bandIndices = new int[4+N];
-              bandIndices[0] = bandIndices[1] = 4;
-              bandIndices[2] = bandIndices[3] = 3;
-              for(int i=4; i<4+N; i++) bandIndices[i] = 2;
-              break;
-      case 3: bandIndices = new int[] {1,1,1,0,1,0}; break;
-      case 4: bandIndices = new int[] {2,2,2,2,0,2}; break;
+      case 0: return new ObjectFaceShape(bands,new int[] {3,0,3,0,3,0},null);
+      case 1: return new ObjectFaceShape(bands,new int[] { 5,4,4,5,5 },null);
+      case 2: return new ObjectFaceShape(bands,new int[] { 5,5,4,5,5 },null);
+      case 3: return new ObjectFaceShape(bands,new int[] {1,1,1,0,1,0},null);
+      case 4: return new ObjectFaceShape(bands,new int[] {2,2,2,2,0,2},null);
       }
 
-    return new ObjectFaceShape(bands,bandIndices,null);
+    return null;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -521,21 +543,23 @@ public class TwistyPenrose extends ShapeHexahedron
     float[][] corners= { {0.030f,0.12f} };
     float[][] centers= { {0.0f, 0.0f, 0.0f} };
     float[][] vertices= getVertices(variant);
-    int[] indices;
 
-    if ( variant<1 || variant>2 )
+    if( variant==1 || variant==2 )
       {
-      indices = new int[] { 0,0,0,0,0,0,0,0 };
+      int[] indices = { 0,0,0,0,0,0 };
+      ObjectVertexEffects effects = FactoryCubit.generateVertexEffect(vertices,corners,indices,centers,indices);
+      String n = EffectName.PIPE.name();
+      float[] v = {0.5f,0,0,1,0.92f};
+      float[] c = {-0.5f,0.5f,0.0f};
+      float[] r = {0,0,0,0};
+      effects.joinEffect(n,v,c,r,true);
+      return effects;
       }
     else
       {
-      indices = new int[4+2*N];
-      indices[0] = indices[2] = indices[3] = indices[5] = 0;
-      indices[1] = indices[4] = -1;
-      for(int v=6; v<4+2*N; v++) indices[v] = -1;
+      int[] indices = { 0,0,0,0,0,0,0,0 };
+      return FactoryCubit.generateVertexEffect(vertices,corners,indices,centers,indices);
       }
-
-    return FactoryCubit.generateVertexEffect(vertices,corners,indices,centers,indices);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -575,16 +599,7 @@ public class TwistyPenrose extends ShapeHexahedron
 
   public float[][][] getStickerAngles()
     {
-    float D = (float)(Math.PI/4);
-
-    return new float[][][]
-      {
-        {{ 0,0,0,0 }},
-        {{ 0,0,D }},
-        {{ 0,0,0,0 }},
-        {{ 0,0,0,0 }},
-        {{ 0,0,0,0 }}
-      };
+    return null;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
