commit 14bd7976802f3b3c3e135810eb4db9edeb6bc71a
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Tue May 26 13:53:47 2020 +0100

    1) Cube: convert it to the latest library. Main difference: objects are rendered better, individual cubits have rounded corners.
    2) Examples: some adjustments to MeshJoin & Predeform
    3) Library: fix a bug in main_vertex_shader's 'degree' function, which didn't work proprely in case of a vertex which was exactly at the center (i.e. vector PS was zero)

diff --git a/src/main/java/org/distorted/main/RubikRenderer.java b/src/main/java/org/distorted/main/RubikRenderer.java
index bad78b60..3e49d1d8 100644
--- a/src/main/java/org/distorted/main/RubikRenderer.java
+++ b/src/main/java/org/distorted/main/RubikRenderer.java
@@ -24,7 +24,6 @@ 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;
 
@@ -44,8 +43,13 @@ public class RubikRenderer implements GLSurfaceView.Renderer
 
    RubikRenderer(RubikSurfaceView v)
      {
+     final float BRIGHTNESS = 0.1f;
+
      mView = v;
      mScreen = new DistortedScreen();
+     mScreen.glClearColor(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS, 1.0f);
+
+     mScreen.showFPS();
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -74,8 +78,7 @@ public class RubikRenderer implements GLSurfaceView.Renderer
    @Override
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
       {
-      DistortedLibrary.setMax(EffectType.VERTEX,12);
-      VertexEffectSink.enable();
+      DistortedLibrary.setMax(EffectType.VERTEX,15);
       BaseEffect.Type.enableEffects();
 
       try
diff --git a/src/main/java/org/distorted/objects/Cubit.java b/src/main/java/org/distorted/objects/Cubit.java
index 7e03d262..1dccb2ed 100644
--- a/src/main/java/org/distorted/objects/Cubit.java
+++ b/src/main/java/org/distorted/objects/Cubit.java
@@ -187,7 +187,6 @@ class Cubit
     computeRotationRow();
 
     mEffect = new DistortedEffects();
-    mEffect.apply(mParent.mSinkEffect);
     mEffect.apply( new MatrixEffectMove(vector) );
     mEffect.apply( new MatrixEffectQuaternion(mQuatScramble, matrCenter));
     mEffect.apply(mRotateEffect);
diff --git a/src/main/java/org/distorted/objects/RubikCube.java b/src/main/java/org/distorted/objects/RubikCube.java
index 138fbb62..2998e716 100644
--- a/src/main/java/org/distorted/objects/RubikCube.java
+++ b/src/main/java/org/distorted/objects/RubikCube.java
@@ -22,6 +22,7 @@ package org.distorted.objects;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 
+import org.distorted.library.effect.VertexEffectDeform;
 import org.distorted.library.effect.VertexEffectMove;
 import org.distorted.library.effect.VertexEffectRotate;
 import org.distorted.library.effect.VertexEffectSink;
@@ -141,34 +142,14 @@ class RubikCube extends RubikObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  VertexEffectSink getSink(int size)
-    {
-    Static3D center = new Static3D(0,0,0);
-    Static4D region = new Static4D(0,0,0,0.72f);
-    float strength;
-
-    switch(size)
-      {
-      case 1 : strength= 1.1f; break;
-      case 2 : strength= 1.5f; break;
-      case 3 : strength= 1.8f; break;
-      case 4 : strength= 2.0f; break;
-      default: strength= 3.0f - 4.0f/size;
-      }
-
-    return new VertexEffectSink( new Static1D(strength), center, region );
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  MeshBase createCubitMesh(int cubit, int vertices)
+  MeshBase createCubitMesh(int cubit)
     {
     if( mMesh==null )
       {
       final int MESHES=6;
       int association = 1;
       MeshBase[] meshes = new MeshRectangles[MESHES];
-      meshes[0] = new MeshRectangles(vertices,vertices);
+      meshes[0] = new MeshRectangles(14,14);
       meshes[0].setEffectAssociation(0,association);
 
       for(int i=1; i<MESHES; i++)
@@ -187,6 +168,31 @@ class RubikCube extends RubikObject
       Static1D angle180= new Static1D(180);
       Static1D angle270= new Static1D(270);
 
+      float d1 = 1.0f;
+      float d2 =-0.05f;
+      float d3 = 0.12f;
+
+      Static3D dCen0 = new Static3D( d1*(+0.5f), d1*(+0.5f), d1*(+0.5f) );
+      Static3D dCen1 = new Static3D( d1*(+0.5f), d1*(+0.5f), d1*(-0.5f) );
+      Static3D dCen2 = new Static3D( d1*(+0.5f), d1*(-0.5f), d1*(+0.5f) );
+      Static3D dCen3 = new Static3D( d1*(+0.5f), d1*(-0.5f), d1*(-0.5f) );
+      Static3D dCen4 = new Static3D( d1*(-0.5f), d1*(+0.5f), d1*(+0.5f) );
+      Static3D dCen5 = new Static3D( d1*(-0.5f), d1*(+0.5f), d1*(-0.5f) );
+      Static3D dCen6 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*(+0.5f) );
+      Static3D dCen7 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*(-0.5f) );
+
+      Static3D dVec0 = new Static3D( d2*(+0.5f), d2*(+0.5f), d2*(+0.5f) );
+      Static3D dVec1 = new Static3D( d2*(+0.5f), d2*(+0.5f), d2*(-0.5f) );
+      Static3D dVec2 = new Static3D( d2*(+0.5f), d2*(-0.5f), d2*(+0.5f) );
+      Static3D dVec3 = new Static3D( d2*(+0.5f), d2*(-0.5f), d2*(-0.5f) );
+      Static3D dVec4 = new Static3D( d2*(-0.5f), d2*(+0.5f), d2*(+0.5f) );
+      Static3D dVec5 = new Static3D( d2*(-0.5f), d2*(+0.5f), d2*(-0.5f) );
+      Static3D dVec6 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*(+0.5f) );
+      Static3D dVec7 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*(-0.5f) );
+
+      Static4D dReg  = new Static4D(0,0,0,d3);
+      Static1D dRad  = new Static1D(1);
+
       VertexEffectMove   effect0 = new VertexEffectMove(new Static3D(0,0,+0.5f));
       effect0.setMeshAssociation(63);  // all 6 sides
       VertexEffectRotate effect1 = new VertexEffectRotate( angle180, axisX, center );
@@ -200,12 +206,32 @@ class RubikCube extends RubikObject
       VertexEffectRotate effect5 = new VertexEffectRotate( angle90 , axisY, center );
       effect5.setMeshAssociation(1);  // right
 
+      VertexEffectDeform effect6 = new VertexEffectDeform(dVec0, dRad, dCen0, dReg);
+      VertexEffectDeform effect7 = new VertexEffectDeform(dVec1, dRad, dCen1, dReg);
+      VertexEffectDeform effect8 = new VertexEffectDeform(dVec2, dRad, dCen2, dReg);
+      VertexEffectDeform effect9 = new VertexEffectDeform(dVec3, dRad, dCen3, dReg);
+      VertexEffectDeform effect10= new VertexEffectDeform(dVec4, dRad, dCen4, dReg);
+      VertexEffectDeform effect11= new VertexEffectDeform(dVec5, dRad, dCen5, dReg);
+      VertexEffectDeform effect12= new VertexEffectDeform(dVec6, dRad, dCen6, dReg);
+      VertexEffectDeform effect13= new VertexEffectDeform(dVec7, dRad, dCen7, dReg);
+
+      VertexEffectSink   effect14= new VertexEffectSink( new Static1D(1.5f), center, new Static4D(0,0,0,0.72f) );
+
       mMesh.apply(effect0);
       mMesh.apply(effect1);
       mMesh.apply(effect2);
       mMesh.apply(effect3);
       mMesh.apply(effect4);
       mMesh.apply(effect5);
+      mMesh.apply(effect6);
+      mMesh.apply(effect7);
+      mMesh.apply(effect8);
+      mMesh.apply(effect9);
+      mMesh.apply(effect10);
+      mMesh.apply(effect11);
+      mMesh.apply(effect12);
+      mMesh.apply(effect13);
+      mMesh.apply(effect14);
       }
 
     return mMesh.copy(false);
