commit c8f3a7659d8714845b9b9b6f0332950947bf3e26
Author: leszek <leszek@koltunski.pl>
Date:   Mon Sep 18 00:11:31 2023 +0200

    fix the 'band' problem in the TwistyBandagedMegaminx.

diff --git a/src/main/java/org/distorted/objectlib/bandaged/FactoryBandaged.java b/src/main/java/org/distorted/objectlib/bandaged/FactoryBandaged.java
index 4da21cf9..66658c35 100644
--- a/src/main/java/org/distorted/objectlib/bandaged/FactoryBandaged.java
+++ b/src/main/java/org/distorted/objectlib/bandaged/FactoryBandaged.java
@@ -118,7 +118,7 @@ abstract public class FactoryBandaged
   private ArrayList<float[]> mTmpArray;
   private ArrayList<float[][]> mVertexArray;
   private BandagedElement[] mElements;
-  private Static3D[] mNormals;
+  private Static3D[] mPuzzleNormals;
   private float[] mDist3D;
   private int[][] mFaceBelongsBitmap;
   private float[][] mDiaAxis;
@@ -132,6 +132,9 @@ abstract public class FactoryBandaged
   private int[] mNumLayers;
   private float[] mTmp;
   private float[][][] mAllPositions;
+  private boolean mCalledFromBandagedObject; // true if this class is being called from the
+                                             // one of the 'BandagedObject*' classes; false if
+                                             // called from one of the 'TwistyBandaged*' classes.
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -153,23 +156,27 @@ abstract public class FactoryBandaged
   abstract float[][] getVertices(int[] numLayers, int variant);
   abstract int[][] getIndices(int[] numLayers, int variant);
   abstract int getNumVariants(int[] numLayers);
