commit 47d98cd582cf2e2c704a6aebab66d6d849c6b3e0
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Tue Aug 17 17:30:20 2021 +0200

    Convert the Ivy corner cubit to the new, 'universal' cubit creation method.
    
    This forces deep changes to 'createRoundSolid' and the underlying 'MeshPolygon' class to make them support arbitrary Polygon 'centers of face convexity'.
    
    Reason: the faces of this cubit are concave and such default 'center of face convexity' (which by default used to be (0,0)) turned to lie outside the face - which produces strange visual artifacts.

diff --git a/src/main/java/org/distorted/helpers/FactoryCubit.java b/src/main/java/org/distorted/helpers/FactoryCubit.java
index e1d95d9b..c5113973 100644
--- a/src/main/java/org/distorted/helpers/FactoryCubit.java
+++ b/src/main/java/org/distorted/helpers/FactoryCubit.java
@@ -809,19 +809,54 @@ public class FactoryCubit
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void computeConvexityCenter(double[] out, float[] in, FaceTransform ft)
+    {
+    if( in==null )
+      {
+      out[0] = out[1] = 0.0f;
+      }
+    else
+      {
+      out[0] = in[0] - ft.vx;
+      out[1] = in[1] - ft.vy;
+      out[2] = in[2] - ft.vz;
+      out[3] = 1.0f;
+
+      mQuat1[0] =-ft.qx;
+      mQuat1[1] =-ft.qy;
+      mQuat1[2] =-ft.qz;
+      mQuat1[3] = ft.qw;
+
+      mQuat2[0] = -mQuat1[0];
+      mQuat2[1] = -mQuat1[1];
+      mQuat2[2] = -mQuat1[2];
+      mQuat2[3] = +mQuat1[3];
+
+      quatMultiply(mQuat1, out  , mQuat3);
+      quatMultiply(mQuat3, mQuat2, out  );
+
+      out[0] /= ft.scale;
+      out[1] /= ft.scale;
+      out[2] /= ft.scale;
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
                                      final float[][] bands    , final int[]   bandIndexes,
                                      final float[][] corners  , final int[]   cornerIndexes,
                                      final float[][] centers  , final int[]   centerIndexes,
-                                     final int numComponents )
+                                     final int numComponents  , final float[] convexityCenter )
     {
     int numFaces = vertIndexes.length;
     float[] band, bandsComputed;
     MeshBase[] meshes = new MeshBase[numFaces];
     FaceTransform fInfo;
     StickerCoords sInfo;
+    double[] convexXY = new double[4];
 
     for(int face=0; face<numFaces; face++)
       {
@@ -833,9 +868,11 @@ public class FactoryCubit
       float[] vertsFloat = new float[lenVerts];
       for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
 
+      computeConvexityCenter(convexXY,convexityCenter,fInfo);
+
       band = bands[bandIndexes[face]];
       bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
-      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
+      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6], (float)convexXY[0], (float)convexXY[1]);
       meshes[face].setEffectAssociation(0,(1<<face),0);
       }
 
diff --git a/src/main/java/org/distorted/objects/ObjectList.java b/src/main/java/org/distorted/objects/ObjectList.java
index c65bdd60..16b926d2 100644
--- a/src/main/java/org/distorted/objects/ObjectList.java
+++ b/src/main/java/org/distorted/objects/ObjectList.java
@@ -168,7 +168,7 @@ public enum ObjectList
 
   IVY  (
          new int[][] {
-                       {2 , 8, 8, R.raw.ivy, R.drawable.ui_small_ivy, R.drawable.ui_medium_ivy, R.drawable.ui_big_ivy, R.drawable.ui_huge_ivy} ,
+                       {2 , 8, 8, 0, R.drawable.ui_small_ivy, R.drawable.ui_medium_ivy, R.drawable.ui_big_ivy, R.drawable.ui_huge_ivy} ,
                      },
          TwistyIvy.class,
          new MovementIvy(),
diff --git a/src/main/java/org/distorted/objects/TwistyBandagedAbstract.java b/src/main/java/org/distorted/objects/TwistyBandagedAbstract.java
index a04324b7..6e2581d6 100644
--- a/src/main/java/org/distorted/objects/TwistyBandagedAbstract.java
+++ b/src/main/java/org/distorted/objects/TwistyBandagedAbstract.java
@@ -277,7 +277,7 @@ abstract class TwistyBandagedAbstract extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       }
 
