commit 411c628598d860f27fe1ce6948100e4384949513
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Mar 5 13:23:44 2020 +0000

    Make RubikCube more abstract.

diff --git a/src/main/java/org/distorted/object/RubikCube.java b/src/main/java/org/distorted/object/RubikCube.java
index 88a2c253..ce9e52fb 100644
--- a/src/main/java/org/distorted/object/RubikCube.java
+++ b/src/main/java/org/distorted/object/RubikCube.java
@@ -19,15 +19,18 @@
 
 package org.distorted.object;
 
-import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 
+import org.distorted.library.effect.MatrixEffect;
+import org.distorted.library.effect.MatrixEffectMove;
+import org.distorted.library.effect.MatrixEffectRotate;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.mesh.MeshBase;
-import org.distorted.library.mesh.MeshCubes;
+import org.distorted.library.mesh.MeshJoined;
 import org.distorted.library.mesh.MeshRectangles;
+import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
@@ -35,6 +38,21 @@ import org.distorted.library.type.Static4D;
 
 class RubikCube extends RubikObject
 {
+  private static final float SQ2 = 0.5f*((float)Math.sqrt(2));
+  private static final float[] LEGAL = new float[] { 0.0f , 0.5f , -0.5f , 1.0f , -1.0f , SQ2 , -SQ2 };
+
+  // axisXright (right-YELLOW) axisXleft (left-WHITE) axisYright (top-BLUE) axisYleft (bottom-GREEN) axisZright (front-RED) axisZleft (back-BROWN)
+  private static final int[] FACE_COLORS   = new int[] { 0xffffff00, 0xffffffff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffb5651d };
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  RubikCube(int size, Static4D quatCur, Static4D quatAcc, DistortedTexture texture, MeshRectangles mesh, DistortedEffects effects)
+    {
+    super(size,quatCur,quatAcc,texture,mesh,effects);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
   int[][] getCubitPositions(int size)
     {
     int[][] tmp = new int[getNumCubits(size)][3];
@@ -73,71 +91,76 @@ class RubikCube extends RubikObject
 
   float[] getLegalQuats()
     {
-    final float SQ2 = 0.5f*((float)Math.sqrt(2));
-    return new float[] { 0.0f , 0.5f , -0.5f , 1.0f , -1.0f , SQ2 , -SQ2 };
+    return LEGAL;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  boolean belongsToRotation( Static3D currentPosition, Static3D axis, int row)
+  int getNumFaces()
     {
-    if( axis.get0()!=0 ) return currentPosition.get0()==row;
-    if( axis.get1()!=0 ) return currentPosition.get1()==row;
-    if( axis.get2()!=0 ) return currentPosition.get2()==row;
+    return FACE_COLORS.length;
+    }
 
-    return false;
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void createFaceTexture(Canvas canvas, Paint paint, int face)
+    {
+    final int S = TEXTURE_HEIGHT;
+    final int R = TEXTURE_HEIGHT/10;
+    final int M = TEXTURE_HEIGHT/20;
+
+    paint.setColor(FACE_COLORS[face]);
+    canvas.drawRoundRect( (face*S+M), M, (face*S+M) + (S-2*M), M + (S-2*M), R, R, paint);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  RubikCube(int size, Static4D quatCur, Static4D quatAcc, DistortedTexture texture, MeshRectangles mesh, DistortedEffects effects)
+  MeshBase createCubitMesh(int vertices)
     {
-    super(size,quatCur,quatAcc,texture,mesh,effects);
+    final int MESHES=6;
+
+    Static3D axisY  = new Static3D(0,1,0);
+    Static3D axisX  = new Static3D(1,0,0);
+    Static3D center = new Static3D(0,0,0);
+    Static1D angle  = new Static1D(0);
+
+    MatrixEffect[] effectsY = new MatrixEffect[2];
+    effectsY[0] = new MatrixEffectMove(new Static3D(0,0,+0.5f));
+    effectsY[1] = new MatrixEffectRotate( angle, axisY, center );
+
+    MeshBase[] meshes = new MeshRectangles[MESHES];
+    for(int i=0; i<MESHES; i++) meshes[i] = new MeshRectangles(vertices,vertices);
+
+    angle.set(0);
+    meshes[4].apply(effectsY);  // front
+    angle.set(90);
+    meshes[0].apply(effectsY);  // right
+    angle.set(180);
+    meshes[5].apply(effectsY);  // back
+    angle.set(270);
+    meshes[1].apply(effectsY);  // left
+
+    MatrixEffect[] effectsX = new MatrixEffect[2];
+    effectsX[0] = new MatrixEffectMove(new Static3D(0,0,+0.5f));
+    effectsX[1] = new MatrixEffectRotate( angle, axisX, center );
+
+    angle.set( 90);
+    meshes[3].apply(effectsX);  // bottom
+    angle.set(-90);
+    meshes[2].apply(effectsX);  // top
+
+    return new MeshJoined(meshes);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
 
-  public void createTexture()
+  boolean belongsToRotation( Static3D currentPosition, Static3D axis, int row)
     {
-    Bitmap bitmap;
-
-    final int S = 128;
-    final int W = 3*S;
-    final int H = 2*S;
-    final int R = S/10;
-    final int M = S/20;
-
-    Paint paint = new Paint();
-    bitmap = Bitmap.createBitmap(W,H, Bitmap.Config.ARGB_8888);
-    Canvas canvas = new Canvas(bitmap);
-
-    paint.setAntiAlias(true);
-    paint.setTextAlign(Paint.Align.CENTER);
-    paint.setStyle(Paint.Style.FILL);
-
-    // 3x2 bitmap = 6 squares:
-    //
-    // RED     GREEN   BLUE
-    // YELLOW  WHITE   BROWN
-
-    paint.setColor(0xff000000);                                  // BLACK BACKGROUND
-    canvas.drawRect(0, 0, W, H, paint);                          //
-
-    paint.setColor(0xffff0000);                                  // RED
-    canvas.drawRoundRect(    M,   M,   S-M,   S-M, R, R, paint); //
-    paint.setColor(0xff00ff00);                                  // GREEN
-    canvas.drawRoundRect(  S+M,   M, 2*S-M,   S-M, R, R, paint); //
-    paint.setColor(0xff0000ff);                                  // BLUE
-    canvas.drawRoundRect(2*S+M,   M, 3*S-M,   S-M, R, R, paint); //
-    paint.setColor(0xffffff00);                                  // YELLOW
-    canvas.drawRoundRect(    M, S+M,   S-M, 2*S-M, R, R, paint); //
-    paint.setColor(0xffffffff);                                  // WHITE
-    canvas.drawRoundRect(  S+M, S+M, 2*S-M, 2*S-M, R, R, paint); //
-    paint.setColor(0xffb5651d);                                  // BROWN
-    canvas.drawRoundRect(2*S+M, S+M, 3*S-M, 2*S-M, R, R, paint); //
-
-    mTexture.setTexture(bitmap);
+    if( axis.get0()!=0 ) return currentPosition.get0()==row;
+    if( axis.get1()!=0 ) return currentPosition.get1()==row;
+    if( axis.get2()!=0 ) return currentPosition.get2()==row;
+
+    return false;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -146,38 +169,30 @@ class RubikCube extends RubikObject
 
   static
     {
-    // 3x2 bitmap = 6 squares:
-    //
-    // RED     GREEN   BLUE
-    // YELLOW  WHITE   BROWN
-
-    final float ze = 0.0f;
-    final float ot = 1.0f/3.0f;
-    final float tt = 2.0f/3.0f;
-    final float oh = 1.0f/2.0f;
-    final float of = 1.0f/40.0f;
-
-    mapFront = new Static4D(ze,oh, ze+ot,oh+oh);
-    mapBack  = new Static4D(tt,ze, tt+ot,ze+oh);
-    mapLeft  = new Static4D(ot,ze, ot+ot,ze+oh);
-    mapRight = new Static4D(ze,ze, ze+ot,ze+oh);
-    mapTop   = new Static4D(tt,oh, tt+ot,oh+oh);
-    mapBottom= new Static4D(ot,oh, ot+ot,oh+oh);
-
-    mapBlack = new Static4D(ze,ze, ze+of,ze+of);
+    // axisXright (right-YELLOW) axisXleft (left-WHITE) axisYright (top-BLUE) axisYleft (bottom-GREEN) axisZright (front-RED) axisZleft (back-BROWN)
+
+    mapRight = new Static4D( 0*(1/7.0f), 0.0f, 1/7.0f, 1.0f);
+    mapLeft  = new Static4D( 1*(1/7.0f), 0.0f, 1/7.0f, 1.0f);
+    mapTop   = new Static4D( 2*(1/7.0f), 0.0f, 1/7.0f, 1.0f);
+    mapBottom= new Static4D( 3*(1/7.0f), 0.0f, 1/7.0f, 1.0f);
+    mapFront = new Static4D( 4*(1/7.0f), 0.0f, 1/7.0f, 1.0f);
+    mapBack  = new Static4D( 5*(1/7.0f), 0.0f, 1/7.0f, 1.0f);
+    mapBlack = new Static4D( 6*(1/7.0f), 0.0f, 1/7.0f, 1.0f);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  MeshBase createCubitMesh(int vertices, int x, int y, int z)
+  void textureCubitMesh(MeshBase mesh, int x, int y, int z)
     {
-    Static4D tmpLeft  = (x==       0 ? mapLeft  :mapBlack);
     Static4D tmpRight = (x== mSize-1 ? mapRight :mapBlack);
-    Static4D tmpFront = (z== mSize-1 ? mapFront :mapBlack);
-    Static4D tmpBack  = (z==       0 ? mapBack  :mapBlack);
+    Static4D tmpLeft  = (x==       0 ? mapLeft  :mapBlack);
     Static4D tmpTop   = (y== mSize-1 ? mapTop   :mapBlack);
     Static4D tmpBottom= (y==       0 ? mapBottom:mapBlack);
+    Static4D tmpFront = (z== mSize-1 ? mapFront :mapBlack);
+    Static4D tmpBack  = (z==       0 ? mapBack  :mapBlack);
+
+    Static4D[] maps = new Static4D[] { tmpRight, tmpLeft, tmpTop, tmpBottom, tmpFront, tmpBack};
 
-    return new MeshCubes(vertices,vertices,vertices, tmpFront, tmpBack, tmpLeft, tmpRight, tmpTop, tmpBottom);
+    mesh.setTextureMap(maps);
     }
 }
diff --git a/src/main/java/org/distorted/object/RubikObject.java b/src/main/java/org/distorted/object/RubikObject.java
index 6ff7bfb5..bbf6d9fe 100644
--- a/src/main/java/org/distorted/object/RubikObject.java
+++ b/src/main/java/org/distorted/object/RubikObject.java
@@ -20,6 +20,9 @@
 package org.distorted.object;
 
 import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
 
 import org.distorted.library.effect.Effect;
 import org.distorted.library.effect.MatrixEffectQuaternion;
@@ -42,6 +45,7 @@ import static org.distorted.magic.RubikRenderer.NODE_FBO_SIZE;
 
 public abstract class RubikObject extends DistortedNode
   {
+  static final int TEXTURE_HEIGHT = 128;
   static final float OBJECT_SCREEN_RATIO = 0.5f;
   final float[] LEGAL_QUATS;
 
@@ -65,9 +69,9 @@ public abstract class RubikObject extends DistortedNode
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  RubikObject(int size, Static4D quatCur, Static4D quatAcc, DistortedTexture texture, MeshRectangles mesh, DistortedEffects effects)
+  RubikObject(int size, Static4D quatCur, Static4D quatAcc, DistortedTexture nodeTexture, MeshRectangles nodeMesh, DistortedEffects nodeEffects)
     {
-    super(texture,effects,mesh);
+    super(nodeTexture,nodeEffects,nodeMesh);
 
     resizeFBO(NODE_FBO_SIZE, NODE_FBO_SIZE);
 
@@ -94,7 +98,7 @@ public abstract class RubikObject extends DistortedNode
     mQuatAEffect = new MatrixEffectQuaternion(quatAcc, center);
 
     MatrixEffectScale nodeScaleEffect = new MatrixEffectScale(mNodeScale);
-    effects.apply(nodeScaleEffect);
+    nodeEffects.apply(nodeScaleEffect);
 
     mCubits = new Cubit[NUM_CUBITS];
     mTexture = new DistortedTexture();
@@ -108,7 +112,10 @@ public abstract class RubikObject extends DistortedNode
       int y = positions[i][1];
       int z = positions[i][2];
 
-      mCubits[i] = new Cubit( this ,createCubitMesh(vertices,x,y,z), new Static3D(x,y,z) );
+      MeshBase cubit = createCubitMesh(vertices);
+      textureCubitMesh(cubit,x,y,z);
+
+      mCubits[i] = new Cubit( this , cubit, new Static3D(x,y,z) );
       attach(mCubits[i].mNode);
       }
     }
@@ -139,6 +146,34 @@ public abstract class RubikObject extends DistortedNode
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// the getFaceColors + final black in a horizontal strip.
+
+  public void createTexture()
+    {
+    Bitmap bitmap;
+
+    final int numColors = getNumFaces();
+
+    Paint paint = new Paint();
+    bitmap = Bitmap.createBitmap( (numColors+1)*TEXTURE_HEIGHT, TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);
+    Canvas canvas = new Canvas(bitmap);
+
+    paint.setAntiAlias(true);
+    paint.setTextAlign(Paint.Align.CENTER);
+    paint.setStyle(Paint.Style.FILL);
+
+    paint.setColor(0xff000000);
+    canvas.drawRect(0, 0, (numColors+1)*TEXTURE_HEIGHT, TEXTURE_HEIGHT, paint);
+
+    for(int i=0; i<numColors; i++)
+      {
+      createFaceTexture(canvas,paint,i);
+      }
+
+    mTexture.setTexture(bitmap);
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getSize()
@@ -329,8 +364,10 @@ public abstract class RubikObject extends DistortedNode
   abstract int getNumCubits(int size);
   abstract int[][] getCubitPositions(int size);
   abstract float[] getLegalQuats();
-  abstract boolean belongsToRotation(Static3D position, Static3D axis, int row);
-  abstract MeshBase createCubitMesh(int vertices, int x, int y, int z);
+  abstract int getNumFaces();
+  abstract void createFaceTexture(Canvas canvas, Paint paint, int face);
+  abstract MeshBase createCubitMesh(int vertices);
 
-  public abstract void createTexture();
+  abstract boolean belongsToRotation(Static3D position, Static3D axis, int row);
+  abstract void textureCubitMesh(MeshBase mesh, int x, int y, int z);
   }
