commit fb377daeb7781c37fb404a275251675d45f0fa51
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Tue Aug 11 15:19:52 2020 +0100

    Major progress with Dino; rotations (almost?) work now.

diff --git a/src/main/java/org/distorted/main/RubikSurfaceView.java b/src/main/java/org/distorted/main/RubikSurfaceView.java
index ec31fd89..fa985808 100644
--- a/src/main/java/org/distorted/main/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/main/RubikSurfaceView.java
@@ -466,7 +466,8 @@ public class RubikSurfaceView extends GLSurfaceView
 
       mCurrentAxis = (int)res.get0();
       float offset = res.get1();
-      mCurrentRow = (int)(object.returnMultiplier()*offset);
+      mCurrentRow  = object.computeRowFromOffset(offset);
+
       computeCurrentAxis( object.getRotationAxis()[mCurrentAxis] );
       mRotationFactor = object.returnRotationFactor(offset);
 
diff --git a/src/main/java/org/distorted/objects/RubikCube.java b/src/main/java/org/distorted/objects/RubikCube.java
index 25f0e1c8..5b126213 100644
--- a/src/main/java/org/distorted/objects/RubikCube.java
+++ b/src/main/java/org/distorted/objects/RubikCube.java
@@ -307,6 +307,13 @@ class RubikCube extends RubikObject
     return mMeshes[index].copy(true);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  float returnMultiplier()