diff --git a/src/main/java/org/distorted/objects/TwistyCube.java b/src/main/java/org/distorted/objects/TwistyCube.java
index d824f456..f527bfb5 100644
--- a/src/main/java/org/distorted/objects/TwistyCube.java
+++ b/src/main/java/org/distorted/objects/TwistyCube.java
@@ -180,7 +180,7 @@ class TwistyCube extends TwistyObject
                                                   bands, bandIndexes,
                                                   corners, cornerIndexes,
                                                   centers, centerIndexes,
-                                                  getNumCubitFaces() );
+                                                  getNumCubitFaces(), null );
       }
 
     return mMeshes[index].copy(true);
diff --git a/src/main/java/org/distorted/objects/TwistyDiamond.java b/src/main/java/org/distorted/objects/TwistyDiamond.java
index 884bd27b..c3c7feca 100644
--- a/src/main/java/org/distorted/objects/TwistyDiamond.java
+++ b/src/main/java/org/distorted/objects/TwistyDiamond.java
@@ -433,7 +433,7 @@ public class TwistyDiamond extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[0].copy(true);
       }
@@ -455,7 +455,7 @@ public class TwistyDiamond extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[1].copy(true);
       }
diff --git a/src/main/java/org/distorted/objects/TwistyDino.java b/src/main/java/org/distorted/objects/TwistyDino.java
index 904b9428..82c2834f 100644
--- a/src/main/java/org/distorted/objects/TwistyDino.java
+++ b/src/main/java/org/distorted/objects/TwistyDino.java
@@ -210,7 +210,7 @@ public abstract class TwistyDino extends TwistyObject
                                               bands, bandIndexes,
                                               corners, cornerIndexes,
                                               centers, centerIndexes,
-                                              getNumCubitFaces() );
+                                              getNumCubitFaces(), null );
       }
 
     MeshBase mesh = mMeshes[0].copy(true);
diff --git a/src/main/java/org/distorted/objects/TwistyHelicopter.java b/src/main/java/org/distorted/objects/TwistyHelicopter.java
index 26768093..c7b35e72 100644
--- a/src/main/java/org/distorted/objects/TwistyHelicopter.java
+++ b/src/main/java/org/distorted/objects/TwistyHelicopter.java
@@ -338,7 +338,7 @@ public class TwistyHelicopter extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[0].copy(true);
       }
@@ -363,7 +363,7 @@ public class TwistyHelicopter extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[1].copy(true);
       }
diff --git a/src/main/java/org/distorted/objects/TwistyIvy.java b/src/main/java/org/distorted/objects/TwistyIvy.java
index 277d2d62..de09bb14 100644
--- a/src/main/java/org/distorted/objects/TwistyIvy.java
+++ b/src/main/java/org/distorted/objects/TwistyIvy.java
@@ -24,17 +24,10 @@ import android.content.res.Resources;
 import org.distorted.helpers.FactoryCubit;
 import org.distorted.helpers.ObjectSticker;
 import org.distorted.library.effect.MatrixEffectQuaternion;
-import org.distorted.library.effect.VertexEffect;
-import org.distorted.library.effect.VertexEffectMove;
-import org.distorted.library.effect.VertexEffectRotate;
-import org.distorted.library.effect.VertexEffectScale;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.mesh.MeshBase;
-import org.distorted.library.mesh.MeshJoined;
-import org.distorted.library.mesh.MeshPolygon;
 import org.distorted.library.mesh.MeshSquare;