diff --git a/src/main/java/org/distorted/objects/RubikObject.java b/src/main/java/org/distorted/objects/RubikObject.java
index 15be196b..7c59e44d 100644
--- a/src/main/java/org/distorted/objects/RubikObject.java
+++ b/src/main/java/org/distorted/objects/RubikObject.java
@@ -27,7 +27,6 @@ import android.graphics.Paint;
 import org.distorted.library.effect.Effect;
 import org.distorted.library.effect.MatrixEffectQuaternion;
 import org.distorted.library.effect.MatrixEffectScale;
-import org.distorted.library.effect.VertexEffectSink;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedNode;
 import org.distorted.library.main.DistortedTexture;
@@ -42,6 +41,7 @@ import org.distorted.library.type.Static4D;
 
 public abstract class RubikObject extends DistortedNode
   {
+  static final int INTERIOR_COLOR = 0xff000000;
   public static final int NODE_FBO_SIZE = 600;
 
   private static final int TEXTURE_HEIGHT = 128;
@@ -65,7 +65,6 @@ public abstract class RubikObject extends DistortedNode
   Static1D mRotationAngleStatic, mRotationAngleMiddle, mRotationAngleFinal;
   DistortedTexture mTexture;
 
-  VertexEffectSink mSinkEffect;
   MatrixEffectScale mScaleEffect;
   MatrixEffectQuaternion mQuatCEffect;
   MatrixEffectQuaternion mQuatAEffect;
@@ -91,7 +90,6 @@ public abstract class RubikObject extends DistortedNode
     computeStartAndStep(mOrigPos);
     mNodeScale= new Static3D(1,1,1);
     mQuatAccumulated = quatAcc;
-    mSinkEffect  = getSink(mSize);
 
     mRotationAngleStatic = new Static1D(0);
     mRotationAngleMiddle = new Static1D(0);
@@ -109,11 +107,9 @@ public abstract class RubikObject extends DistortedNode
     mCubits = new Cubit[NUM_CUBITS];
     mTexture = new DistortedTexture();
 
-    int vertices = (int)(24.0f/mSize + 2.0f);
-
     for(int i=0; i<NUM_CUBITS; i++)
       {
-      MeshBase cubitMesh = createCubitMesh(i,vertices);
+      MeshBase cubitMesh = createCubitMesh(i);
       mCubits[i] = new Cubit(this,cubitMesh,mOrigPos[i]);
       textureCubitMesh(cubitMesh,i);
 
@@ -300,7 +296,7 @@ public abstract class RubikObject extends DistortedNode
     paint.setTextAlign(Paint.Align.CENTER);
     paint.setStyle(Paint.Style.FILL);
 
-    paint.setColor(0xff000000);
+    paint.setColor(INTERIOR_COLOR);
     canvas.drawRect(0, 0, (numColors+1)*TEXTURE_HEIGHT, TEXTURE_HEIGHT, paint);
 
     for(int i=0; i<numColors; i++)
@@ -596,11 +592,10 @@ public abstract class RubikObject extends DistortedNode
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   abstract float getScreenRatio();
-  abstract VertexEffectSink getSink(int size);
   abstract Static3D[] getCubitPositions(int size);
   abstract float[] getLegalQuats();
   abstract int getNumFaces();
-  abstract MeshBase createCubitMesh(int cubit, int vertices);
+  abstract MeshBase createCubitMesh(int cubit);
   abstract void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side);
   public abstract Static3D[] getRotationAxis();
   public abstract int getBasicAngle();
diff --git a/src/main/java/org/distorted/objects/RubikPyraminx.java b/src/main/java/org/distorted/objects/RubikPyraminx.java
index 566ab7ae..b1d3a9cf 100644
--- a/src/main/java/org/distorted/objects/RubikPyraminx.java
+++ b/src/main/java/org/distorted/objects/RubikPyraminx.java
@@ -205,16 +205,7 @@ public class RubikPyraminx extends RubikObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  VertexEffectSink getSink(int size)
-    {
-    Static3D center = new Static3D(0,0,0);
-    Static4D region = new Static4D(0,0,0,0.6f);
-    return new VertexEffectSink( new Static1D(1.3f), center, region );
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private MeshBase createStaticMesh(int cubit, int vertices)
+  private MeshBase createStaticMesh(int cubit)
     {
     final float SQ2 = (float)Math.sqrt(2);
     final float SQ3 = (float)Math.sqrt(3);
@@ -269,6 +260,9 @@ public class RubikPyraminx extends RubikObject
     Static3D center1= new Static3D(0,-SQ3*SQ2/12,-SQ3/6);
     Static3D center2= new Static3D(0,-SQ3*SQ2/12,+SQ3/3);
 
+    Static3D center = new Static3D(0,0,0);
+    Static4D region = new Static4D(0,0,0,0.6f);
+
     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) );
@@ -282,17 +276,12 @@ public class RubikPyraminx extends RubikObject
     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
+    VertexEffectSink   effect12= new VertexEffectSink( new Static1D(1.3f), center, region );
+
     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);
