commit 6983badfa5f3621a2f9c4831de902f656f600014
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Apr 18 22:06:17 2021 +0200

    Port bugfixes from DistortedCube; add Ivy Corner & Ivy Face meshes.

diff --git a/src/main/java/org/distorted/examples/meshfile/FactoryCubit.java b/src/main/java/org/distorted/examples/meshfile/FactoryCubit.java
index 1a97aa2..215148d 100644
--- a/src/main/java/org/distorted/examples/meshfile/FactoryCubit.java
+++ b/src/main/java/org/distorted/examples/meshfile/FactoryCubit.java
@@ -47,12 +47,12 @@ class FactoryCubit
 
   private static FactoryCubit mThis;
 
-  private static class StickerInfo
+  private static class StickerCoords
     {
     double[] vertices;
     }
 
-  private static class FaceInfo
+  private static class FaceTransform
     {
     int sticker;
     double vx,vy,vz;
@@ -61,8 +61,10 @@ class FactoryCubit
     boolean flip;
     }
 
-  private static final ArrayList<FaceInfo>       mFaceInfo = new ArrayList<>();
-  private static final ArrayList<StickerInfo> mStickerInfo = new ArrayList<>();
+  private static final ArrayList<FaceTransform> mNewFaceTransf = new ArrayList<>();
+  private static final ArrayList<FaceTransform> mOldFaceTransf = new ArrayList<>();
+  private static final ArrayList<StickerCoords> mStickerCoords = new ArrayList<>();
+
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -290,7 +292,7 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void fitInSquare(FaceInfo info, double[][] vert3D)
+  private void fitInSquare(FaceTransform info, double[][] vert3D)
     {
     double minX = Double.MAX_VALUE;
     double maxX =-Double.MAX_VALUE;
@@ -320,7 +322,7 @@ class FactoryCubit
     info.scale = max3/0.5;
 
     int len = vert3D.length;
-    StickerInfo sInfo = new StickerInfo();
+    StickerCoords sInfo = new StickerCoords();
     sInfo.vertices = new double[2*len];
 
     for( int vertex=0; vertex<len; vertex++ )
@@ -329,39 +331,41 @@ class FactoryCubit
       sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
       }
 
-    mStickerInfo.add(sInfo);
+    mStickerCoords.add(sInfo);
 
-    info.sticker = mStickerInfo.size() -1;
+    info.sticker = mStickerCoords.size() -1;
     info.flip = false;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void constructNew(FaceInfo info, final double[][] vert3D)
+  private FaceTransform constructNewTransform(final double[][] vert3D)
     {
+    FaceTransform ft = new FaceTransform();
+
     // compute center of gravity
-    info.vx = 0.0f;
-    info.vy = 0.0f;
-    info.vz = 0.0f;
+    ft.vx = 0.0f;
+    ft.vy = 0.0f;
+    ft.vz = 0.0f;
     int len = vert3D.length;
 
     for (double[] vert : vert3D)
       {
-      info.vx += vert[0];
-      info.vy += vert[1];
-      info.vz += vert[2];
+      ft.vx += vert[0];
+      ft.vy += vert[1];
+      ft.vz += vert[2];
       }
 
-    info.vx /= len;
-    info.vy /= len;
-    info.vz /= len;
+    ft.vx /= len;
+    ft.vy /= len;
+    ft.vz /= len;
 
     // move all vertices so that their center of gravity is at (0,0,0)
     for (int i=0; i<len; i++)
       {
-      vert3D[i][0] -= info.vx;
-      vert3D[i][1] -= info.vy;
-      vert3D[i][2] -= info.vz;
+      vert3D[i][0] -= ft.vx;
+      vert3D[i][1] -= ft.vy;
+      vert3D[i][2] -= ft.vz;
       }
 
     // find 3 non-colinear vertices
@@ -427,13 +431,15 @@ class FactoryCubit
       }
 
     // fit the whole thing in a square and remember the scale & 2D vertices
-    fitInSquare(info, vert3D);
+    fitInSquare(ft, vert3D);
 
     // remember the rotation
