commit a6aa9a47e7226474b27ec5799785c52aedae1d31
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Tue May 30 23:18:14 2023 +0200

    Improve the 'rot axis parallel to face axis' touch control mode:
    support case when the rot axis is parallel and agrees in direction with the face axis, and the one when they disagreee in direction.

diff --git a/src/main/java/org/distorted/objectlib/main/ObjectControl.java b/src/main/java/org/distorted/objectlib/main/ObjectControl.java
index e11519bd..0e7829cc 100644
--- a/src/main/java/org/distorted/objectlib/main/ObjectControl.java
+++ b/src/main/java/org/distorted/objectlib/main/ObjectControl.java
@@ -36,6 +36,10 @@ public class ObjectControl
     public static final int MODE_REPLACE = 2;
     public static final int MODE_NOTHING = 3;
 
+    public static final int ROT_AXIS_NOT_NORMAL = 0;
+    public static final int ROT_AXIS_NORMAL_OPP = 1;
+    public static final int ROT_AXIS_NORMAL_AGR = 2;
+
     // Moving the finger from the middle of the vertical screen to the right edge will rotate a
     // given face by SWIPING_SENSITIVITY/2 degrees.
     public final static int SWIPING_SENSITIVITY  = 240;
@@ -73,7 +77,7 @@ public class ObjectControl
     private int mMeshState, mIconMode;
     private boolean mRotateOnCreation;
     private final Static4D mQuat,mTemp;
-    private boolean mRotAxisIsNormal;
+    private int mRotAxisType;
     private final float[] mNormalTouchPoint;
     private float mNormalRotAngle;
 
@@ -250,7 +254,7 @@ public class ObjectControl
 
     private void continueRotation(float x, float y)
       {
-      if( !mRotAxisIsNormal )
+      if( mRotAxisType == ROT_AXIS_NOT_NORMAL )
         {
         float dx = x-mStartRotX;
         float dy = y-mStartRotY;
@@ -272,6 +276,7 @@ public class ObjectControl
         {
         float rotAngle = computeNormalRotAngle(mNormalTouchPoint[0]-x,mNormalTouchPoint[1]-y);
         mCurrentAngle = mNormalRotAngle - rotAngle;
+        if( mRotAxisType==ROT_AXIS_NORMAL_AGR ) mCurrentAngle = -mCurrentAngle;
         mPreRender.getObject().continueRotation(mCurrentAngle);
         addSpeedProbe(mCurrentAngle);
         }
@@ -283,8 +288,6 @@ public class ObjectControl
       {
       if( mAxis[0]==0 && mAxis[1]==0 )
         {
-        mRotAxisIsNormal = true;
-
         // 0. get face center in object space
         // 1. multiply it by mQuat
         // 2. multiply if by mObjectRatio. Let the result be (x,y,z)
@@ -306,10 +309,13 @@ public class ObjectControl
         float A = D / (D-z);
         mNormalTouchPoint[0] = A*x;
         mNormalTouchPoint[1] = A*y;
+
+        boolean agree = mTouchControl.axisAndFaceAgree(mCurrentAxis);
+        mRotAxisType = (agree ? ROT_AXIS_NORMAL_AGR : ROT_AXIS_NORMAL_OPP);
         }
       else
         {
-        mRotAxisIsNormal = false;
+        mRotAxisType = ROT_AXIS_NOT_NORMAL;
         }
       }
 
@@ -341,7 +347,7 @@ public class ObjectControl
       mTouchControl.getCastedRotAxis(mAxis,mQuat,mCurrentAxis);
       correctRotationAxis();
       mRotationFactor = mTouchControl.returnRotationFactor(numLayers,mCurrentRow);
-      if( mRotAxisIsNormal ) mNormalRotAngle = computeNormalRotAngle(mNormalTouchPoint[0]-x,mNormalTouchPoint[1]-y);
+      if( mRotAxisType != ROT_AXIS_NOT_NORMAL ) mNormalRotAngle = computeNormalRotAngle(mNormalTouchPoint[0]-x,mNormalTouchPoint[1]-y);
 
       if( object.beginNewRotation( mCurrentAxis, mCurrentRow ) )
         {
diff --git a/src/main/java/org/distorted/objectlib/main/ObjectType.java b/src/main/java/org/distorted/objectlib/main/ObjectType.java
index 955aace9..c90e4fda 100644
--- a/src/main/java/org/distorted/objectlib/main/ObjectType.java
+++ b/src/main/java/org/distorted/objectlib/main/ObjectType.java
@@ -111,7 +111,7 @@ public enum ObjectType
 
   COIH_3 ( TwistyCoinHexahedron.class , 25, R.drawable.coin_3, true,   50, new InitData(new int[] {3,3,3,3,3,3,3})),
 
-  COIN_3 ( TwistyCoinTetrahedron.class, 15, R.drawable.coin_3, false,   40, new InitData(new int[] {3,3,3,3})),
+  COIN_3 ( TwistyCoinTetrahedron.class, 15, R.drawable.coin_3, true,   40, new InitData(new int[] {3,3,3,3})),
   TINS_5 ( TwistyTins.class           , 28, R.drawable.coin_3, false,    60, new InitData(new int[] {5,5,5,5})),
   ;
 
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControl.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControl.java
index 3141c637..3dc6e9f4 100644
--- a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControl.java
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControl.java
@@ -135,6 +135,7 @@ public abstract class TouchControl
   public abstract boolean objectTouched(Static4D rotatedTouchPoint, Static4D rotatedCamera);
   public abstract void newRotation(int[] output, Static4D rotatedTouchPoint, Static4D quat);
   public abstract void getCastedRotAxis(float[] output, Static4D quat, int rotIndex);
+  public abstract boolean axisAndFaceAgree(int rotIndex);
   public abstract int getTouchedCubitFace();
   public abstract int getTouchedCubit();
   public abstract float[] getTouchedPuzzleCenter();
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlBall.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlBall.java
index 1d75df17..2fa251f1 100644
--- a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlBall.java
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlBall.java
@@ -350,4 +350,11 @@ public class TouchControlBall extends TouchControl
       output[1] = 0;
       }
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean axisAndFaceAgree(int axisIndex)
+    {
+    return false;
+    }
 }
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java
index 25519b5d..b2ed308c 100644
--- a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java
@@ -588,6 +588,13 @@ public class TouchControlShapeChanging extends TouchControl
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean axisAndFaceAgree(int axisIndex)
+    {
+    return false;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public float[] getTouchedPuzzleCenter()
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeConstant.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeConstant.java
index bfa0fc7f..efe33033 100644
--- a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeConstant.java
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeConstant.java
@@ -408,6 +408,28 @@ public abstract class TouchControlShapeConstant extends TouchControl
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean axisAndFaceAgree(int axisIndex)
+    {
+    Static3D rotAxis = mRotAxis[axisIndex];
+    Static3D faceAxis= mFaceAxis[mLastTouchedFace];
+
+    float rx = rotAxis.get0();
+    float ry = rotAxis.get1();
+    float rz = rotAxis.get2();
+
+    float fx = faceAxis.get0();
+    float fy = faceAxis.get1();
+    float fz = faceAxis.get2();
+
+    float dx = rx-fx;
+    float dy = ry-fy;
+    float dz = rz-fz;
+
+    return (dx*dx + dy*dy + dz*dz) == 0;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public float[] getTouchedPuzzleCenter()