@@ -305,6 +294,7 @@ public class RubikPyraminx extends RubikObject
     result.apply(effect9);
     result.apply(effect10);
     result.apply(effect11);
+    result.apply(effect12);
 
     if( mRotArray[cubit]>=0 )
       {
@@ -316,18 +306,18 @@ public class RubikPyraminx extends RubikObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  MeshBase createCubitMesh(int cubit, int vertices)
+  MeshBase createCubitMesh(int cubit)
     {
     int kind = mRotArray[cubit];
 
     if( kind>=0 )
       {
-      if( mMeshRotated[kind]==null ) mMeshRotated[kind] = createStaticMesh(cubit,vertices);
+      if( mMeshRotated[kind]==null ) mMeshRotated[kind] = createStaticMesh(cubit);
       return mMeshRotated[kind].copy(false);
       }
     else
       {
-      if( mMesh==null ) mMesh = createStaticMesh(cubit,vertices);
+      if( mMesh==null ) mMesh = createStaticMesh(cubit);
       return mMesh.copy(false);
       }
     }
@@ -354,7 +344,7 @@ public class RubikPyraminx extends RubikObject
 
     canvas.drawRect(left,top,left+side,top+side,paint);
 
-    paint.setColor(0xff000000);
+    paint.setColor(INTERIOR_COLOR);
     paint.setStyle(Paint.Style.STROKE);
 
     canvas.drawLine(           left, HEIGHT,  side       +left, HEIGHT, paint);