-    info.qx =-mQuat1[0];
-    info.qy =-mQuat1[1];
-    info.qz =-mQuat1[2];
-    info.qw = mQuat1[3];
+    ft.qx =-mQuat1[0];
+    ft.qy =-mQuat1[1];
+    ft.qz =-mQuat1[2];
+    ft.qw = mQuat1[3];
+
+    return ft;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -472,15 +478,21 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private double computeScale(double[] v1, double[] v2)
+  private double computeScale(double[] v1, double[] v2, int v1i, int v2i)
     {
-    double lenSq1 = v1[0]*v1[0] + v1[1]*v1[1];
-    double lenSq2 = v2[0]*v2[0] + v2[1]*v2[1];
+    double v1x = v1[2*v1i];
+    double v1y = v1[2*v1i+1];
+    double v2x = v2[2*v2i];
+    double v2y = v2[2*v2i+1];
+
+    double lenSq1 = v1x*v1x + v1y*v1y;
+    double lenSq2 = v2x*v2x + v2y*v2y;
 
     return Math.sqrt(lenSq2/lenSq1);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// valid for 0<angle<2*PI
 
   private double computeSinHalf(double cos)
     {
@@ -488,6 +500,7 @@ class FactoryCubit
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// valid for 0<angle<2*PI
 
   private double computeCosHalf(double sin, double cos)
     {
@@ -510,8 +523,9 @@ class FactoryCubit
 
   private boolean isScaledVersionOf(double[] newVert, double[] oldVert, int len, int vertex, boolean inverted)
     {
+    int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted);
     double EPSILON = 0.001;
-    double scale = computeScale(newVert,oldVert);
+    double scale = computeScale(newVert,oldVert,newZeroIndex,0);
 
     for(int i=1; i<len; i++)
       {
@@ -539,18 +553,18 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void correctInfo(FaceInfo info, double scale, double sin, double cos, int oldSticker, boolean flip)
+  private void correctTransform(FaceTransform ft, double scale, double sin, double cos, int oldSticker, boolean flip)
     {
-    mStickerInfo.remove(info.sticker);
+    mStickerCoords.remove(ft.sticker);
 
-    info.flip    = flip;
-    info.sticker = oldSticker;
-    info.scale  *= scale;
+    ft.flip    = flip;
+    ft.sticker = oldSticker;
+    ft.scale  *= scale;
 
-    mQuat1[0] = info.qx;
-    mQuat1[1] = info.qy;
-    mQuat1[2] = info.qz;
-    mQuat1[3] = info.qw;
+    mQuat1[0] = ft.qx;
+    mQuat1[1] = ft.qy;
+    mQuat1[2] = ft.qz;
+    mQuat1[3] = ft.qw;
 
     double sinHalf = computeSinHalf(cos);
     double cosHalf = computeCosHalf(sin,cos);
@@ -579,10 +593,10 @@ class FactoryCubit
 
     quatMultiply( mQuat1, mQuat2, mQuat3 );
 
-    info.qx = mQuat3[0];
-    info.qy = mQuat3[1];
-    info.qz = mQuat3[2];
-    info.qw = mQuat3[3];
+    ft.qx = mQuat3[0];
+    ft.qy = mQuat3[1];
+    ft.qz = mQuat3[2];
+    ft.qw = mQuat3[3];
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -602,7 +616,7 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private boolean foundVertex(FaceInfo info, double[] buffer, int len, double[] newVert,
+  private boolean foundVertex(FaceTransform ft, double[] buffer, int len, double[] newVert,
                               double[] oldVert, double lenFirstOld, int oldSticker, boolean inverted)
     {
     for(int vertex=0; vertex<len; vertex++)
@@ -617,8 +631,9 @@ class FactoryCubit
 
       if( isScaledVersionOf(buffer,oldVert,len,vertex,inverted) )
         {
-        double scale = computeScale(oldVert,newVert);
-        correctInfo(info,scale,sin,cos,oldSticker,inverted);
+        int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted);
+        double scale = computeScale(oldVert,newVert,0,newZeroIndex);
+        correctTransform(ft,scale,sin,cos,oldSticker,inverted);
         return true;
         }
       }
@@ -628,10 +643,10 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private boolean successfullyCollapsedStickers(final FaceInfo newInfo, final FaceInfo oldInfo)
+  private boolean successfullyCollapsedStickers(final FaceTransform newInfo, final FaceTransform oldInfo)
     {
-    StickerInfo sNewInfo = mStickerInfo.get(newInfo.sticker);
-    StickerInfo sOldInfo = mStickerInfo.get(oldInfo.sticker);
+    StickerCoords sNewInfo = mStickerCoords.get(newInfo.sticker);
+    StickerCoords sOldInfo = mStickerCoords.get(oldInfo.sticker);
     double[] newVert = sNewInfo.vertices;
     double[] oldVert = sOldInfo.vertices;
     int oldLen = oldVert.length;
@@ -671,147 +686,170 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void prepareFaceInfo( final double[][] vertices, final int[][] indexes)
-    {
-    mFaceInfo.clear();
-    mStickerInfo.clear();
-
-    int numFaces = indexes.length;
-    FaceInfo oldInfo;
-
-    for(int face=0; face<numFaces; face++)
-      {
-      FaceInfo newInfo = new FaceInfo();
-      int[] index = indexes[face];
-      double[][] vert = constructVert(vertices,index);
-      constructNew(newInfo,vert);
-
-      for(int previous=0; previous<face; previous++)
-        {
-        oldInfo = mFaceInfo.get(previous);
-        if( successfullyCollapsedStickers(newInfo,oldInfo) ) break;
-        }
-
-      mFaceInfo.add(newInfo);
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices, int[][] vertIndexes,
-                                      float[][] corners, int[] cornerIndexes )
+  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices,
+                                      float[][] corners, int[] cornerIndexes,
+                                      float[][] centers, int[] centerIndexes )
     {
-    int numNeig, lenFV;
     int lenV = vertices.length;
-    int[] verts = new int[2*(lenV-1)];
     Static3D[] staticVert = new Static3D[1];
     Static3D center = new Static3D(0,0,0);
-    double cx, cy, cz;
-    double[] singleV;
 
     for(int v=0; v<lenV; v++)
       {
-      // prepare verts[]
-      numNeig = 0;
+      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
 
-      for (int[] vertIndex : vertIndexes)
+      int cent = centerIndexes[v];
+
+      if( cent>=0 )
         {
-        lenFV = vertIndex.length;
+        center.set( centers[cent][0], centers[cent][1], centers[cent][2]);
 
-        for (int fv = 0; fv < lenFV; fv++)
-          if (vertIndex[fv] == v)
-            {
-            int prev = fv > 0 ? fv - 1 : lenFV - 1;
-            int next = fv < lenFV - 1 ? fv + 1 : 0;
+        int corn = cornerIndexes[v];
+        float strength = corners[corn][0];
+        float radius   = corners[corn][1];
 
-            verts[numNeig++] = vertIndex[prev];
-            verts[numNeig++] = vertIndex[next];
-            }
+        roundCorners(mesh, center, staticVert, strength, radius);
         }
+      }
+    }
 
-      cx=cy=cz=0.0f;
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-      // from verts[] prepare center
-      for(int n=0; n<numNeig; n++)
-        {
-        singleV = vertices[verts[n]];
+  private void correctComponents(MeshBase mesh, int numComponents)
+    {
+    int numTexToBeAdded = numComponents-mesh.getNumTexComponents();
 
-        cx += singleV[0];
-        cy += singleV[1];
-        cz += singleV[2];
-        }
-      center.set( (float)(cx/numNeig - vertices[v][0]),
-                  (float)(cy/numNeig - vertices[v][1]),
-                  (float)(cz/numNeig - vertices[v][2]));
+    //mesh.mergeEffComponents();
 
-      // round Corners
-      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
+    for(int i=0; i<numTexToBeAdded; i++ ) mesh.addEmptyTexComponent();
+    }
 
-      int corn = cornerIndexes[v];
-      float strength = corners[corn][0];
-      float radius   = corners[corn][1];
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-      roundCorners(mesh, center, staticVert, strength, radius);
-      }
+  private void printTransform(FaceTransform f)
+    {
+    android.util.Log.e("D", "q=("+f.qx+", "+f.qy+", "+f.qz+", "+f.qw+") v=("
+                       +f.vx+", "+f.vy+", "+f.vz+") scale="+f.scale+" sticker="+f.sticker);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC
 
-  private void printInfo()
+  public void printStickerCoords()
     {
-    int stickers = mStickerInfo.size();
+    int stickers = mStickerCoords.size();
 
-    android.util.Log.d("D", "-------------------------");
+    android.util.Log.d("D", "---- STICKER COORDS ----");
 
     for(int s=0; s<stickers; s++)
       {
-      String ver = "";
-      StickerInfo info = mStickerInfo.get(s);
+      String ver = "{ ";
+      StickerCoords info = mStickerCoords.get(s);
       int len = info.vertices.length/2;
 
       for(int i =0; i<len; i++)
         {
-        ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
+        if( i!=0 ) ver += ", ";
+        ver += ( (float)info.vertices[2*i]+"f, "+(float)info.vertices[2*i+1]+"f");
         }
 
-      android.util.Log.e("D", "sticker "+s+" "+ver);
+      ver += " }";
+      android.util.Log.d("D", ver);
       }
 
-    android.util.Log.d("D", "-------------------------");
+    android.util.Log.d("D", "---- END STICKER COORDS ----");
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void printFaceTransform()
+    {
+    android.util.Log.d("D", "---- OLD FACE TRANSFORM ---");
 
-    int faces = mFaceInfo.size();
+    int oldfaces = mOldFaceTransf.size();
 
-    for(int f=0; f<faces; f++)
+    for(int f=0; f<oldfaces; f++)
       {
-      FaceInfo info = mFaceInfo.get(f);
+      printTransform(mOldFaceTransf.get(f));
+      }
+
+    android.util.Log.d("D", "---- NEW FACE TRANSFORM ---");
 
-      android.util.Log.e("D", "q=("+info.qx+", "+info.qy+", "+info.qz+", "+info.qw+") v=("
-                       +info.vx+", "+info.vy+", "+info.vz+") scale="+info.scale+" sticker="+info.sticker);
+    int newfaces = mNewFaceTransf.size();
+
+    for(int f=0; f<newfaces; f++)
+      {
+      printTransform(mNewFaceTransf.get(f));
       }
+    }
 
-    android.util.Log.d("D", "-------------------------");
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void clear()
+    {
+    mStickerCoords.clear();
+    mNewFaceTransf.clear();
+    mOldFaceTransf.clear();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
-                              final float[][] bands    , final int[]   bandIndexes,
-                              final float[][] corners  , final int[]   cornerIndexes)
+  public void createNewFaceTransform( final double[][] vertices, final int[][] indexes)
     {
-    prepareFaceInfo(vertices,vertIndexes);
+    FaceTransform ft;
+    int numNew = mNewFaceTransf.size();
+
+    for(int i=0; i<numNew; i++)
+      {
+      ft = mNewFaceTransf.remove(0);
+      mOldFaceTransf.add(ft);
+      }
+
+    int numFaces = indexes.length;
+    int numOld = mOldFaceTransf.size();
+
+    for (int face=0; face<numFaces; face++)
+      {
+      boolean collapsed = false;
+
+      double[][] vert = constructVert(vertices, indexes[face]);
+
+      FaceTransform newT = constructNewTransform(vert);
+
+      for (int old=0; !collapsed && old<numOld; old++)
+        {
+        ft = mOldFaceTransf.get(old);
+        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
+        }
+
+      for (int pre=0; !collapsed && pre<face; pre++)
+        {
+        ft = mNewFaceTransf.get(pre);
+        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
+        }
 
+      mNewFaceTransf.add(newT);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  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 )
+    {
     int numFaces = vertIndexes.length;
     float[] band, bandsComputed;
     MeshBase[] meshes = new MeshBase[numFaces];
-    FaceInfo fInfo;
-    StickerInfo sInfo;
-
-    printInfo();
+    FaceTransform fInfo;
+    StickerCoords sInfo;
 
     for(int face=0; face<numFaces; face++)
       {
-      fInfo = mFaceInfo.get(face);
-      sInfo = mStickerInfo.get(fInfo.sticker);
+      fInfo = mNewFaceTransf.get(face);
+      sInfo = mStickerCoords.get(fInfo.sticker);
 
       double[] verts = sInfo.vertices;
       int lenVerts = verts.length;
@@ -830,7 +868,7 @@ class FactoryCubit
     for(int face=0; face<numFaces; face++)
       {
       int assoc = (1<<face);
-      fInfo = mFaceInfo.get(face);
+      fInfo = mNewFaceTransf.get(face);
 
       float vx = (float)fInfo.vx;
       float vy = (float)fInfo.vy;
@@ -850,7 +888,9 @@ class FactoryCubit
       mesh.apply(new MatrixEffectMove(move3D)           ,assoc,-1);
       }
 
-    prepareAndRoundCorners(mesh, vertices, vertIndexes, corners, cornerIndexes);
+    prepareAndRoundCorners(mesh, vertices, corners, cornerIndexes, centers, centerIndexes);
+
+    correctComponents(mesh,numComponents);
 
     return mesh;
     }
diff --git a/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java b/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java
index b39c198..a089cc3 100644
--- a/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java
+++ b/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java
@@ -252,13 +252,16 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
 
     private void createMesh()
       {
-      int mode = 4;
+      int mode = 6;
+      int numComponents = 0;
       double[][] vertices = null;
       int[][] vertIndexes = null;
       float[][] bands     = null;
       int[] bandIndexes   = null;
       float[][] corners   = null;
       int[] cornerIndexes = null;
+      float[][] centers   = null;
+      int[] centerIndexes = null;
 
       ///// CUBE ////////////////////////////////////////////////////////////////////////////////
 
@@ -299,6 +302,15 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
           };
 
         cornerIndexes = new int[] { 0,0,0,0,0,0,0,0 };
+
+        centers = new float[][]
+          {
+              { 0.0f, 0.0f, 0.0f }
+          };
+
+        centerIndexes = new int[] { 0,0,0,0,0,0,0,0 };
+
+        numComponents = 8;
         }
 
       ///// TETRAHEDRON //////////////////////////////////////////////////////////////////////////
@@ -334,6 +346,15 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
           };
 
         cornerIndexes = new int[] { 0,0,0,0 };
+
+        centers = new float[][]
+          {
+              { 0.0f, 0.0f, 0.0f }
+          };
+
+        centerIndexes = new int[] { 0,0,0,0 };
+
+        numComponents = 4;
         }
 
       ///// DINO ////////////////////////////////////////////////////////////////////////////////
@@ -366,10 +387,19 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
 
         corners = new float[][]
           {
-              { 0.01f, 0.04f }
+              { 0.02f, 0.04f }
           };
 
         cornerIndexes = new int[] { 0,0,0,0 };
+
+        centers = new float[][]
+          {
+              { 0.0f,-0.25f,-0.25f }
+          };
+
+        centerIndexes = new int[] { 0,0,0,0 };
+
+        numComponents = 4;
         }
 
       ///// OCTAHEDRON ////////////////////////////////////////////////////////////////////////////
@@ -411,6 +441,15 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
           };
 
         cornerIndexes = new int[] { 0,0,0,0,0,0 };
+
+        centers = new float[][]
+          {
+              { 0.0f, 0.0f, 0.0f }
+          };
+
+        centerIndexes = new int[] { 0,0,0,0,0,0 };
+
+        numComponents = 8;
         }
 
       ///// KILOMINX EDGE ////////////////////////////////////////////////////////////////////////
@@ -458,17 +497,210 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
 
         corners = new float[][]
           {
-              { 0.01f, 0.12f },
-              { 0.00f, 0.00f }
+              { 0.04f, 0.12f }
+          };
+
+        cornerIndexes = new int[] { 0,-1,-1,-1,0,-1,-1,-1 };
+
+        centers = new float[][]
+          {
+              { 0.0f, 0.0f, 0.0f }
+          };
+
+        centerIndexes = new int[] { 0,-1,-1,-1,0,-1,-1,-1 };
+
+        numComponents = 6;
+        }
+
+      ///// IVY_CORNER ////////////////////////////////////////////////////////////////////////
+
+      else if( mode==5 )
+        {
+        int IVY_N = 3;
+        final float IVY_D = 0.003f;
+        final double angle = Math.PI/(2*IVY_N);
+        final double CORR  = 1.0 - 2*IVY_D;
+
+        vertices = new double[3*IVY_N+7][3];
+        vertIndexes = new int[6][IVY_N+4];
+
+        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;
+          }
+
+        bands = new float[][]
+          {
+             {+0.012f,20,0.2f,0.5f,7,1,2},
+             {-0.100f,20,0.2f,0.0f,2,1,2}
+          };
+
+        bandIndexes = new int[] { 0,0,0,1,1,1 };
+
+        corners = new float[][]
+          {
+              { 0.04f, 0.12f }
+          };
+
+        cornerIndexes = new int[3*IVY_N+7];
+
+        centers = new float[][]
+          {
+              {-0.5f,-0.5f,-0.5f}
           };
 
-        cornerIndexes = new int[] { 0,1,1,1,0,1,1,1 };
+        centerIndexes = new int[3*IVY_N+7];
+
+        for(int i=0; i<4; i++)
+          {
+          cornerIndexes[i] = 0;
+          centerIndexes[i] = 0;
+          }
+        for(int i=4; i<3*IVY_N+7; i++)
+          {
+          cornerIndexes[i] = -1;
+          centerIndexes[i] = -1;
+          }
+
+        numComponents = 6;
+        }
+
+      ///// IVY_FACE ////////////////////////////////////////////////////////////////////////
+
+      else if( mode==6 )
+        {
+        int IVY_N = 6;
+        final float IVY_D = 0.003f;
+        final double angle = Math.PI/(2*IVY_N);
+        final double CORR  = 1.0 - 2*IVY_D;
+
+        vertices   = new double[2*IVY_N][3];
+        vertIndexes= new int[2][2*IVY_N];
+
+        for(int i=0; i<IVY_N; i++)
+          {
+          double cos = Math.cos(i*angle);
+          double sin = Math.sin(i*angle);
+
+          vertices[i      ][0] = CORR*(0.5-cos);
+          vertices[i      ][1] = CORR*(0.5-sin);
+          vertices[i      ][2] = 0.0;
+          vertices[i+IVY_N][0] = CORR*(cos-0.5);
+          vertices[i+IVY_N][1] = CORR*(sin-0.5);
+          vertices[i+IVY_N][2] = 0.0;
+
+          vertIndexes[0][i      ] = i;
+          vertIndexes[0][i+IVY_N] = i+IVY_N;
+          vertIndexes[1][i      ] = i;
+          vertIndexes[1][i+IVY_N] = i+IVY_N;
+          }
+
+        bands = new float[][]
+          {
+             {+0.012f,20,0.2f,0.5f,7,1,2},
+             {-0.100f,20,0.2f,0.0f,2,1,2},
+          };
+
+        bandIndexes = new int[] { 0,1 };
+
+        corners = new float[][]
+          {
+             {0.03f,0.10f}
+          };
+
+        centers = new float[][]
+          {
+              {-0.0f,-0.0f,-0.5f}
+          };
+
+        cornerIndexes = new int[2*IVY_N];
+        centerIndexes = new int[2*IVY_N];
+
+        for(int i=0; i<2*IVY_N; i++)
+          {
+          cornerIndexes[i] = -1;
+          centerIndexes[i] = -1;
+          }
+
+        cornerIndexes[0    ] = 0;
+        cornerIndexes[IVY_N] = 0;
+        centerIndexes[0    ] = 0;
+        centerIndexes[IVY_N] = 0;
+
+        numComponents = 2;
         }
 
       FactoryCubit factory = FactoryCubit.getInstance();
-      mMesh = factory.createRoundedSolid(vertices, vertIndexes, bands, bandIndexes, corners, cornerIndexes);
 
-      int numEff = mMesh.numEffComponents();
+      factory.clear();
+      factory.createNewFaceTransform(vertices,vertIndexes);
+      mMesh = factory.createRoundedSolid(vertices, vertIndexes,
+                                         bands, bandIndexes,
+                                         corners, cornerIndexes,
+                                         centers, centerIndexes,
+                                         numComponents );
+
+      int numEff = mMesh.getNumEffComponents();
 
       for(int i=0; i<numEff; i++)
         {
@@ -486,7 +718,7 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
       DataInputStream dos = new DataInputStream(is);
       mMesh = new MeshFile(dos);
 
-      int numEff = mMesh.numEffComponents();
+      int numEff = mMesh.getNumEffComponents();
 
       for(int i=0; i<numEff; i++)
         {
@@ -554,13 +786,13 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
 
     int getEffComponentNum()
       {
-      return mMesh.numEffComponents();
+      return mMesh.getNumEffComponents();
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     int getTexComponentNum()
       {
-      return mMesh.numTexComponents();
+      return mMesh.getNumTexComponents();
       }
 }