-import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 import org.distorted.main.R;
@@ -46,9 +39,7 @@ import java.util.Random;
 public class TwistyIvy extends TwistyObject
 {
   public static final float IVY_D = 0.003f;
-  public static final float IVY_C = 0.59f;
-  public static final float IVY_M = 0.35f;
-  private static final int IVY_N = 8;
+  private static final int  IVY_N = 8;
 
   private static final int FACES_PER_CUBIT =6;
 
@@ -90,10 +81,10 @@ public class TwistyIvy extends TwistyObject
 
   private static final int[][] mFaceMap =
          {
-           {  4, 2, 0, 12,12,12 },
-           {  5, 2, 1, 12,12,12 },
-           {  4, 3, 1, 12,12,12 },
-           {  5, 3, 0, 12,12,12 },
+           {  4, 0, 2, 12,12,12 },
+           {  5, 1, 2, 12,12,12 },
+           {  4, 1, 3, 12,12,12 },
+           {  5, 0, 3, 12,12,12 },
 
            {  6, 12,12,12,12,12 },
            {  7, 12,12,12,12,12 },
@@ -105,26 +96,27 @@ public class TwistyIvy extends TwistyObject
 
   private static MeshBase mCornerMesh, mFaceMesh;
 
-  private static final int NUM_STICKERS = 2;
   private static final ObjectSticker[] mStickers;
 
+  private static final float[][] STICKERS = new float[][]
+          {
+             { 0.29258922f, -0.5f, 0.29258922f, 0.29258922f, -0.5f, 0.29258922f },
+             { -0.5f, 0.5f, 0.5f, -0.5f }
+          };
+  private static final int NUM_STICKERS = STICKERS.length;
+
   static
     {
     mStickers = new ObjectSticker[NUM_STICKERS];
 
-    float A = (+0.5f-IVY_M)*IVY_C;
-    float B = (-0.5f-IVY_M)*IVY_C;
-    float C = 0.50f-IVY_D;
     float D = (float)(Math.PI/4);
-
-    final float[][] coords = { {A,B,A,A,B,A},{-C,C,C,-C} };
     final float[][] angles = { { 0,0,D },{ D,D } };
     final float[][] radii  = { { 0,0.02f,0 },{ 0.06f,0.06f } };
     final float[] strokes = { 0.03f, 0.08f };
 
     for(int s=0; s<NUM_STICKERS; s++)
       {
-      mStickers[s] = new ObjectSticker(coords[s],angles[s],radii[s],strokes[s]);
+      mStickers[s] = new ObjectSticker(STICKERS[s], angles[s],radii[s],strokes[s]);
       }
     }
 
@@ -231,156 +223,6 @@ public class TwistyIvy extends TwistyObject
     return 0;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  MeshBase createFacesIvyCorner()
-    {
-    MeshBase[] meshes = new MeshBase[6];
-
-    final float angle = (float)Math.PI/(2*IVY_N);
-    final float CORR  = 1.0f - 2*IVY_D;
-    final float DIST  = -0.5f*CORR + IVY_D;
-    float[] vertices  = new float[2*(IVY_N+1)+6];
-
-    vertices[0] = (0.5f-IVY_M) * IVY_C;
-    vertices[1] = (DIST-IVY_M) * IVY_C;
-    vertices[2] = (0.5f-IVY_M) * IVY_C;
-    vertices[3] = (0.5f-IVY_M) * IVY_C;
-    vertices[4] = (DIST-IVY_M) * IVY_C;
-    vertices[5] = (0.5f-IVY_M) * IVY_C;
-
-    for(int i=0; i<=IVY_N; i++)
-      {
-      float ang = (IVY_N-i)*angle;
-      float sin = (float)Math.sin(ang);
-      float cos = (float)Math.cos(ang);
-
-      vertices[2*i+6] = (CORR*(cos-0.5f)-IVY_M)*IVY_C;
-      vertices[2*i+7] = (CORR*(sin-0.5f)-IVY_M)*IVY_C;
-      }
-
-    FactoryCubit factory = FactoryCubit.getInstance();
-    float[] bands0 = factory.computeBands(+0.012f,20,0.2f,0.5f,7);
-    float[] bands1 = factory.computeBands(-0.100f,20,0.2f,0.0f,2);
-
-    meshes[0] = new MeshPolygon(vertices,bands0,1,2);
-    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(vertices,bands1,1,2);
-    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);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private VertexEffect[] createVertexEffectsIvyCorner()
-    {
-    Static3D axisX  = new Static3D(1,0,0);
-    Static3D axisY  = new Static3D(0,1,0);
-    Static1D angle1 = new Static1D(+90);
-    Static1D angle2 = new Static1D(-90);
-    Static3D center = new Static3D(0,0,0);
-    Static3D move1  = new Static3D(IVY_M-0.5f,IVY_M-0.5f,0);
-
-    VertexEffect[] effect = new VertexEffect[5];
-
-    effect[0] = new VertexEffectScale(1/IVY_C);
-    effect[1] = new VertexEffectMove(move1);
-    effect[2] = new VertexEffectScale(new Static3D(1,1,-1));
-    effect[3] = new VertexEffectRotate(angle1,axisX,center);
-    effect[4] = new VertexEffectRotate(angle2,axisY,center);
-
-    effect[2].setMeshAssociation(54,-1);  // meshes 1,2,4,5
-    effect[3].setMeshAssociation(18,-1);  // meshes 1,4
-    effect[4].setMeshAssociation(36,-1);  // meshes 2,5
-
-    return effect;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private MeshBase createFacesIvyFace()
-    {
-    MeshBase[] meshes = new MeshBase[2];
-
-    final float angle = (float)Math.PI/(2*IVY_N);
-    final float CORR  = 1.0f - 2*IVY_D;
-    float[] vertices = new float[4*IVY_N];
-
-    for(int i=0; i<IVY_N; i++)
-      {
-      float sin = (float)Math.sin(i*angle);
-      float cos = (float)Math.cos(i*angle);
-
-      vertices[2*i          ] = CORR*(0.5f-cos);
-      vertices[2*i+1        ] = CORR*(0.5f-sin);
-      vertices[2*i  +2*IVY_N] = CORR*(cos-0.5f);
-      vertices[2*i+1+2*IVY_N] = CORR*(sin-0.5f);
-      }
-
-    FactoryCubit factory = FactoryCubit.getInstance();
-    float[] bands0 = factory.computeBands(+0.03f,35,0.5f,0.5f,5);
-    float[] bands1 = factory.computeBands(-0.10f,45,0.5f,0.0f,2);
-
-    meshes[0] = new MeshPolygon(vertices,bands0,0,0);
-    meshes[0].setEffectAssociation(0,1,0);
-    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
-    meshes[1].setEffectAssociation(0,2,0);
-
-    return new MeshJoined(meshes);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private MeshBase createIvyFaceMesh()
-    {
-    MeshBase mesh = createFacesIvyFace();
-
-    Static3D center = new Static3D(-0.0f,-0.0f,-0.5f);
-    Static3D[] vertices = new Static3D[2];
-    vertices[0] = new Static3D(-0.5f,+0.5f,+0.0f);
-    vertices[1] = new Static3D(+0.5f,-0.5f,+0.0f);
-
-    FactoryCubit.getInstance().roundCorners(mesh,center,vertices,0.03f,0.10f);
-
-    mesh.mergeEffComponents();
-    mesh.addEmptyTexComponent();
-    mesh.addEmptyTexComponent();
-    mesh.addEmptyTexComponent();
-    mesh.addEmptyTexComponent();
-
-    return mesh;
-    }
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private MeshBase createIvyCornerMesh()
-    {
-    MeshBase mesh = createFacesIvyCorner();
-    VertexEffect[] effects = createVertexEffectsIvyCorner();
-    for( VertexEffect effect : effects ) mesh.apply(effect);
-
-    Static3D center = new Static3D(-0.5f,-0.5f,-0.5f);
-    Static3D[] vertices = new Static3D[4];
-    vertices[0] = new Static3D(+0.0f,+0.0f,+0.0f);
-    vertices[1] = new Static3D(-1.0f,+0.0f,+0.0f);
-    vertices[2] = new Static3D(+0.0f,-1.0f,+0.0f);
-    vertices[3] = new Static3D(+0.0f,+0.0f,-1.0f);
-
-    FactoryCubit.getInstance().roundCorners(mesh,center,vertices,0.03f,0.10f);
-
-    mesh.mergeEffComponents();
-
-    return mesh;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   MeshBase createCubitMesh(int cubit, int numLayers)
@@ -389,12 +231,171 @@ public class TwistyIvy extends TwistyObject
 
     if( cubit<4 )
       {
-      if( mCornerMesh==null ) mCornerMesh = createIvyCornerMesh();
+      if( mCornerMesh==null )
+        {
+        final float angle = (float)Math.PI/(2*IVY_N);
+        final float CORR  = 1.0f - 2*IVY_D;
+
+        float[][] centers= new float[][] { {-0.5f,-0.5f,-0.5f} };
+        float[][] corners= new float[][] { {0.03f,0.10f}, {0.02f,0.10f} };
+        int[] cornerIndexes= new int[3*(IVY_N+1)+4];
+        int[] centerIndexes= new int[3*(IVY_N+1)+4];
+        double[][] vertices= new double[3*(IVY_N+1)+4][3];
+        int[][] vertIndexes= new int[6][IVY_N+4];
+        int[] bandIndexes= new int[] { 0,0,0,1,1,1 };
+
+        float[][] bands =
+          {
+               {+0.012f,20,0.2f,0.5f,7,1,2},
+               {-0.100f,20,0.2f,0.0f,2,1,2}
+          };
+
+        for(int i=0; i<3*(IVY_N+1); i++)
+          {
+          cornerIndexes[i+4] = -1;
+          centerIndexes[i+4] = -1;
+          }
+        cornerIndexes[0] = 1;
+        cornerIndexes[1] = 0;
+        cornerIndexes[2] = 0;
+        cornerIndexes[3] = 0;
+
+        centerIndexes[0] = 0;
+        centerIndexes[1] = 0;
+        centerIndexes[2] = 0;
+        centerIndexes[3] = 0;
+
+        vertices[0][0] = 0.0;
+        vertices[0][1] = 0.0;
+        vertices[0][2] = 0.0;
+        vertices[1][0] =-1.0;
+        vertices[1][1] = 0.0;
+        vertices[1][2] = 0.0;
+        vertices[2][0] = 0.0;
+        vertices[2][1] =-1.0;
+        vertices[2][2] = 0.0;
+        vertices[3][0] = 0.0;
+        vertices[3][1] = 0.0;
+        vertices[3][2] =-1.0;
+
+        vertIndexes[0][0] = 2;
+        vertIndexes[0][1] = 0;
+        vertIndexes[0][2] = 1;
+        vertIndexes[3][0] = 2;
+        vertIndexes[3][1] = 0;
+        vertIndexes[3][2] = 1;
+
+        vertIndexes[1][0] = 3;
+        vertIndexes[1][1] = 0;
+        vertIndexes[1][2] = 2;
+        vertIndexes[4][0] = 3;
+        vertIndexes[4][1] = 0;
+        vertIndexes[4][2] = 2;
+
+        vertIndexes[2][0] = 1;
+        vertIndexes[2][1] = 0;
+        vertIndexes[2][2] = 3;
+        vertIndexes[5][0] = 1;
+        vertIndexes[5][1] = 0;
+        vertIndexes[5][2] = 3;
+
+        int N1 = 4;
+        int N2 = N1 + IVY_N + 1;
+        int N3 = N2 + IVY_N + 1;
+
+        for(int i=0; i<=IVY_N; i++)
+          {
+          double cos1 = Math.cos((IVY_N-i)*angle);
+          double sin1 = Math.sin((IVY_N-i)*angle);
+          double cos2 = Math.cos((      i)*angle);
+          double sin2 = Math.sin((      i)*angle);
+
+          vertices[N1+i][0] = CORR*(cos1-0.5) - 0.5;
+          vertices[N1+i][1] = CORR*(sin1-0.5) - 0.5;
+          vertices[N1+i][2] = 0.0;
+
+          vertices[N2+i][0] = 0.0;
+          vertices[N2+i][1] = CORR*(sin2-0.5) - 0.5;
+          vertices[N2+i][2] = CORR*(cos2-0.5) - 0.5;
+
+          vertices[N3+i][0] = CORR*(cos2-0.5) - 0.5;
+          vertices[N3+i][1] = 0.0;
+          vertices[N3+i][2] = CORR*(sin2-0.5) - 0.5;
+
+          vertIndexes[0][i+3] = N1 + i;
+          vertIndexes[1][i+3] = N2 + i;
+          vertIndexes[2][i+3] = N3 + i;
+          vertIndexes[3][i+3] = N1 + i;
+          vertIndexes[4][i+3] = N2 + i;
+          vertIndexes[5][i+3] = N3 + i;
+          }
+
+        float C = 0.5f - SQ2/4;
+        float[] convexCenter = new float[] {-C,-C,-C};
+
+        FactoryCubit factory = FactoryCubit.getInstance();
+        factory.createNewFaceTransform(vertices,vertIndexes);
+        mCornerMesh = factory.createRoundedSolid(vertices, vertIndexes,
+                                                 bands, bandIndexes,
+                                                 corners, cornerIndexes,
+                                                 centers, centerIndexes,
+                                                 getNumCubitFaces(), convexCenter );
+        }
       mesh = mCornerMesh.copy(true);
       }
     else
       {
-      if( mFaceMesh==null ) mFaceMesh = createIvyFaceMesh();
+      if( mFaceMesh==null )
+        {
+        final float angle = (float)Math.PI/(2*IVY_N);
+        final float CORR  = 1.0f - 2*IVY_D;
+        double[][] vertices = new double[2*IVY_N][3];
+        int[][] vert_indices = new int[2][2*IVY_N];
+
+        int[] bandIndexes= new int[] { 0,1 };
+        int[] indexes    = new int[2*IVY_N];
+        float[][] corners= new float[][] { {0.03f,0.10f} };
+        float[][] centers= new float[][] { {-0.0f,-0.0f,-0.5f} };
+
+        for(int i=0; i<IVY_N; i++)
+          {
+          double sin = Math.sin(i*angle);
+          double cos = Math.cos(i*angle);
+
+          vertices[i      ][0] = CORR*(0.5f-cos);
+          vertices[i      ][1] = CORR*(0.5f-sin);
+          vertices[i      ][2] = 0;
+          vertices[i+IVY_N][0] = CORR*(cos-0.5f);
+          vertices[i+IVY_N][1] = CORR*(sin-0.5f);
+          vertices[i+IVY_N][2] = 0;
+          }
+
+        for(int i=0; i<2*IVY_N; i++)
+          {
+          vert_indices[0][i] = i;
+          vert_indices[1][i] = 2*IVY_N-1-i;
+          }
+
+        for(int i=0; i<2*IVY_N; i++)
+          {
+          indexes[i] = -1;
+          }
+        indexes[0] = indexes[IVY_N] = 0;
+
+        float[][] bands =
+          {
+               {+0.03f,35,0.5f,0.5f,5,0,0},
+               {+0.10f,45,0.5f,0.0f,2,0,0}
+          };
+
+        FactoryCubit factory = FactoryCubit.getInstance();
+        factory.createNewFaceTransform(vertices,vert_indices);
+        mFaceMesh = factory.createRoundedSolid(vertices, vert_indices,
+                                                bands, bandIndexes,
+                                                corners, indexes,
+                                                centers, indexes,
+                                                getNumCubitFaces(), null );
+        }
       mesh = mFaceMesh.copy(true);
       }
 
diff --git a/src/main/java/org/distorted/objects/TwistyJing.java b/src/main/java/org/distorted/objects/TwistyJing.java
index b01a9aba..76b3a4be 100644
--- a/src/main/java/org/distorted/objects/TwistyJing.java
+++ b/src/main/java/org/distorted/objects/TwistyJing.java
@@ -322,7 +322,7 @@ public class TwistyJing extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[0].copy(true);
       }
@@ -344,7 +344,7 @@ public class TwistyJing extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
 
         factory.printStickerCoords();
         }
@@ -369,7 +369,7 @@ public class TwistyJing extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
 
         factory.printStickerCoords();
         }
diff --git a/src/main/java/org/distorted/objects/TwistyKilominx.java b/src/main/java/org/distorted/objects/TwistyKilominx.java
index 4ed25ae1..df72d84f 100644
--- a/src/main/java/org/distorted/objects/TwistyKilominx.java
+++ b/src/main/java/org/distorted/objects/TwistyKilominx.java
@@ -424,7 +424,7 @@ public class TwistyKilominx extends TwistyMinx
                                       bands, bandIndexes,
                                       corners, cornerIndexes,
                                       centers, centerIndexes,
-                                      getNumCubitFaces() );
+                                      getNumCubitFaces(), null );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -496,7 +496,7 @@ public class TwistyKilominx extends TwistyMinx
                                       bands, bandIndexes,
                                       corners, cornerIndexes,
                                       centers, centerIndexes,