-
+  abstract float sizeCorrection(int[] numLayers); // again workaround for the Megaminx
+                                                  // '2-3-4-5' vs. '3-3-5-5' problem.
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private int[] computeFaceBelongsBitmap(float[][] vertices, float[] move)
+  private int[] computeFaceBelongsBitmap(float[][] vertices, float[] move, float corr)
     {
     int numVerts = vertices.length;
     int[] ret = new int[numVerts];
 
-    for(int i=0; i<numVerts; i++)
+    for(int v=0; v<numVerts; v++)
       {
       int vertBelongsBitmap=0x00000000;
-      float[] vert=vertices[i];
+      float[] vert=vertices[v];
 
-      for(int j=0; j<mNumFaces; j++)
-        if( vertInFace(vert, move, mNormals[j], mDist3D[j]) ) vertBelongsBitmap |= (1<<j);
+      for(int f=0; f<mNumFaces; f++)
+        if( vertInFace(vert, move, mPuzzleNormals[f], mDist3D[f], corr) )
+          {
+          vertBelongsBitmap |= (1<<f);
+          }
 
-      ret[i]=vertBelongsBitmap;
+      ret[v]=vertBelongsBitmap;
       }
 
     return ret;
@@ -456,7 +463,7 @@ abstract public class FactoryBandaged
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
+  static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist, float corr)
     {
     final float MAX_ERROR = 0.01f;
 
@@ -464,7 +471,11 @@ abstract public class FactoryBandaged
     float y= faceAxis.get1();
     float z= faceAxis.get2();
 
-    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
+    float vx = vertex[0]*corr;
+    float vy = vertex[1]*corr;
+    float vz = vertex[2]*corr;
+
+    float a = (vx+move[0])*x + (vy+move[1])*y + (vz+move[2])*z;
     float diff = a - dist;
 
     return diff>-MAX_ERROR && diff<MAX_ERROR;
@@ -472,115 +483,101 @@ abstract public class FactoryBandaged
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void computeVectorFace(float[] prev, float[] curr, float[] next, float[] output)
+  private float[] computeVector(int index, float[][] vertices, int[][][] indices, int[] bandIndices, float[][] normals)
     {
-    float ax = prev[0]-curr[0];
-    float ay = prev[1]-curr[1];
-    float az = prev[2]-curr[2];
+    int numFaces = indices.length;
+    int numBordering=0, numExternal=0;
+    float x=0, y=0, z=0;
 
-    float bx = next[0]-curr[0];
-    float by = next[1]-curr[1];
-    float bz = next[2]-curr[2];
+    for(int f=0; f<numFaces; f++)
+      {
+      int numComponentsInFace = indices[f].length;
 
-    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
-    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
+      for(int c=0; c<numComponentsInFace; c++)
+        {
+        int[] ind = indices[f][c];
+        int numVertsInComponent = ind.length;
 
-    ax /= lena;
-    ay /= lena;
-    az /= lena;
+        for(int v=0; v<numVertsInComponent; v++)
+          {
+          if( ind[v]==index )
+            {
+            float[] nor = normals[f];
 
-    bx /= lenb;
-    by /= lenb;
-    bz /= lenb;
+            x += nor[0];
+            y += nor[1];
+            z += nor[2];
 
-    output[0] = ay*bz - az*by;
-    output[1] = az*bx - ax*bz;
-    output[2] = ax*by - ay*bx;
+            numBordering++;
+            if( bandIndices[f]>0 ) numExternal++;
 
-    output[3] = ax;
-    output[4] = ay;
-    output[5] = az;
+            v = numVertsInComponent;
+            c = numComponentsInFace;
+            }
+          }
+        }
+      }
 
-    output[6] = bx;
-    output[7] = by;
-    output[8] = bz;
+    return ( numExternal<2 || numBordering<3 ) ? null : new float[] { x/numBordering, y/numBordering, z/numBordering};
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// 'concave' vertices do not get pushed!
 
-  private boolean vertexIsConcave(float[][] vecs, int numVecs)
+  private void createCubitFaceNormal(float[] output, float[] v0, float[] v1, float[] v2)
     {
-    for(int i=0; i<numVecs; i++)
-      {
-      float[] v1 = vecs[i];
+    float ax = v0[0]-v1[0];
+    float ay = v0[1]-v1[1];
+    float az = v0[2]-v1[2];
 
-      for(int j=0; j<numVecs; j++)
-        {
-        if( i==j ) continue;
+    float bx = v2[0]-v1[0];
+    float by = v2[1]-v1[1];
+    float bz = v2[2]-v1[2];
 
-        float[] v2 = vecs[j];
+    output[0] = ay*bz - az*by;
+    output[1] = az*bx - ax*bz;
+    output[2] = ax*by - ay*bx;
 
-        float scalar1 = v1[0]*v2[3] + v1[1]*v2[4] + v1[2]*v2[5];
-        float scalar2 = v1[0]*v2[6] + v1[1]*v2[7] + v1[2]*v2[8];
+    float len = (float)Math.sqrt(output[0]*output[0] + output[1]*output[1] + output[2]*output[2]);
 
-        if( scalar1<0 || scalar2<0 ) return true;
-        }
+    if( len!=0 )
+      {
+      output[0] /= len;
+      output[1] /= len;
+      output[2] /= len;
+      }
+    else
+      {
+      android.util.Log.e("D", "ERROR in createCubitFaceNormal!");
       }
-
-    return false;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private float[] computeVector(int index, float[][] vertices, int[][][] indices, int[] bandIndices)
+  private float[][] generateCubitFaceNormals(float[][] vertices, int[][][] indices)
     {
-    int band=0;
     int numFaces = indices.length;
-    int numBordering = 0;
-    float x=0, y=0, z=0;
-
-    float[][] vecs = new float[numFaces][9];
-    int vecIndex = 0;
+    float[][] ret = new float[numFaces][3];
 
     for(int f=0; f<numFaces; f++)
       {
-      int numComponentsInFace = indices[f].length;
+      int[] verts = indices[f][0];
+      int numVerts = verts.length;
 
-      for(int c=0; c<numComponentsInFace; c++)
+      for(int v=0; v<numVerts; v++)
         {
-        int[] ind = indices[f][c];
-        int numVertsInComponent = ind.length;
+        int i0 = verts[0];
+        int i1 = verts[1];
+        int i2 = verts[2];
 
-        for(int v=0; v<numVertsInComponent; v++)
-          {
-          if(ind[v]==index)
-            {
-            int prev=v>0 ? v-1 : numVertsInComponent-1;
-            int next=v<numVertsInComponent-1 ? v+1 : 0;
-
-            int prevIndex=ind[prev];
-            int currIndex=ind[v];
-            int nextIndex=ind[next];
-
-            float[] vec = vecs[vecIndex++];
-            computeVectorFace(vertices[prevIndex], vertices[currIndex], vertices[nextIndex], vec);
-            band|=bandIndices[f];
-            v = numVertsInComponent;
-            c = numComponentsInFace;
-            numBordering++;
+        float[] v0 = vertices[i0];
+        float[] v1 = vertices[i1];
+        float[] v2 = vertices[i2];
 
-            x += vec[0];
-            y += vec[1];
-            z += vec[2];
-            }
-          }
+        createCubitFaceNormal(ret[f], v0,v1,v2);
         }
       }
 
-    boolean concave = vertexIsConcave(vecs,vecIndex);
-
-    return ( concave || band==0 || numBordering<3 ) ? null : new float[] { x/numBordering, y/numBordering, z/numBordering};
+    return ret;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -589,10 +586,11 @@ abstract public class FactoryBandaged
     {
     int len = vertices.length;
     float[][] vectors = new float[len][];
+    float[][] normals = generateCubitFaceNormals(vertices,indices);
 
     for(int i=0; i<len; i++)
       {
-      vectors[i] = computeVector(i,vertices,indices,bandIndices);
+      vectors[i] = computeVector(i,vertices,indices,bandIndices,normals);
       }
 
     return vectors;
@@ -863,6 +861,7 @@ abstract public class FactoryBandaged
   public void prepare(int numVariants, int[] numLayers)
     {
     if( mVertexArray==null ) mVertexArray = new ArrayList<>();
+    mCalledFromBandagedObject = false;
     mVertices= new float[numVariants][][];
     mIndices = new int[numVariants][][][];
     mMove = new float[numVariants][3];
@@ -878,11 +877,11 @@ abstract public class FactoryBandaged
     mNumLayers = new int[num];
     for(int l=0; l<num; l++) mNumLayers[l] = numLayers[l];
 
-    mNormals   = getNormals();
-    mNumFaces  = mNormals.length;
-    mDist3D    = getDist3D(mNumLayers);
-    mDiaAxis   = getDiameterAxis();
-    mMinMax    = new float[mDiaAxis.length][2];
+    mPuzzleNormals= getNormals();
+    mNumFaces     = mPuzzleNormals.length;
+    mDist3D       = getDist3D(mNumLayers);
+    mDiaAxis      = getDiameterAxis();
+    mMinMax       = new float[mDiaAxis.length][2];
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -930,10 +929,11 @@ abstract public class FactoryBandaged
   public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode)
     {
     float[][] bands = getBands(iconMode, mNumLayers);
+    float corr = mCalledFromBandagedObject ? 1.0f : sizeCorrection(mNumLayers);
 
     if( mBandIndices[variant]==null )
       {
-      mFaceBelongsBitmap[variant] = computeFaceBelongsBitmap(mVertices[variant], mMove[variant]);
+      mFaceBelongsBitmap[variant] = computeFaceBelongsBitmap(mVertices[variant], mMove[variant],corr);
       mBandIndices[variant] = generateBandIndices(mVertices[variant], mIndices[variant], mFaceBelongsBitmap[variant]);
       }
 
@@ -974,6 +974,9 @@ abstract public class FactoryBandaged
   public MeshBase createMesh(float[] pos, int[] numLayers, boolean iconMode, boolean roundCorners)
     {
     prepare(1,numLayers);
+
+    mCalledFromBandagedObject = true;
+
     ObjectShape shape           = createIrregularShape(0,pos);
     ObjectFaceShape face        = createIrregularFaceShape(0,iconMode);
     ObjectVertexEffects effects = createVertexEffects(0,roundCorners);
diff --git a/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedCuboid.java b/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedCuboid.java
index 56921bd4..f9dde448 100644
--- a/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedCuboid.java
+++ b/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedCuboid.java
@@ -136,6 +136,13 @@ public class FactoryBandagedCuboid extends FactoryBandaged
      return new float[][] { {1,0,0},{0,1,0},{0,0,1} };
      }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public float sizeCorrection(int[] numLayers)
+    {
+    return 1.0f;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int diameterMap(float diameter)
diff --git a/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedMegaminx.java b/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedMegaminx.java
index 334c6298..264f95d5 100644
--- a/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedMegaminx.java
+++ b/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedMegaminx.java
@@ -1060,6 +1060,21 @@ public class FactoryBandagedMegaminx extends FactoryBandaged
             };
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public float sizeCorrection(int[] numLayers)
+    {
+    switch(numLayers[0])
+      {
+      case 2: return 2.0f/3;
+      case 3: return 3.0f/3;
+      case 4: return 4.0f/5;
+      case 5: return 5.0f/5;
+      }
+
+    return 1.0f;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int diameterMap(float diameter)
@@ -1074,7 +1089,7 @@ public class FactoryBandagedMegaminx extends FactoryBandaged
   public float[][] getBands(boolean iconMode, int[] numLayers)
     {
     float height= iconMode ? 0.001f : 0.05f;
-    int[] angle = {72,55,50,46,42,39,36,34,31,29,27};
+    int[] angle = {1,55,50,46,42,39,36,34,31,29,27};
     float R     = 0.5f;
     float S     = 0.5f;
     int extraI  = 0;
@@ -1082,7 +1097,7 @@ public class FactoryBandagedMegaminx extends FactoryBandaged
     int numVertA= numLayers[0]>=4 ? 4 : 5;
     int numVertI= numLayers[0]>=4 ? 2 : 3;
 
-    return new float[][] { {  0.001f    ,angle[ 0],R,S,numVertI,extraV,extraI},
+    return new float[][] { {0.001f      ,angle[ 0],R,S,numVertI,extraV,extraI},
                            {height      ,angle[ 1],R,S,numVertA,extraV,extraI},
                            {height      ,angle[ 1],R,S,numVertA,extraV,extraI},
                            {height/ 1.5f,angle[ 2],R,S,numVertA,extraV,extraI},
diff --git a/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedPyraminx.java b/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedPyraminx.java
index cdafe069..8560ddf4 100644
--- a/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedPyraminx.java
+++ b/src/main/java/org/distorted/objectlib/bandaged/FactoryBandagedPyraminx.java
@@ -220,6 +220,13 @@ public class FactoryBandagedPyraminx extends FactoryBandaged
             };
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public float sizeCorrection(int[] numLayers)
+    {
+    return 1.0f;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int diameterMap(float diameter)
