commit 550db260d613bddb17e41e7e8ce4935fbd3039a6
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Mar 24 10:15:24 2022 +0100

    Progress with BandagedCreator: joining cubits together. Still at least one (probably two) bugs here remain:
    
    1) sometimes some of the walls of the newly creaed joined cubit are incorrectly rotated
    2) there is an unpleasant flash when joining

diff --git a/src/main/java/org/distorted/bandaged/BandagedCreatorRenderer.java b/src/main/java/org/distorted/bandaged/BandagedCreatorRenderer.java
index 9f4d8312..ad2cbee7 100644
--- a/src/main/java/org/distorted/bandaged/BandagedCreatorRenderer.java
+++ b/src/main/java/org/distorted/bandaged/BandagedCreatorRenderer.java
@@ -38,10 +38,9 @@ public class BandagedCreatorRenderer implements GLSurfaceView.Renderer, Distorte
    private final BandagedCreatorView mView;
    private final DistortedScreen mScreen;
    private final Static3D mScale;
-   private final Static3D mMoveWhole;
-   private final Static3D[] mMove;
-   private final Static3D[] mMoveUnscaled;
+   private final Static3D mMoveY;
    private final BandagedCubit[] mCubits;
+   private float mScaleValue;
 
    static final int COLOR_DEFAULT = 0xffffff55;
    static final int COLOR_MARKED  = 0xffff0000;
@@ -95,20 +94,9 @@ public class BandagedCreatorRenderer implements GLSurfaceView.Renderer, Distorte
 
      mScreen = new DistortedScreen();
      mScreen.glClearColor(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS, 1.0f);
-     mScale= new Static3D(1,1,1);
-     mMoveWhole = new Static3D(0,0,0);
-
-     int len = POSITIONS.length;
-     mMove         = new Static3D[len];
-     mMoveUnscaled = new Static3D[len];
-
-     for(int i=0; i<len; i++)
-       {
-       mMove[i] = new Static3D(0,0,0);
-       mMoveUnscaled[i] = new Static3D(0,0,0);
-       }
-
-     mCubits = createCubits();
+     mScale = new Static3D(1,1,1);
+     mMoveY = new Static3D(0,0,0);
+     mCubits= createCubits();
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -120,48 +108,12 @@ public class BandagedCreatorRenderer implements GLSurfaceView.Renderer, Distorte
 
      for(int c=0; c<len; c++)
        {
-       computeMove(mMoveUnscaled[c],POSITIONS[c]);
-       cubits[c] = new BandagedCubit(POSITIONS[c],mQuat1,mQuat2,mMove[c],mMoveWhole,mScale, COLOR_DEFAULT);
+       cubits[c] = new BandagedCubit(POSITIONS[c],mQuat1,mQuat2,mMoveY,mScale,COLOR_DEFAULT);
        }
 
      return cubits;
      }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void computeMove(Static3D move, float[] position)