-                                      getNumCubitFaces() );
+                                      getNumCubitFaces(), null );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyMegaminx.java b/src/main/java/org/distorted/objects/TwistyMegaminx.java
index 5235559a..83908535 100644
--- a/src/main/java/org/distorted/objects/TwistyMegaminx.java
+++ b/src/main/java/org/distorted/objects/TwistyMegaminx.java
@@ -350,7 +350,7 @@ public class TwistyMegaminx extends TwistyMinx
                                       bands, bandIndexes,
                                       corners, cornerIndexes,
                                       centers, centerIndexes,
-                                      getNumCubitFaces() );
+                                      getNumCubitFaces(), null );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -403,7 +403,7 @@ public class TwistyMegaminx extends TwistyMinx
                                       bands, bandIndexes,
                                       corners, cornerIndexes,
                                       centers, centerIndexes,
-                                      getNumCubitFaces() );
+                                      getNumCubitFaces(), null );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyMinx.java b/src/main/java/org/distorted/objects/TwistyMinx.java
index d96fb8ad..34620d83 100644
--- a/src/main/java/org/distorted/objects/TwistyMinx.java
+++ b/src/main/java/org/distorted/objects/TwistyMinx.java
@@ -427,7 +427,7 @@ abstract class TwistyMinx extends TwistyObject
                                       bands, bandIndexes,
                                       corners, cornerIndexes,
                                       centers, centerIndexes,
