commit 40ab026e185c6969f75c3e3577ba88b8deefd426
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun May 24 22:03:55 2020 +0100

    In library: allow a mixture of a deep and shallow copy of a Mesh ( mVertAttribs1 might be copied deeply or shallowly, mVertAttribs2 are always copied deeeply).
    Port RubikCube to the new library.

diff --git a/src/main/java/org/distorted/main/RubikRenderer.java b/src/main/java/org/distorted/main/RubikRenderer.java
index 99683588..bad78b60 100644
--- a/src/main/java/org/distorted/main/RubikRenderer.java
+++ b/src/main/java/org/distorted/main/RubikRenderer.java
@@ -23,6 +23,7 @@ import android.opengl.GLES30;
 import android.opengl.GLSurfaceView;
 
 import org.distorted.effects.BaseEffect;
+import org.distorted.library.effect.EffectType;
 import org.distorted.library.effect.VertexEffectSink;
 import org.distorted.library.main.DistortedLibrary;
 import org.distorted.library.main.DistortedScreen;
@@ -73,6 +74,7 @@ public class RubikRenderer implements GLSurfaceView.Renderer
    @Override
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
       {
+      DistortedLibrary.setMax(EffectType.VERTEX,12);
       VertexEffectSink.enable();
       BaseEffect.Type.enableEffects();
 
@@ -101,9 +103,6 @@ public class RubikRenderer implements GLSurfaceView.Renderer
         else
           {
           FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
-          crashlytics.setCustomKey("DistortedError", message );
-          crashlytics.setCustomKey("GLversion"     , version );
-          crashlytics.setCustomKey("GLSLrenderer"  , renderer);
           crashlytics.log("DistortedError: " +message );
           crashlytics.log("GLversion"        +version );
           crashlytics.log("GLSLrenderer"     +renderer);
diff --git a/src/main/java/org/distorted/objects/Cubit.java b/src/main/java/org/distorted/objects/Cubit.java
index 7fbb2f4f..7e03d262 100644
--- a/src/main/java/org/distorted/objects/Cubit.java
+++ b/src/main/java/org/distorted/objects/Cubit.java
@@ -353,7 +353,6 @@ class Cubit
     else
       {
       FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
-      crashlytics.setCustomKey("getAngle", "points in RotationAngle: "+pointNum );
       crashlytics.log("points in RotationAngle: "+pointNum);
       return 0;
       }
diff --git a/src/main/java/org/distorted/objects/RubikCube.java b/src/main/java/org/distorted/objects/RubikCube.java
index 497c1622..138fbb62 100644
--- a/src/main/java/org/distorted/objects/RubikCube.java
+++ b/src/main/java/org/distorted/objects/RubikCube.java
@@ -22,9 +22,8 @@ package org.distorted.objects;
 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.effect.VertexEffectMove;
+import org.distorted.library.effect.VertexEffectRotate;
 import org.distorted.library.effect.VertexEffectSink;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedTexture;
@@ -76,6 +75,8 @@ class RubikCube extends RubikObject
           -0.5f*((float)Math.sqrt(2))
          };
 
+  private static MeshBase mMesh = null;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   RubikCube(int size, Static4D quatCur, Static4D quatAcc, DistortedTexture texture, MeshRectangles mesh, DistortedEffects effects, int[][] moves)
@@ -162,39 +163,52 @@ class RubikCube extends RubikObject
 
   MeshBase createCubitMesh(int cubit, int vertices)
     {
-    final int MESHES=6;
+    if( mMesh==null )
+      {
+      final int MESHES=6;
+      int association = 1;
+      MeshBase[] meshes = new MeshRectangles[MESHES];
+      meshes[0] = new MeshRectangles(vertices,vertices);
+      meshes[0].setEffectAssociation(0,association);
 
-    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);
+      for(int i=1; i<MESHES; i++)
+        {
+        association <<=1;
+        meshes[i] = meshes[0].copy(true);
+        meshes[i].setEffectAssociation(0,association);
+        }
+
+      mMesh = new MeshJoined(meshes);
+
+      Static3D axisY   = new Static3D(0,1,0);
+      Static3D axisX   = new Static3D(1,0,0);
+      Static3D center  = new Static3D(0,0,0);
+      Static1D angle90 = new Static1D(90);
+      Static1D angle180= new Static1D(180);
+      Static1D angle270= new Static1D(270);
+
+      VertexEffectMove   effect0 = new VertexEffectMove(new Static3D(0,0,+0.5f));
+      effect0.setMeshAssociation(63);  // all 6 sides
+      VertexEffectRotate effect1 = new VertexEffectRotate( angle180, axisX, center );
+      effect1.setMeshAssociation(32);  // back
+      VertexEffectRotate effect2 = new VertexEffectRotate( angle90 , axisX, center );
+      effect2.setMeshAssociation(8);  // bottom
+      VertexEffectRotate effect3 = new VertexEffectRotate( angle270, axisX, center );
+      effect3.setMeshAssociation(4);  // top
+      VertexEffectRotate effect4 = new VertexEffectRotate( angle270, axisY, center );
+      effect4.setMeshAssociation(2);  // left
+      VertexEffectRotate effect5 = new VertexEffectRotate( angle90 , axisY, center );
+      effect5.setMeshAssociation(1);  // right
+
+      mMesh.apply(effect0);
+      mMesh.apply(effect1);
+      mMesh.apply(effect2);
+      mMesh.apply(effect3);
+      mMesh.apply(effect4);
+      mMesh.apply(effect5);
+      }
+
+    return mMesh.copy(false);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/RubikPyraminx.java b/src/main/java/org/distorted/objects/RubikPyraminx.java
index adb07286..566ab7ae 100644
--- a/src/main/java/org/distorted/objects/RubikPyraminx.java
+++ b/src/main/java/org/distorted/objects/RubikPyraminx.java
@@ -22,10 +22,10 @@ package org.distorted.objects;
 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.effect.MatrixEffectScale;
+import org.distorted.library.effect.VertexEffectDeform;
+import org.distorted.library.effect.VertexEffectMove;
+import org.distorted.library.effect.VertexEffectRotate;
+import org.distorted.library.effect.VertexEffectScale;
 import org.distorted.library.effect.VertexEffectSink;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedTexture;
@@ -66,18 +66,22 @@ public class RubikPyraminx extends RubikObject
          };
 
   private int[] mRotArray;