+    {
+    return getSize();
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 
@@ -324,9 +331,9 @@ class RubikCube extends RubikObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public float returnMultiplier()
+  public int computeRowFromOffset(float offset)
     {
-    return getSize();
+    return (int)(getSize()*offset);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/RubikDino.java b/src/main/java/org/distorted/objects/RubikDino.java
index 58013e3e..e1e77cef 100644
--- a/src/main/java/org/distorted/objects/RubikDino.java
+++ b/src/main/java/org/distorted/objects/RubikDino.java
@@ -331,6 +331,13 @@ public class RubikDino extends RubikObject
     canvas.drawArc( ARC3_W-RADIUS+left, ARC2_H-RADIUS, ARC3_W+RADIUS+left, ARC2_H+RADIUS, 345, 90, false, paint);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  float returnMultiplier()
+    {
+    return 2.0f;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 
@@ -348,11 +355,9 @@ public class RubikDino extends RubikObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public float returnMultiplier()
+  public int computeRowFromOffset(float offset)
     {
-    // TODO
-
-    return 0;
+    return offset<0.5f ? 0:2;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/RubikMovement.java b/src/main/java/org/distorted/objects/RubikMovement.java
index d8d0f9be..df730dab 100644
--- a/src/main/java/org/distorted/objects/RubikMovement.java
+++ b/src/main/java/org/distorted/objects/RubikMovement.java
@@ -27,17 +27,18 @@ import org.distorted.library.type.Static4D;
 
 public abstract class RubikMovement
   {
-  private int mLastTouchedAxis;
+  private int mLastTouchedFace, mNumFaceAxis;
   private float[] mPoint, mCamera, mTouch;
   private float[] mPoint2D, mMove2D;
   private float[][][] mCastAxis;
-  private int mNumRotAxis, mNumFaceAxis;
+  private int[] mEnabledRotAxis;
   private float mDistanceCenterFace3D, mDistanceCenterFace2D;
   private Static3D[] mFaceAxis;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   abstract boolean isInsideFace(float[] point);
+  abstract void computeEnabledAxis(int face, float[] touchPoint, int[] enabledAxis);
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -50,18 +51,19 @@ public abstract class RubikMovement
     mPoint2D = new float[2];
     mMove2D  = new float[2];
 
-    mNumRotAxis = rotAxis.length;
     mFaceAxis   = faceAxis;
     mNumFaceAxis= mFaceAxis.length;
 
+    mEnabledRotAxis = new int[rotAxis.length+1];
+
     mDistanceCenterFace3D = distance3D; // distance from the center of the object to each of its faces
     mDistanceCenterFace2D = distance2D; // distance from the center of a face to its edge
 
     // mCastAxis[1][2]{0,1} are the 2D coords of the 2nd axis cast onto the face defined by the
     // 1st pair (axis,lr)
-    mCastAxis = new float[mNumFaceAxis][mNumRotAxis][2];
+    mCastAxis = new float[mNumFaceAxis][rotAxis.length][2];
 
-    for( int casted=0; casted<mNumRotAxis; casted++)
+    for( int casted=0; casted<rotAxis.length; casted++)
       {
       Static3D a = rotAxis[casted];
       mPoint[0]= a.get0();
@@ -88,14 +90,13 @@ public abstract class RubikMovement
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // find the casted axis with which our move2D vector forms an angle closest to 90 deg.
 
-  private int computeRotationIndex(int faceAxis, float[] move2D)
+  private int computeRotationIndex(int faceAxis, float[] move2D, int[] enabled)
     {
     float cosAngle, minCosAngle = Float.MAX_VALUE;
-    int minIndex=-1;
+    int minIndex=-1, index;
     float m0 = move2D[0];
     float m1 = move2D[1];
     float len = (float)Math.sqrt(m0*m0 + m1*m1);
-    float x,y;
 
     if( len!=0.0f )
       {
@@ -108,21 +109,18 @@ public abstract class RubikMovement
       m1 = 0.0f;  //
       }
 
-    for(int rotAxis=0; rotAxis<mNumRotAxis; rotAxis++)
+    int numAxis = enabled[0];
+
+    for(int axis=1; axis<=numAxis; axis++)
       {
-      x = mCastAxis[faceAxis][rotAxis][0];
-      y = mCastAxis[faceAxis][rotAxis][1];
+      index = enabled[axis];
+      cosAngle = m0*mCastAxis[faceAxis][index][0] + m1*mCastAxis[faceAxis][index][1];
+      if( cosAngle<0 ) cosAngle = -cosAngle;
 
-      if( x*x + y*y > 0.01f )
+      if( cosAngle<minCosAngle )
         {
-        cosAngle = m0*x + m1*y;
-        if( cosAngle<0 ) cosAngle = -cosAngle;
-
-        if( cosAngle<minCosAngle )
-          {
-          minCosAngle=cosAngle;
-          minIndex = rotAxis;
-          }
+        minCosAngle=cosAngle;
+        minIndex = index;
         }
       }
 
@@ -242,12 +240,12 @@ public abstract class RubikMovement
     mCamera[1] = rotatedCamera.get1()/objectRatio;
     mCamera[2] = rotatedCamera.get2()/objectRatio;
 
-    for( mLastTouchedAxis=0; mLastTouchedAxis<mNumFaceAxis; mLastTouchedAxis++)
+    for( mLastTouchedFace=0; mLastTouchedFace<mNumFaceAxis; mLastTouchedFace++)
       {
-      if( faceIsVisible(mFaceAxis[mLastTouchedAxis]) )
+      if( faceIsVisible(mFaceAxis[mLastTouchedFace]) )
         {
-        castTouchPointOntoFace(mFaceAxis[mLastTouchedAxis], mTouch);
-        convertTo2Dcoords(mTouch, mFaceAxis[mLastTouchedAxis], mPoint2D);
+        castTouchPointOntoFace(mFaceAxis[mLastTouchedFace], mTouch);
+        convertTo2Dcoords(mTouch, mFaceAxis[mLastTouchedFace], mPoint2D);
         if( isInsideFace(mPoint2D) ) return true;
         }
       }
@@ -265,14 +263,15 @@ public abstract class RubikMovement
     mPoint[1] = rotatedTouchPoint.get1()/objectRatio;
     mPoint[2] = rotatedTouchPoint.get2()/objectRatio;
 
-    castTouchPointOntoFace(mFaceAxis[mLastTouchedAxis], mTouch);
-    convertTo2Dcoords(mTouch, mFaceAxis[mLastTouchedAxis], mMove2D);
+    castTouchPointOntoFace(mFaceAxis[mLastTouchedFace], mTouch);
+    convertTo2Dcoords(mTouch, mFaceAxis[mLastTouchedFace], mMove2D);
 
     mMove2D[0] -= mPoint2D[0];
     mMove2D[1] -= mPoint2D[1];
 
-    int rotIndex = computeRotationIndex(mLastTouchedAxis, mMove2D);
-    float offset = computeOffset(mPoint2D, mCastAxis[mLastTouchedAxis][rotIndex]);
+    computeEnabledAxis(mLastTouchedFace, mPoint2D, mEnabledRotAxis);
+    int rotIndex = computeRotationIndex(mLastTouchedFace, mMove2D, mEnabledRotAxis);
+    float offset = computeOffset(mPoint2D, mCastAxis[mLastTouchedFace][rotIndex]);
 
     return new Static2D(rotIndex,offset);
     }
@@ -281,7 +280,7 @@ public abstract class RubikMovement
 
   public int getTouchedFace()
     {
-    return mLastTouchedAxis;
+    return mLastTouchedFace;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/RubikMovementCube.java b/src/main/java/org/distorted/objects/RubikMovementCube.java
index 05d0cca8..d3730d3f 100644
--- a/src/main/java/org/distorted/objects/RubikMovementCube.java
+++ b/src/main/java/org/distorted/objects/RubikMovementCube.java
@@ -34,4 +34,21 @@ class RubikMovementCube extends RubikMovement
     {
     return ( p[0]<=0.5f && p[0]>=-0.5f && p[1]<=0.5f && p[1]>=-0.5f );
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void computeEnabledAxis(int face, float[] touchPoint, int[] enabled)
+    {
+    enabled[0] = 2;
+
+    switch(face)
+      {
+      case 0:
+      case 1: enabled[1]=1; enabled[2]=2; break;
+      case 2:
+      case 3: enabled[1]=0; enabled[2]=2; break;
+      case 4:
+      case 5: enabled[1]=0; enabled[2]=1; break;
+      }
+    }
 }
diff --git a/src/main/java/org/distorted/objects/RubikMovementDino.java b/src/main/java/org/distorted/objects/RubikMovementDino.java
index 0f57830f..a8b51e9f 100644
--- a/src/main/java/org/distorted/objects/RubikMovementDino.java
+++ b/src/main/java/org/distorted/objects/RubikMovementDino.java
@@ -28,10 +28,89 @@ class RubikMovementDino extends RubikMovement
     super(RubikDino.ROT_AXIS, RubikDino.FACE_AXIS, 0.5f, 0.5f);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// _____________
+// |  \  0  /  |
+// |   \   /   |
+// | 3 |   | 1 |
+// |   /   \   |
+// |  /  2  \  |
+// -------------
+
+  private int getQuarter(float[] touchPoint)
+    {
+    boolean p0 = touchPoint[1] >= touchPoint[0];
+    boolean p1 = touchPoint[1] >=-touchPoint[0];
+
+    if( p0 )  return p1 ? 0:3;
+    else      return p1 ? 1:2;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   boolean isInsideFace(float[] p)
     {
     return ( p[0]<=0.5f && p[0]>=-0.5f && p[1]<=0.5f && p[1]>=-0.5f );
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void computeEnabledAxis(int face, float[] touchPoint, int[] enabled)
+    {
+    enabled[0] = 2;
+
+    int quarter = getQuarter(touchPoint);
+
+    switch(face)
+      {
+      case 0: switch(quarter)
+                {
+                case 0: enabled[1]=0; enabled[2]=1; break;
+                case 1: enabled[1]=3; enabled[2]=1; break;
+                case 2: enabled[1]=2; enabled[2]=3; break;
+                case 3: enabled[1]=0; enabled[2]=2; break;
+                }
+              break;
+      case 1: switch(quarter)
+                {
+                case 0: enabled[1]=2; enabled[2]=3; break;
+                case 1: enabled[1]=3; enabled[2]=1; break;
+                case 2: enabled[1]=0; enabled[2]=1; break;
+                case 3: enabled[1]=0; enabled[2]=2; break;
+                }
+              break;
+      case 2: switch(quarter)
+                {
+                case 0: enabled[1]=1; enabled[2]=2; break;
+                case 1: enabled[1]=0; enabled[2]=1; break;
+                case 2: enabled[1]=0; enabled[2]=3; break;
+                case 3: enabled[1]=2; enabled[2]=3; break;
+                }
+              break;
+      case 3: switch(quarter)
+                {
+                case 0: enabled[1]=1; enabled[2]=2; break;
+                case 1: enabled[1]=2; enabled[2]=3; break;
+                case 2: enabled[1]=0; enabled[2]=3; break;
+                case 3: enabled[1]=0; enabled[2]=1; break;
+                }
+              break;
+      case 4: switch(quarter)
+                {
+                case 0: enabled[1]=0; enabled[2]=3; break;
+                case 1: enabled[1]=0; enabled[2]=2; break;
+                case 2: enabled[1]=1; enabled[2]=2; break;
+                case 3: enabled[1]=1; enabled[2]=3; break;
+                }
+              break;
+      case 5: switch(quarter)
+                {
+                case 0: enabled[1]=1; enabled[2]=2; break;
+                case 1: enabled[1]=0; enabled[2]=2; break;
+                case 2: enabled[1]=0; enabled[2]=3; break;
+                case 3: enabled[1]=1; enabled[2]=3; break;
+                }
+              break;
+      }
+    }
 }
diff --git a/src/main/java/org/distorted/objects/RubikMovementPyraminx.java b/src/main/java/org/distorted/objects/RubikMovementPyraminx.java
index 5ab1fed8..878b3d04 100644
--- a/src/main/java/org/distorted/objects/RubikMovementPyraminx.java
+++ b/src/main/java/org/distorted/objects/RubikMovementPyraminx.java
@@ -43,4 +43,19 @@ class RubikMovementPyraminx extends RubikMovement
 
     return a1 && a2 && a3;
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void computeEnabledAxis(int face, float[] touchPoint, int[] enabled)
+    {
+    enabled[0] = 3;
+
+    switch(face)
+      {
+      case 0: enabled[1]=1; enabled[2]=2; enabled[3]=3; break;
+      case 1: enabled[1]=0; enabled[2]=2; enabled[3]=3; break;
+      case 2: enabled[1]=0; enabled[2]=1; enabled[3]=3; break;
+      case 3: enabled[1]=0; enabled[2]=1; enabled[3]=2; break;
+      }
+    }
 }
diff --git a/src/main/java/org/distorted/objects/RubikObject.java b/src/main/java/org/distorted/objects/RubikObject.java
index 619d6d45..84247029 100644
--- a/src/main/java/org/distorted/objects/RubikObject.java
+++ b/src/main/java/org/distorted/objects/RubikObject.java
@@ -63,7 +63,7 @@ public abstract class RubikObject extends DistortedNode
   private static final Static3D CENTER = new Static3D(0,0,0);
   static final int INTERIOR_COLOR = 0xff000000;
   private static final int POST_ROTATION_MILLISEC = 500;
-  private static final int TEXTURE_HEIGHT = 128;
+  private static final int TEXTURE_HEIGHT = 256;
 
   final Static3D[] ROTATION_AXIS;
   final Static4D[] QUATS;
@@ -695,9 +695,10 @@ public abstract class RubikObject extends DistortedNode
   abstract MeshBase createCubitMesh(int cubit);
   abstract void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side);
   abstract int getFaceColor(int cubit, int cubitface, int size);
+  abstract float returnMultiplier();
   public abstract Static3D[] getRotationAxis();
   public abstract int getBasicAngle();
-  public abstract float returnMultiplier();
+  public abstract int computeRowFromOffset(float offset);
   public abstract float returnRotationFactor(float offset);
   public abstract String retObjectString();
   public abstract float[] getRowChances();
diff --git a/src/main/java/org/distorted/objects/RubikPyraminx.java b/src/main/java/org/distorted/objects/RubikPyraminx.java
index 909a174c..be480366 100644
--- a/src/main/java/org/distorted/objects/RubikPyraminx.java
+++ b/src/main/java/org/distorted/objects/RubikPyraminx.java
@@ -391,6 +391,14 @@ public class RubikPyraminx extends RubikObject
     canvas.drawArc( ARC3_W-RADIUS+left, ARC2_H-RADIUS, ARC3_W+RADIUS+left, ARC2_H+RADIUS, 345, 90, false, paint);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// I don't quite understand it, but 0.82 works better than the theoretically correct SQ3/2 ( 0.866 )
+
+  float returnMultiplier()
+    {
+    return getSize()/0.82f;//(SQ3/2);
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 
@@ -407,11 +415,11 @@ public class RubikPyraminx extends RubikObject
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// I don't quite understand it, but 0.82 works better than the theoretically correct SQ3/2 ( 0.866 )
+// 0.82?? see returnMultiplier()
 
-  public float returnMultiplier()
+  public int computeRowFromOffset(float offset)
     {
-    return getSize()/0.82f;//(SQ3/2);
+    return (int)(getSize()*offset/0.82f);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/scores/RubikScoresDownloader.java b/src/main/java/org/distorted/scores/RubikScoresDownloader.java
index 1fdf6d1a..c124d90f 100644
--- a/src/main/java/org/distorted/scores/RubikScoresDownloader.java
+++ b/src/main/java/org/distorted/scores/RubikScoresDownloader.java
@@ -373,13 +373,13 @@ public class RubikScoresDownloader implements Runnable
     String timlist = scores.getUnsubmittedTimelist();
     String country = scores.getCountry();
     long epoch = System.currentTimeMillis();
-    String salt = "cubold";
+    String salt = "cuboid";
 
     String url1="https://distorted.org/magic/cgi-bin/submit.cgi";
     String url2 = "n="+name+"&v="+veri+"&r="+numRuns+"&p="+numPlay+"&i="+deviceID+"&e="+mVersion+"d";
     url2 += "&o="+objlist+"&l="+lvllist+"&t="+timlist+"&c="+country+"&f="+epoch;
     url2 += "&oo="+RubikObjectList.getObjectList()+"&min=0&max="+MAX_LEVEL+"&lo="+MAX_PLACES;
-    url2 += "&h="+computeHash( url2+"d", salt.getBytes() );
+    url2 += "&h="+computeHash( url2, salt.getBytes() );
 
     return url1 + "?" + url2;
     }