-      {
-      int numCenters = position.length/3;
-      float totalX=0.0f, totalY=0.0f, totalZ=0.0f;
-
-      for(int center=0; center<numCenters; center++)
-        {
-        totalX += position[3*center  ];
-        totalY += position[3*center+1];
-        totalZ += position[3*center+2];
-        }
-
-      totalX /= numCenters;
-      totalY /= numCenters;
-      totalZ /= numCenters;
-
-      move.set(totalX,totalY,totalZ);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   public BandagedCubit[] getCubits()
-     {
-     return mCubits;
-     }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   public DistortedScreen getScreen()
-     {
-     return mScreen;
-     }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    @Override
@@ -177,19 +129,14 @@ public class BandagedCreatorRenderer implements GLSurfaceView.Renderer, Distorte
    public void onSurfaceChanged(GL10 glUnused, int width, int height)
       {
       final float Q = SCREEN_RATIO/OBJECT_SIZE;
-      float scale = width<height ? Q*width : Q*height;
+      mScaleValue = width<height ? Q*width : Q*height;
 
       mScreen.detachAll();
       int len = POSITIONS.length;
 
       for(int i=0; i<len; i++)
         {
-        float x = mMoveUnscaled[i].get0();
-        float y = mMoveUnscaled[i].get1();
-        float z = mMoveUnscaled[i].get2();
-
-        mMove[i].set(x*scale,y*scale,z*scale);
-
+        mCubits[i].scaleMove(mScaleValue);
         mCubits[i].setTexture(COLOR_DEFAULT);
         DistortedNode node = mCubits[i].getNode();
         mScreen.attach(node);
@@ -198,9 +145,9 @@ public class BandagedCreatorRenderer implements GLSurfaceView.Renderer, Distorte
       float RB = BandagedCreatorActivity.RATIO_BAR;
       float RS = BandagedCreatorActivity.RATIO_SCROLL;
       float yOffset = (0.5f*RB/(1-RS))*height;
-      mMoveWhole.set1(yOffset);
+      mMoveY.set1(yOffset);
 
-      mScale.set( scale,scale,scale );
+      mScale.set( mScaleValue,mScaleValue,mScaleValue );
       mScreenMin = Math.min(width, height);
       mView.setScreenSize(width,height, (int)yOffset);
       mScreen.resize(width,height);
@@ -220,4 +167,63 @@ public class BandagedCreatorRenderer implements GLSurfaceView.Renderer, Distorte
      {
      android.util.Log.e("CREATOR", "unexpected exception: "+ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public BandagedCubit[] getCubits()
+     {
+     return mCubits;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public DistortedScreen getScreen()
+     {
+     return mScreen;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   private boolean isAdjacent(float[] pos1, float[] pos2)
+     {
+     int len1 = pos1.length/3;
+     int len2 = pos2.length/3;
+
+     for(int i=0; i<len1; i++)
+       for(int j=0; j<len2; j++)
+         {
+         float d0 = pos1[3*i  ] - pos2[3*j  ];
+         float d1 = pos1[3*i+1] - pos2[3*j+1];
+         float d2 = pos1[3*i+2] - pos2[3*j+2];
+
+         if( d0*d0 + d1*d1 + d2*d2 == 1 ) return true;
+         }
+
+     return false;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void tryConnectingCubits(int index1, int index2)
+     {
+     if( index1!=index2 )
+       {
+       float[] pos1 = mCubits[index1].getPosition();
+       float[] pos2 = mCubits[index2].getPosition();
+
+       if( isAdjacent(pos1,pos2) )
+         {
+         mCubits[index2].prepareJoin(pos1);
+
+         mCubits[index1].detach();
+         DistortedNode node1 = mCubits[index1].getNode();
+         mScreen.detach(node1);
+         DistortedNode node2 = mCubits[index2].getNode();
+         mScreen.detach(node2);
+         mCubits[index2].swapNodes(mScaleValue);
+         DistortedNode node3 = mCubits[index2].getNode();
+         mScreen.attach(node3);
+         }
+       }
+     }
 }
diff --git a/src/main/java/org/distorted/bandaged/BandagedCreatorScreen.java b/src/main/java/org/distorted/bandaged/BandagedCreatorScreen.java
index c2fc0ffc..5aef82fa 100644
--- a/src/main/java/org/distorted/bandaged/BandagedCreatorScreen.java
+++ b/src/main/java/org/distorted/bandaged/BandagedCreatorScreen.java
@@ -25,6 +25,7 @@ import android.widget.LinearLayout;
 import org.distorted.helpers.TransparentImageButton;
 import org.distorted.main.R;
 import org.distorted.main.RubikActivity;
+import org.distorted.objectlib.helpers.FactoryCubit;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -90,7 +91,8 @@ public class BandagedCreatorScreen
       @Override
       public void onClick(View v)
         {
-
+        FactoryCubit factory = FactoryCubit.getInstance();
+        factory.printFaceTransform();
         }
       });
     }
diff --git a/src/main/java/org/distorted/bandaged/BandagedCreatorView.java b/src/main/java/org/distorted/bandaged/BandagedCreatorView.java
index 81b9a87e..b79087c6 100644
--- a/src/main/java/org/distorted/bandaged/BandagedCreatorView.java
+++ b/src/main/java/org/distorted/bandaged/BandagedCreatorView.java
@@ -37,7 +37,7 @@ public class BandagedCreatorView extends GLSurfaceView
 {
     private final static int DIRECTION_SENSITIVITY=  12;
     private int mX, mY;
-    private int mTouchedIndex;
+    private int mTouchedIndex1, mTouchedIndex2;
     private BandagedCreatorRenderer mRenderer;
     private BandagedTouchControl mTouchControl;
     private int mScreenWidth, mScreenHeight;
@@ -54,6 +54,9 @@ public class BandagedCreatorView extends GLSurfaceView
       mX = -1;
       mY = -1;
 
+      mTouchedIndex1 = -1;
+      mTouchedIndex2 = -1;
+
       if(!isInEditMode())
         {
         BandagedCreatorActivity act = (BandagedCreatorActivity)context;
@@ -136,9 +139,9 @@ public class BandagedCreatorView extends GLSurfaceView
          case MotionEvent.ACTION_DOWN: float x1 = (x -  mScreenWidth*0.5f)/mRenderer.mScreenMin;
                                        float y1 = (mScreenHeight*0.5f - y)/mRenderer.mScreenMin;
 
-                                       mTouchedIndex = mTouchControl.cubitTouched(x1,y1,mRenderer.mQuat2);
+                                       int index = mTouchControl.cubitTouched(x1,y1,mRenderer.mQuat2);
 
-                                       if( mTouchedIndex<0 )
+                                       if( index<0 )
                                          {
                                          mX = x;
                                          mY = y;
@@ -148,7 +151,16 @@ public class BandagedCreatorView extends GLSurfaceView
                                          mX = -1;
                                          mY = -1;
 
-                                         mTouchControl.markCubit(mTouchedIndex, BandagedCreatorRenderer.COLOR_MARKED);
+                                         if( mTouchedIndex1<0 )
+                                           {
+                                           mTouchedIndex1 = index;
+                                           mTouchControl.markCubit(mTouchedIndex1, BandagedCreatorRenderer.COLOR_MARKED);
+                                           }
+                                         else if( mTouchedIndex1 != index )
+                                           {
+                                           mTouchedIndex2 = index;
+                                           mTouchControl.markCubit(mTouchedIndex2, BandagedCreatorRenderer.COLOR_MARKED);
+                                           }
                                          }
 
                                        break;
@@ -180,15 +192,20 @@ public class BandagedCreatorView extends GLSurfaceView
                                          }
                                        break;
 
-         case MotionEvent.ACTION_UP  : mX = -1;
-                                       mY = -1;
-
-                                       if( mTouchedIndex>=0 )
+         case MotionEvent.ACTION_UP  : if( mTouchedIndex2>=0 )
                                          {
-                                         mTouchControl.markCubit(mTouchedIndex, BandagedCreatorRenderer.COLOR_DEFAULT);
-                                         mTouchedIndex = -1;
+                                         mTouchControl.markCubit(mTouchedIndex1, BandagedCreatorRenderer.COLOR_DEFAULT);
+                                         mTouchControl.markCubit(mTouchedIndex2, BandagedCreatorRenderer.COLOR_DEFAULT);
+
+                                         mRenderer.tryConnectingCubits(mTouchedIndex1,mTouchedIndex2);
+
+                                         mTouchedIndex1 = -1;
+                                         mTouchedIndex2 = -1;
                                          }
 
+                                       mX = -1;
+                                       mY = -1;
+
         	                             resetQuats();
                                        break;
          }
diff --git a/src/main/java/org/distorted/bandaged/BandagedCubit.java b/src/main/java/org/distorted/bandaged/BandagedCubit.java
index ff1c64c3..dd931214 100644
--- a/src/main/java/org/distorted/bandaged/BandagedCubit.java
+++ b/src/main/java/org/distorted/bandaged/BandagedCubit.java
@@ -36,24 +36,50 @@ public class BandagedCubit
 {
     private static final Static3D CENTER = new Static3D(0,0,0);
 
-    private final DistortedNode mNode;
+    private DistortedNode mNode, mNewNode;
     private final DistortedTexture mTexture;
     private final DistortedEffects mEffects;
-    private final MeshBase mMesh;
-    private final float[] mPosition;
+    private final Static3D mMove;
+
+    private float mUnscaledX, mUnscaledY, mUnscaledZ;
+    private float[] mPosition, mNewPosition;
     private boolean mIsAttached;
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void computeMove(float[] position)
+      {
+      int numCenters = position.length/3;
+      mUnscaledX=0.0f;
+      mUnscaledY=0.0f;
+      mUnscaledZ=0.0f;
+
+      for(int center=0; center<numCenters; center++)
+        {
+        mUnscaledX += position[3*center  ];
+        mUnscaledY += position[3*center+1];
+        mUnscaledZ += position[3*center+2];
+        }
+
+      mUnscaledX /= numCenters;
+      mUnscaledY /= numCenters;
+      mUnscaledZ /= numCenters;
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public BandagedCubit(float[] position, Static4D quat1, Static4D quat2, Static3D move1, Static3D move2, Static3D scale, int color)
+    public BandagedCubit(float[] position, Static4D quat1, Static4D quat2, Static3D moveY, Static3D scale, int color)
       {
       mPosition = position;
       mIsAttached = true;
 
+      computeMove(mPosition);
+      mMove = new Static3D(0,0,0);
+
       FactoryBandaged3x3Cubit factory = FactoryBandaged3x3Cubit.getInstance();
-      mMesh = factory.createMesh(position);
+      MeshBase mesh = factory.createMesh(mPosition);
 
       mTexture = new DistortedTexture();
       mTexture.setColorARGB(color);
@@ -61,17 +87,58 @@ public class BandagedCubit
       MatrixEffectScale scaleEffect = new MatrixEffectScale(scale);
       MatrixEffectQuaternion quat1Effect = new MatrixEffectQuaternion(quat1, CENTER);
       MatrixEffectQuaternion quat2Effect = new MatrixEffectQuaternion(quat2, CENTER);
-      MatrixEffectMove move1Effect = new MatrixEffectMove(move1);
-      MatrixEffectMove move2Effect = new MatrixEffectMove(move2);
+      MatrixEffectMove moveSEffect = new MatrixEffectMove(mMove);
+      MatrixEffectMove moveYEffect = new MatrixEffectMove(moveY);
 
       mEffects = new DistortedEffects();
       mEffects.apply(scaleEffect);
-      mEffects.apply(move1Effect);
+      mEffects.apply(moveSEffect);
       mEffects.apply(quat2Effect);
       mEffects.apply(quat1Effect);
-      mEffects.apply(move2Effect);
+      mEffects.apply(moveYEffect);
+
+      mNode = new DistortedNode(mTexture,mEffects,mesh);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void prepareJoin(float[] position)
+      {
+      int len1 = mPosition.length;
+      int len2 = position.length;
+
+      mNewPosition = new float[len1+len2];
 
-      mNode = new DistortedNode(mTexture,mEffects,mMesh);
+      System.arraycopy(mPosition, 0, mNewPosition,    0, len1);
+      System.arraycopy(position , 0, mNewPosition, len1, len2);
+
+/*
+int l= mPosition.length/3;
+String s="";
+for(int i=0; i<l; i++) s += (mPosition[3*i]+" "+mPosition[3*i+1]+" "+mPosition[3*i+2]+"\n");
+android.util.Log.e("D", "pos after joining: \n"+s);
+*/
+      FactoryBandaged3x3Cubit factory = FactoryBandaged3x3Cubit.getInstance();
+      MeshBase mesh = factory.createMesh(mNewPosition);
+      mNewNode = new DistortedNode(mTexture,mEffects,mesh);
+
+      computeMove(mNewPosition);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void swapNodes(float scale)
+      {
+      mPosition = mNewPosition;
+      mNode = mNewNode;
+      mMove.set( scale*mUnscaledX, scale*mUnscaledY, scale*mUnscaledZ);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void scaleMove(float scale)
+      {
+      mMove.set( scale*mUnscaledX, scale*mUnscaledY, scale*mUnscaledZ);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
