commit 105853851059af975a63b66e412348db449dae07
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Jun 7 21:42:42 2020 +0100

    More progreess porting RubikCube.

diff --git a/src/main/java/org/distorted/main/RubikRenderer.java b/src/main/java/org/distorted/main/RubikRenderer.java
index 8aad826a..3980f6d6 100644
--- a/src/main/java/org/distorted/main/RubikRenderer.java
+++ b/src/main/java/org/distorted/main/RubikRenderer.java
@@ -49,6 +49,7 @@ public class RubikRenderer implements GLSurfaceView.Renderer
      mView = v;
      mScreen = new DistortedScreen();
      mScreen.glClearColor(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS, 1.0f);
+     mScreen.showFPS();
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -77,7 +78,7 @@ public class RubikRenderer implements GLSurfaceView.Renderer
    @Override
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
       {
-      DistortedLibrary.setMax(EffectType.VERTEX,15);
+      DistortedLibrary.setMax(EffectType.VERTEX,25);    // 24 Cube Quats + Rotate
       VertexEffectRotate.enable();
       BaseEffect.Type.enableEffects();
 
diff --git a/src/main/java/org/distorted/objects/Cubit.java b/src/main/java/org/distorted/objects/Cubit.java
index 29b89e52..ecd293e6 100644
--- a/src/main/java/org/distorted/objects/Cubit.java
+++ b/src/main/java/org/distorted/objects/Cubit.java
@@ -64,7 +64,7 @@ class Cubit
 //
 // We also have to remember that the group of unit quaternions is a double-cover of rotations
 // in 3D ( q represents the same rotation as -q ) - so invert if needed.
-
+/*
   private void normalizeScrambleQuat(Static4D quat)
     {
     final float MAX_ERROR = 0.0001f;
@@ -121,7 +121,7 @@ class Cubit
 
     quat.set(x,y,z,w);
     }
-
+*/
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void modifyCurrentPosition(Static4D quat)
@@ -284,7 +284,7 @@ class Cubit
   void removeRotationNow(Static4D quat)
     {
     mQuatScramble.set(RubikSurfaceView.quatMultiply(quat,mQuatScramble));
-    normalizeScrambleQuat( mQuatScramble );
+ //   normalizeScrambleQuat( mQuatScramble );
     modifyCurrentPosition(quat);
     }
 
diff --git a/src/main/java/org/distorted/objects/RubikCube.java b/src/main/java/org/distorted/objects/RubikCube.java
index e6f1aeb9..1bc863ff 100644
--- a/src/main/java/org/distorted/objects/RubikCube.java
+++ b/src/main/java/org/distorted/objects/RubikCube.java
@@ -39,6 +39,8 @@ import org.distorted.library.type.Static4D;
 
 class RubikCube extends RubikObject
 {
+  static final float SQ2 = (float)Math.sqrt(2);
+
   // the three rotation axis of a RubikCube. Must be normalized.
   static final Static3D[] AXIS = new Static3D[]
          {
@@ -54,26 +56,41 @@ class RubikCube extends RubikObject
            0xffff0000, 0xffb5651d    // AXIS[2]right (front-RED   ) AXIS[2]left (back  -BROWN)
          };
 
-  // All legal rotation quats of a RubikCube of any size must have all four of their components
-  // equal to either 0, +-1, +-0.5 or +-sqrt(2)/2.
+  // All legal rotation quats of a RubikCube of any size.
   // Here's how to compute this:
   // 1) compute how many rotations there are (RubikCube of any size = 24)
   // 2) take the AXIS, angles of rotation (90 in RubikCube's case) compute the basic quaternions
   // (i.e. rotations of 1 basic angle along each of the axis) and from there start semi-randomly
   // multiplying them and eventually you'll find all (24) legal rotations.
-  // 3) linear scan through those shows that the only floats in those 24 quats are those 7 given
-  // below.
-  //
   // Example program in C, res/raw/compute_quats.c , is included.
-  private static final float[] LEGALQUATS = new float[]
+  private static final Static4D[] QUATS = new Static4D[]
          {
-           0.0f ,
-           0.5f ,
-          -0.5f ,
-           1.0f ,
-          -1.0f ,
-           0.5f*((float)Math.sqrt(2)) ,
-          -0.5f*((float)Math.sqrt(2))
+         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
+         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
+         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
+         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
+
+         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
+         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
+         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
+         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
+         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
+         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
+         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
+         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
+         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
+         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
+         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
+         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
+
+         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
+         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
+         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
+         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
+         new Static4D( -0.5f,  -0.5f,  -0.5f,   0.5f),
+         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
+         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
+         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
          };
 
   private static MeshBase mMesh = null;
@@ -121,9 +138,9 @@ class RubikCube extends RubikObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  float[] getLegalQuats()
+  Static4D[] getQuats()
     {
-    return LEGALQUATS;
+    return QUATS;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/RubikObject.java b/src/main/java/org/distorted/objects/RubikObject.java
index a0e61f8f..97270db0 100644
--- a/src/main/java/org/distorted/objects/RubikObject.java
+++ b/src/main/java/org/distorted/objects/RubikObject.java
@@ -30,6 +30,7 @@ import org.distorted.library.effect.Effect;
 import org.distorted.library.effect.MatrixEffectMove;
 import org.distorted.library.effect.MatrixEffectQuaternion;
 import org.distorted.library.effect.MatrixEffectScale;
+import org.distorted.library.effect.VertexEffectQuaternion;
 import org.distorted.library.effect.VertexEffectRotate;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedNode;
@@ -53,7 +54,6 @@ public abstract class RubikObject extends DistortedNode
   private static final int POST_ROTATION_MILLISEC = 500;
   private static final int TEXTURE_HEIGHT = 128;
 
-  final float[] LEGAL_QUATS;
   final Static3D[] ROTATION_AXIS;
   final int NUM_FACES;
 
@@ -95,7 +95,7 @@ public abstract class RubikObject extends DistortedNode
     mList = list;
     mOrigPos = getCubitPositions(size);
 
-    LEGAL_QUATS = getLegalQuats();
+    Static4D[] quats = getQuats();
     NUM_CUBITS  = mOrigPos.length;
     ROTATION_AXIS = getRotationAxis();
     OBJECT_SCREEN_RATIO = getScreenRatio();
@@ -131,7 +131,7 @@ public abstract class RubikObject extends DistortedNode
       mCubits[i] = new Cubit(this,mOrigPos[i]);
       cubitMesh[i] = createCubitMesh(i);
       cubitMesh[i].apply(new MatrixEffectMove(mOrigPos[i]),1,0);
-      cubitMesh[i].setEffectAssociation(0, mCubits[i].computeAssociation(), i);
+      cubitMesh[i].setEffectAssociation(0, mCubits[i].computeAssociation(), 0);
       }
 
     mMesh = new MeshJoined(cubitMesh);
@@ -139,6 +139,15 @@ public abstract class RubikObject extends DistortedNode
     resetAllTextureMaps();
 
     mEffects = new DistortedEffects();
+
+    int num_quats = quats.length;
+    for(int q=0; q<num_quats; q++)
+      {
+      VertexEffectQuaternion vq = new VertexEffectQuaternion(quats[q],CENTER);
+      vq.setMeshAssociation(0,q);
+      mEffects.apply(vq);
+      }
+
     mEffects.apply(mRotateEffect);
     mEffects.apply(mQuatAEffect);
     mEffects.apply(mQuatCEffect);
@@ -383,8 +392,6 @@ public abstract class RubikObject extends DistortedNode
   public void releaseResources()
     {
     mTexture.markForDeletion();
-
-    // TODO ?
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -614,7 +621,7 @@ public abstract class RubikObject extends DistortedNode
 
   abstract float getScreenRatio();
   abstract Static3D[] getCubitPositions(int size);
-  abstract float[] getLegalQuats();
+  abstract Static4D[] getQuats();
   abstract int getNumFaces();
   abstract MeshBase createCubitMesh(int cubit);
   abstract void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side);
diff --git a/src/main/java/org/distorted/objects/RubikPyraminx.java b/src/main/java/org/distorted/objects/RubikPyraminx.java
index e4d251a0..468b84ef 100644
--- a/src/main/java/org/distorted/objects/RubikPyraminx.java
+++ b/src/main/java/org/distorted/objects/RubikPyraminx.java
@@ -43,6 +43,7 @@ public class RubikPyraminx extends RubikObject
 {
   private static final float SQ2 = (float)Math.sqrt(2);
   private static final float SQ3 = (float)Math.sqrt(3);
+  private static final float SQ6 = (float)Math.sqrt(6);
 
   static final Static3D[] AXIS = new Static3D[]
          {
@@ -59,10 +60,20 @@ public class RubikPyraminx extends RubikObject
          };
 
   // computed with res/raw/compute_quats.c
-  private static final float[] LEGALQUATS = new float[]
+  private static final Static4D[] QUATS = new Static4D[]
          {
-           0.0f, 1.0f, -1.0f, 0.5f, -0.5f, SQ2/2, -SQ2/2, SQ3/2, -SQ3/2,
-           SQ3/3, -SQ3/3, SQ3/6, -SQ3/6, SQ2*SQ3/3, -SQ2*SQ3/3, SQ2*SQ3/6, -SQ2*SQ3/6
+           new Static4D(  0.0f,   0.0f,   0.0f,  1.0f),
+           new Static4D(  0.0f,  SQ3/2,   0.0f,  0.5f),
+           new Static4D( SQ2/2, -SQ3/6, -SQ6/6,  0.5f),
+           new Static4D(-SQ2/2, -SQ3/6, -SQ6/6,  0.5f),
+           new Static4D(  0.0f, -SQ3/6,  SQ6/3,  0.5f),
+           new Static4D(  0.0f,  SQ3/2,   0.0f, -0.5f),
+           new Static4D( SQ2/2, -SQ3/6, -SQ6/6, -0.5f),
+           new Static4D(-SQ2/2, -SQ3/6, -SQ6/6, -0.5f),
+           new Static4D(  0.0f, -SQ3/6,  SQ6/3, -0.5f),
+           new Static4D( SQ2/2, -SQ3/3,  SQ6/6,  0.0f),
+           new Static4D(  0.0f, -SQ3/3, -SQ6/3,  0.0f),
+           new Static4D(-SQ2/2, -SQ3/3,  SQ6/6,  0.0f)
          };
 
   private int[] mRotArray;
@@ -184,9 +195,9 @@ public class RubikPyraminx extends RubikObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  float[] getLegalQuats()
+  Static4D[] getQuats()
     {
-    return LEGALQUATS;
+    return QUATS;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