-                                      getNumCubitFaces() );
+                                      getNumCubitFaces(), null );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyPyraminx.java b/src/main/java/org/distorted/objects/TwistyPyraminx.java
index c2b786bd..7d233b72 100644
--- a/src/main/java/org/distorted/objects/TwistyPyraminx.java
+++ b/src/main/java/org/distorted/objects/TwistyPyraminx.java
@@ -333,7 +333,7 @@ public class TwistyPyraminx extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[0].copy(true);
       }
@@ -355,7 +355,7 @@ public class TwistyPyraminx extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
 
         factory.printStickerCoords();
         }
diff --git a/src/main/java/org/distorted/objects/TwistyRedi.java b/src/main/java/org/distorted/objects/TwistyRedi.java
index baa96d48..4dc8d76d 100644
--- a/src/main/java/org/distorted/objects/TwistyRedi.java
+++ b/src/main/java/org/distorted/objects/TwistyRedi.java
@@ -340,7 +340,7 @@ public class TwistyRedi extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[0].copy(true);
       }
@@ -366,7 +366,7 @@ public class TwistyRedi extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[1].copy(true);
       }
diff --git a/src/main/java/org/distorted/objects/TwistySkewb.java b/src/main/java/org/distorted/objects/TwistySkewb.java
index c471e9f4..596a97a7 100644
--- a/src/main/java/org/distorted/objects/TwistySkewb.java
+++ b/src/main/java/org/distorted/objects/TwistySkewb.java
@@ -502,7 +502,7 @@ public class TwistySkewb extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[0].copy(true);
       }
