commit 935f36636cdfa75130084053323e1840a9a788eb
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Tue Aug 11 19:12:00 2020 +0100

    Fix the way we continue rotation: when rotating a layer, we need to be doing it with respect to the RotAxis which has been first casted to the touched face, and only then this casted one is casted to the surface of the screen.
    
    Before we were casting the rotAxis directly to the screen without the intermediate casting to the face, which doesn't really work in case of the Dino: if the touched face is rotated away by quite a lot, the rotAxis is then completely counterintuitive.

diff --git a/src/main/java/org/distorted/main/RubikSurfaceView.java b/src/main/java/org/distorted/main/RubikSurfaceView.java
index fa985808..d6f8f4fe 100644
--- a/src/main/java/org/distorted/main/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/main/RubikSurfaceView.java
@@ -164,12 +164,12 @@ public class RubikSurfaceView extends GLSurfaceView
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// cast the 3D axis we are currently rotating along to the 2D in-screen-surface axis
+// cast the 3D axis we are currently rotating along (which is already casted to the surface of the
+// currently touched face AND converted into a 4D vector - fourth 0) to a 2D in-screen-surface axis
 
-    private void computeCurrentAxis(Static3D axis)
+    private void computeCurrentAxis(Static4D axis)
       {
-      Static4D axis4D = new Static4D(axis.get0(), axis.get1(), axis.get2(), 0);
-      Static4D result = rotateVectorByQuat(axis4D, mQuat);
+      Static4D result = rotateVectorByQuat(axis, mQuat);
 
       mAxisX =result.get0();
       mAxisY =result.get1();
@@ -468,7 +468,7 @@ public class RubikSurfaceView extends GLSurfaceView
       float offset = res.get1();
       mCurrentRow  = object.computeRowFromOffset(offset);
 
-      computeCurrentAxis( object.getRotationAxis()[mCurrentAxis] );
+      computeCurrentAxis( mMovement.getCastedRotAxis(mCurrentAxis) );
       mRotationFactor = object.returnRotationFactor(offset);
 
       object.beginNewRotation( mCurrentAxis, mCurrentRow );
diff --git a/src/main/java/org/distorted/objects/RubikMovement.java b/src/main/java/org/distorted/objects/RubikMovement.java
index df730dab..53d504a2 100644
--- a/src/main/java/org/distorted/objects/RubikMovement.java
+++ b/src/main/java/org/distorted/objects/RubikMovement.java
@@ -30,7 +30,8 @@ public abstract class RubikMovement
   private int mLastTouchedFace, mNumFaceAxis;
   private float[] mPoint, mCamera, mTouch;
   private float[] mPoint2D, mMove2D;
-  private float[][][] mCastAxis;
+  private float[][][] mCastedRotAxis;
+  private Static4D[][] mCastedRotAxis4D;
   private int[] mEnabledRotAxis;
   private float mDistanceCenterFace3D, mDistanceCenterFace2D;
   private Static3D[] mFaceAxis;
@@ -59,9 +60,12 @@ public abstract class RubikMovement
     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
+    // mCastedRotAxis[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][rotAxis.length][2];
+    mCastedRotAxis   = new float[mNumFaceAxis][rotAxis.length][2];
+    mCastedRotAxis4D = new Static4D[mNumFaceAxis][rotAxis.length];
+
+    float fx,fy,fz,f;
 
     for( int casted=0; casted<rotAxis.length; casted++)
       {
@@ -72,8 +76,14 @@ public abstract class RubikMovement
 
       for( int face=0; face<mNumFaceAxis; face++)
         {
-        convertTo2Dcoords( mPoint, mFaceAxis[face], mCastAxis[face][casted]);
-        normalize2D(mCastAxis[face][casted]);
+        convertTo2Dcoords( mPoint, mFaceAxis[face], mCastedRotAxis[face][casted]);
+        normalize2D(mCastedRotAxis[face][casted]);
+
+        fx = faceAxis[face].get0();
+        fy = faceAxis[face].get1();
+        fz = faceAxis[face].get2();
+        f  = mPoint[0]*fx + mPoint[1]*fy + mPoint[2]*fz;
+        mCastedRotAxis4D[face][casted] = new Static4D( mPoint[0]-f*fx, mPoint[1]-f*fy, mPoint[2]-f*fz, 0);
         }
       }
     }
@@ -114,7 +124,7 @@ public abstract class RubikMovement
     for(int axis=1; axis<=numAxis; axis++)
       {
       index = enabled[axis];
-      cosAngle = m0*mCastAxis[faceAxis][index][0] + m1*mCastAxis[faceAxis][index][1];
+      cosAngle = m0*mCastedRotAxis[faceAxis][index][0] + m1*mCastedRotAxis[faceAxis][index][1];
       if( cosAngle<0 ) cosAngle = -cosAngle;
 
       if( cosAngle<minCosAngle )
@@ -271,11 +281,18 @@ public abstract class RubikMovement
 
     computeEnabledAxis(mLastTouchedFace, mPoint2D, mEnabledRotAxis);
     int rotIndex = computeRotationIndex(mLastTouchedFace, mMove2D, mEnabledRotAxis);
-    float offset = computeOffset(mPoint2D, mCastAxis[mLastTouchedFace][rotIndex]);
+    float offset = computeOffset(mPoint2D, mCastedRotAxis[mLastTouchedFace][rotIndex]);
 
     return new Static2D(rotIndex,offset);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Static4D getCastedRotAxis(int rotIndex)
+    {
+    return mCastedRotAxis4D[mLastTouchedFace][rotIndex];
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getTouchedFace()
