commit c523e2eacb68380f7ed0d5d3d58f31db99d75526
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Mar 14 21:33:20 2019 +0000

    Improvements for the 'Rubik' app.

diff --git a/src/main/java/org/distorted/examples/TableOfContents.java b/src/main/java/org/distorted/examples/TableOfContents.java
index 27cd57d..e32070b 100644
--- a/src/main/java/org/distorted/examples/TableOfContents.java
+++ b/src/main/java/org/distorted/examples/TableOfContents.java
@@ -409,7 +409,7 @@ public class TableOfContents extends ListActivity
 
    {
    final Map<String, Object> item = new HashMap<>();
-   item.put(ITEM_IMAGE, R.drawable.icon_example_wip);
+   item.put(ITEM_IMAGE, R.drawable.icon_example_rubik);
    item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_rubik));
    item.put(ITEM_SUBTITLE, getText(R.string.example_rubik_subtitle));
    data.add(item);
diff --git a/src/main/java/org/distorted/examples/rubik/RubikRenderer.java b/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
index a8b4b0a..7703c0a 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
@@ -20,28 +20,21 @@
 package org.distorted.examples.rubik;
 
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.opengl.GLSurfaceView;
 
-import org.distorted.examples.R;
 import org.distorted.library.effect.MatrixEffectMove;
 import org.distorted.library.effect.MatrixEffectQuaternion;
 import org.distorted.library.effect.MatrixEffectScale;
-import org.distorted.library.effect.VertexEffect;
-import org.distorted.library.effect.VertexEffectDistort;
 import org.distorted.library.main.Distorted;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedScreen;
 import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.mesh.MeshCubes;
-import org.distorted.library.mesh.MeshFlat;
-import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
-import java.io.IOException;
-import java.io.InputStream;
-
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
@@ -70,6 +63,7 @@ class RubikRenderer implements GLSurfaceView.Renderer
       mView = v;
 
       mScreen = new DistortedScreen();
+   // mScreen.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 
       mQuat1 = new Static4D(           0,         0,           0,          1);  // unity quaternion
       mQuat2 = new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);  // something semi-random that looks good
@@ -87,11 +81,40 @@ class RubikRenderer implements GLSurfaceView.Renderer
       MatrixEffectQuaternion quat1 = new MatrixEffectQuaternion(mQuat1, mCenter);
       MatrixEffectQuaternion quat2 = new MatrixEffectQuaternion(mQuat2, mCenter);
 
+      // 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;
+
+      final Static4D mapFront = new Static4D(ze,oh, ze+ot,oh+oh);
+      final Static4D mapBack  = new Static4D(tt,ze, tt+ot,ze+oh);
+      final Static4D mapLeft  = new Static4D(ot,ze, ot+ot,ze+oh);
+      final Static4D mapRight = new Static4D(ze,ze, ze+ot,ze+oh);
+      final Static4D mapTop   = new Static4D(tt,oh, tt+ot,oh+oh);
+      final Static4D mapBottom= new Static4D(ot,oh, ot+ot,oh+oh);
+
+      final Static4D mapBlack = new Static4D(ze,ze, ze+of,ze+of);
+
+      Static4D tmpFront, tmpBack, tmpLeft, tmpRight, tmpTop, tmpBottom;
+
       for(int x=0; x<CUBE_SIZE; x++)
         for(int y=0; y<CUBE_SIZE; y++)
           for(int z=0; z<CUBE_SIZE; z++)
             {
-            mCubes[x][y][z] = new MeshCubes(VERTICES,VERTICES,VERTICES);
+            tmpLeft  = (x==          0 ? mapLeft  :mapBlack);
+            tmpRight = (x==CUBE_SIZE-1 ? mapRight :mapBlack);
+            tmpFront = (z==CUBE_SIZE-1 ? mapFront :mapBlack);
+            tmpBack  = (z==          0 ? mapBack  :mapBlack);
+            tmpTop   = (y==CUBE_SIZE-1 ? mapTop   :mapBlack);
+            tmpBottom= (y==          0 ? mapBottom:mapBlack);
+
+            mCubes[x][y][z] = new MeshCubes(VERTICES,VERTICES,VERTICES, tmpFront, tmpBack, tmpLeft, tmpRight, tmpTop, tmpBottom);
 
             cubeVectors[x][y][z] = new Static3D( SIZE*(x-0.5f*(CUBE_SIZE-1)), SIZE*(y-0.5f*(CUBE_SIZE-1)), SIZE*(z-0.5f*(CUBE_SIZE-1)) );
 
@@ -135,21 +158,42 @@ class RubikRenderer implements GLSurfaceView.Renderer
     
     public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
       {
-      InputStream is = mView.getContext().getResources().openRawResource(R.raw.monalisa);
       Bitmap bitmap;
-        
-      try 
-        {
-        bitmap = BitmapFactory.decodeStream(is);
-        } 
-      finally 
-        {
-        try 
-          {
-          is.close();
-          } 
-        catch(IOException e) { }
-        }  
+
+      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(  0+M, 0+M,   S-M,   S-M, R, R, paint); //
+      paint.setColor(0xff00ff00);                                  // GREEN
+      canvas.drawRoundRect(  S+M, 0+M, 2*S-M,   S-M, R, R, paint); //
+      paint.setColor(0xff0000ff);                                  // BLUE
+      canvas.drawRoundRect(2*S+M, 0+M, 3*S-M,   S-M, R, R, paint); //
+      paint.setColor(0xffffff00);                                  // YELLOW
+      canvas.drawRoundRect(  0+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); //
 
       if( mTexture==null ) mTexture = new DistortedTexture(SIZE,SIZE);
       mTexture.setTexture(bitmap);
diff --git a/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java b/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
index cdc8f67..b43f616 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
@@ -23,7 +23,6 @@ import android.app.ActivityManager;
 import android.content.Context;
 import android.content.pm.ConfigurationInfo;
 import android.opengl.GLSurfaceView;
-import android.util.AttributeSet;
 import android.view.MotionEvent;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/res/drawable-hdpi/icon_example_rubik.png b/src/main/res/drawable-hdpi/icon_example_rubik.png
new file mode 100644
index 0000000..06358ac
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_rubik.png differ