@@ -527,7 +527,7 @@ public class TwistySkewb extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[1].copy(true);
       }
@@ -552,7 +552,7 @@ public class TwistySkewb extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[2].copy(true);
       }
diff --git a/src/main/java/org/distorted/objects/TwistySquare.java b/src/main/java/org/distorted/objects/TwistySquare.java
index 3f698245..3630b207 100644
--- a/src/main/java/org/distorted/objects/TwistySquare.java
+++ b/src/main/java/org/distorted/objects/TwistySquare.java
@@ -191,7 +191,7 @@ abstract class TwistySquare extends TwistyObject
                                               bands, bandIndexes,
                                               corners, cornerIndexes,
                                               centers, centerIndexes,
-                                              getNumCubitFaces() );
+                                              getNumCubitFaces(), null );
       }
 
     return mMeshes[0].copy(true);
@@ -220,7 +220,7 @@ abstract class TwistySquare extends TwistyObject
                                                bands, bandIndexes,
                                                corners, cornerIndexes,
                                                centers, centerIndexes,
-                                               getNumCubitFaces() );
+                                               getNumCubitFaces(), null );
        }
     return mMeshes[1].copy(true);
     }
diff --git a/src/main/java/org/distorted/objects/TwistySquare1.java b/src/main/java/org/distorted/objects/TwistySquare1.java
index 78a1cf2d..7c1cb245 100644
--- a/src/main/java/org/distorted/objects/TwistySquare1.java
+++ b/src/main/java/org/distorted/objects/TwistySquare1.java
@@ -209,7 +209,7 @@ class TwistySquare1 extends TwistySquare
                                               bands, bandIndexes,
                                               corners, cornerIndexes,
                                               centers, centerIndexes,