-  private static MatrixEffectRotate[][] ROTATION;
+  private static VertexEffectRotate[] ROTATION;
+
+  private static MeshBase mMesh =null;
+  private static MeshBase[] mMeshRotated = new MeshBase[AXIS.length];
 
   static
     {
     Static3D center = new Static3D(0,0,0);
     Static1D angle  = new Static1D(180.0f);
 
-    ROTATION = new MatrixEffectRotate[AXIS.length][1];
+    ROTATION = new VertexEffectRotate[AXIS.length];
 
     for(int i=0; i<AXIS.length; i++)
       {
-      ROTATION[i][0] = new MatrixEffectRotate( angle, AXIS[i], center);
+      ROTATION[i] = new VertexEffectRotate( angle, AXIS[i], center);
+      mMeshRotated[i] = null;
       }
     }
 
@@ -210,41 +214,97 @@ public class RubikPyraminx extends RubikObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  MeshBase createCubitMesh(int cubit, int vertices)
+  private MeshBase createStaticMesh(int cubit, int vertices)
     {
+    final float SQ2 = (float)Math.sqrt(2);
+    final float SQ3 = (float)Math.sqrt(3);
     final float angleFaces = (float)((180/Math.PI)*(2*Math.asin(SQ3/3))); // angle between two faces of a tetrahedron
     final int MESHES=4;
 
+    int association = 1;
     MeshBase[] meshes = new MeshTriangles[MESHES];
-    for(int i=0; i<MESHES; i++) meshes[i] = new MeshTriangles(5);
-
-    MatrixEffect[] effects0 = new MatrixEffect[3];
-    effects0[0] = new MatrixEffectScale( new Static3D(1,SQ3/2,1) );
-    effects0[1] = new MatrixEffectRotate( new Static1D(90), new Static3D(1,0,0), new Static3D(0,0,0) );
-    effects0[2] = new MatrixEffectMove( new Static3D(0,-SQ3*SQ2/12,SQ3/12) );
-
-    meshes[0].apply(effects0);
-
-    Static1D angle = new Static1D(angleFaces);
-    Static3D axis  = new Static3D(-1,0,0);
-    Static3D center= new Static3D(0,-SQ3*SQ2/12,-SQ3/6);
 
-    MatrixEffect[] effects1 = new MatrixEffect[5];
-    effects1[0] = effects0[0];
-    effects1[1] = effects0[1];
-    effects1[2] = effects0[2];
-    effects1[3] = new MatrixEffectRotate( new Static1D(180), new Static3D(0,0,1), center );
-    effects1[4] = new MatrixEffectRotate( angle, axis, center );
-    meshes[1].apply(effects1);
+    meshes[0] = new MeshTriangles(5);
+    meshes[0].setEffectAssociation(0,association);
 
-    axis.set(0.5f,0,-SQ3/2);
-    center.set2(SQ3/3);
-    meshes[2].apply(effects1);
-
-    axis.set2(SQ3/2);
-    meshes[3].apply(effects1);
+    for(int i=1; i<MESHES; i++)
+      {
+      association <<= 1;
+      meshes[i] = meshes[0].copy(true);
+      meshes[i].setEffectAssociation(0,association);
+      }
 
-    MeshJoined result = new MeshJoined(meshes);
+    Static4D[] textureMaps = new Static4D[MESHES];
+    for(int i=0; i<MESHES; i++) textureMaps[i] = new Static4D(i*0.25f,0.0f,0.25f,1.0f);
+    MeshBase result = new MeshJoined(meshes);
+    result.setTextureMap(textureMaps);
+
+    Static3D a0 = new Static3D(         0,        1,       0 );
+    Static3D a1 = new Static3D(         0,  -1.0f/3, 2*SQ2/3 );
+    Static3D a2 = new Static3D(-SQ2*SQ3/3,  -1.0f/3,  -SQ2/3 );
+    Static3D a3 = new Static3D( SQ2*SQ3/3,  -1.0f/3,  -SQ2/3 );
+
+    float tetraHeight = SQ2*SQ3/3;
+    float d1 = 0.75f*tetraHeight;
+    float d2 =-0.10f*tetraHeight;
+    float d3 = 0.20f*tetraHeight;
+
+    Static3D dCen0 = new Static3D( d1*a0.get0(), d1*a0.get1(), d1*a0.get2() );
+    Static3D dCen1 = new Static3D( d1*a1.get0(), d1*a1.get1(), d1*a1.get2() );
+    Static3D dCen2 = new Static3D( d1*a2.get0(), d1*a2.get1(), d1*a2.get2() );
+    Static3D dCen3 = new Static3D( d1*a3.get0(), d1*a3.get1(), d1*a3.get2() );
+
+    Static3D dVec0 = new Static3D( d2*a0.get0(), d2*a0.get1(), d2*a0.get2() );
+    Static3D dVec1 = new Static3D( d2*a1.get0(), d2*a1.get1(), d2*a1.get2() );
+    Static3D dVec2 = new Static3D( d2*a2.get0(), d2*a2.get1(), d2*a2.get2() );
+    Static3D dVec3 = new Static3D( d2*a3.get0(), d2*a3.get1(), d2*a3.get2() );
+
+    Static4D dReg  = new Static4D(0,0,0,d3);
+    Static1D dRad  = new Static1D(1);
+
+    Static1D angle  = new Static1D(angleFaces);
+    Static3D axis1  = new Static3D(  -1, 0,      0);
+    Static3D axis2  = new Static3D(0.5f, 0, -SQ3/2);
+    Static3D axis3  = new Static3D(0.5f, 0, +SQ3/2);
+    Static3D center1= new Static3D(0,-SQ3*SQ2/12,-SQ3/6);
+    Static3D center2= new Static3D(0,-SQ3*SQ2/12,+SQ3/3);
+
+    VertexEffectScale effect1 = new VertexEffectScale ( new Static3D(1,SQ3/2,1) );
+    VertexEffectRotate  effect2 = new VertexEffectRotate( new Static1D(90), new Static3D(1,0,0), new Static3D(0,0,0) );
+    VertexEffectMove effect3 = new VertexEffectMove  ( new Static3D(0,-SQ3*SQ2/12,SQ3/12) );
+    VertexEffectRotate  effect4 = new VertexEffectRotate( new Static1D(180), new Static3D(0,0,1), center1 );
+    VertexEffectRotate  effect5 = new VertexEffectRotate( angle, axis1, center1 );
+    VertexEffectRotate  effect6 = new VertexEffectRotate( angle, axis2, center2 );
+    VertexEffectRotate  effect7 = new VertexEffectRotate( angle, axis3, center2 );
+
+    VertexEffectDeform effect8 = new VertexEffectDeform(dVec0, dRad, dCen0, dReg);
+    VertexEffectDeform effect9 = new VertexEffectDeform(dVec1, dRad, dCen1, dReg);
+    VertexEffectDeform effect10= new VertexEffectDeform(dVec2, dRad, dCen2, dReg);
+    VertexEffectDeform effect11= new VertexEffectDeform(dVec3, dRad, dCen3, dReg);
+
+    effect1.setMeshAssociation(15);  // apply to all 4 meshes
+    effect2.setMeshAssociation(15);  // apply to all 4 meshes
+    effect3.setMeshAssociation(15);  // apply to all 4 meshes
+    effect4.setMeshAssociation(14);  // apply to mesh[1], [2] and [3]
+    effect5.setMeshAssociation( 2);  // apply only to mesh[1]
+    effect6.setMeshAssociation( 4);  // apply only to mesh[2]
+    effect7.setMeshAssociation( 8);  // apply only to mesh[3]
+    effect8.setMeshAssociation(15);  // apply to all 4 meshes
+    effect9.setMeshAssociation(15);  // apply to all 4 meshes
+    effect10.setMeshAssociation(15); // apply to all 4 meshes
+    effect11.setMeshAssociation(15); // apply to all 4 meshes
+
+    result.apply(effect1);
+    result.apply(effect2);
+    result.apply(effect3);
+    result.apply(effect4);
+    result.apply(effect5);
+    result.apply(effect6);
+    result.apply(effect7);
+    result.apply(effect8);
+    result.apply(effect9);
+    result.apply(effect10);
+    result.apply(effect11);
 
     if( mRotArray[cubit]>=0 )
       {
@@ -254,6 +314,24 @@ public class RubikPyraminx extends RubikObject
     return result;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  MeshBase createCubitMesh(int cubit, int vertices)
+    {
+    int kind = mRotArray[cubit];
+
+    if( kind>=0 )
+      {
+      if( mMeshRotated[kind]==null ) mMeshRotated[kind] = createStaticMesh(cubit,vertices);
+      return mMeshRotated[kind].copy(false);
+      }
+    else
+      {
+      if( mMesh==null ) mMesh = createStaticMesh(cubit,vertices);
+      return mMesh.copy(false);
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side)