-                                              getNumCubitFaces() );
+                                              getNumCubitFaces(), null );
       }
     return mMeshes[2].copy(true);
     }
diff --git a/src/main/java/org/distorted/objects/TwistySquare2.java b/src/main/java/org/distorted/objects/TwistySquare2.java
index 77fc6e91..4b8a37c8 100644
--- a/src/main/java/org/distorted/objects/TwistySquare2.java
+++ b/src/main/java/org/distorted/objects/TwistySquare2.java
@@ -214,7 +214,7 @@ class TwistySquare2 extends TwistySquare
                                               bands, bandIndexes,
                                               corners, cornerIndexes,
                                               centers, centerIndexes,
-                                              getNumCubitFaces() );
+                                              getNumCubitFaces(), null );
       }
     return mMeshes[3].copy(true);
     }
diff --git a/src/main/java/org/distorted/objects/TwistyUltimate.java b/src/main/java/org/distorted/objects/TwistyUltimate.java
index 6248be82..feca45a3 100644
--- a/src/main/java/org/distorted/objects/TwistyUltimate.java
+++ b/src/main/java/org/distorted/objects/TwistyUltimate.java
@@ -278,7 +278,7 @@ class TwistyUltimate extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[0].copy(true);
       }
@@ -303,7 +303,7 @@ class TwistyUltimate extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[1].copy(true);
       }
@@ -329,7 +329,7 @@ class TwistyUltimate extends TwistyObject
                                                 bands, bandIndexes,
                                                 corners, cornerIndexes,
                                                 centers, centerIndexes,
-                                                getNumCubitFaces() );
+                                                getNumCubitFaces(), null );
         }
       mesh = mMeshes[2].copy(true);
       }
