commit bef472878328973eef845ca2d690233e00e3e3fa
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed Mar 11 23:13:26 2020 +0000

    Progress with object Movement.

diff --git a/src/main/java/org/distorted/magic/RubikSurfaceView.java b/src/main/java/org/distorted/magic/RubikSurfaceView.java
index 2c668c93..0edfa755 100644
--- a/src/main/java/org/distorted/magic/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/magic/RubikSurfaceView.java
@@ -220,6 +220,28 @@ public class RubikSurfaceView extends GLSurfaceView
         }
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void setUpDragOrRotate(float x, float y)
+      {
+      Static4D touchPoint1 = new Static4D(x, y, 0, 0);
+      Static4D rotatedTouchPoint1= rotateVectorByInvertedQuat(touchPoint1, mQuatAccumulated);
+      Static4D rotatedCamera= rotateVectorByInvertedQuat(CAMERA_POINT, mQuatAccumulated);
+
+      if( mMovement!=null && mMovement.faceTouched(rotatedTouchPoint1,rotatedCamera) )
+        {
+        mDragging           = false;
+        mBeginningRotation  = mRenderer.canRotate();
+        mContinuingRotation = false;
+        }
+      else
+        {
+        mDragging           = mRenderer.canDrag();
+        mBeginningRotation  = false;
+        mContinuingRotation = false;
+        }
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     @Override
@@ -233,23 +255,7 @@ public class RubikSurfaceView extends GLSurfaceView
          {
          case MotionEvent.ACTION_DOWN: mX = x;
                                        mY = y;
-
-                                       Static4D touchPoint1 = new Static4D(x, y, 0, 0);
-                                       Static4D rotatedTouchPoint1= rotateVectorByInvertedQuat(touchPoint1, mQuatAccumulated);
-                                       Static4D rotatedCamera= rotateVectorByInvertedQuat(CAMERA_POINT, mQuatAccumulated);
-
-                                       if( mMovement!=null && mMovement.faceTouched(rotatedTouchPoint1,rotatedCamera) )
-                                         {
-                                         mDragging           = false;
-                                         mBeginningRotation  = mRenderer.canRotate();
-                                         mContinuingRotation = false;
-                                         }
-                                       else
-                                         {
-                                         mDragging           = mRenderer.canDrag();
-                                         mBeginningRotation  = false;
-                                         mContinuingRotation = false;
-                                         }
+                                       setUpDragOrRotate(x,y);
                                        break;
          case MotionEvent.ACTION_MOVE: if( mBeginningRotation )
                                          {
@@ -281,9 +287,8 @@ public class RubikSurfaceView extends GLSurfaceView
                                          float angle = mMovement.continueRotation(rotatedTouchPoint3);
                                          mRenderer.getObject().continueRotation(SWIPING_SENSITIVITY*angle);
                                          }
-                                       else if( mDragging || mRenderer.canDrag() )
+                                       else if( mDragging )
                                          {
-                                         mDragging = true;
                                          mTempCurrent.set(quatFromDrag(mX-x,y-mY));
                                          mRenderer.setQuatCurrentOnNextRender();
 
@@ -297,6 +302,10 @@ public class RubikSurfaceView extends GLSurfaceView
                                            mRenderer.setQuatAccumulatedOnNextRender();
                                            }
                                          }
+                                       else
+                                         {
+                                         setUpDragOrRotate(x,y);
+                                         }
                                        break;
          case MotionEvent.ACTION_UP  : if( mDragging )
                                          {
diff --git a/src/main/java/org/distorted/object/RubikCubeMovement.java b/src/main/java/org/distorted/object/RubikCubeMovement.java
index 73ee1166..7ba9d599 100644
--- a/src/main/java/org/distorted/object/RubikCubeMovement.java
+++ b/src/main/java/org/distorted/object/RubikCubeMovement.java
@@ -51,7 +51,7 @@ class RubikCubeMovement extends RubikObjectMovement
 
   boolean isInsideFace(float[] p)
     {
-    return ( p[0]<=0.5f && p[0]>=-0.5f && p[1]<=0.5f && p[1]>=-0.5f && p[2]<=0.5f && p[2]>=-0.5f );
+    return ( p[0]<=0.5f && p[0]>=-0.5f && p[1]<=0.5f && p[1]>=-0.5f );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/object/RubikObjectMovement.java b/src/main/java/org/distorted/object/RubikObjectMovement.java
index 07fd0a7d..a6d26b7e 100644
--- a/src/main/java/org/distorted/object/RubikObjectMovement.java
+++ b/src/main/java/org/distorted/object/RubikObjectMovement.java
@@ -30,7 +30,7 @@ public abstract class RubikObjectMovement
   float[] mTouch;
   int mRotationVect, mLastTouchedAxis;
 
-  private float[] mPoint, mCamera, mDiff;
+  private float[] mPoint, mCamera, mDiff, m2Dpoint;
   private int mLastTouchedLR;
   private int mNumAxis, mNumFacesPerAxis;
   private int[] mPossible;
@@ -53,6 +53,8 @@ public abstract class RubikObjectMovement
     mDiff  = new float[3];
     mTouch = new float[3];
 
+    m2Dpoint = new float[2];
+
     mAxis = axis;
     mNumAxis = mAxis.length;
     mNumFacesPerAxis = numFacesPerAxis;
@@ -101,6 +103,60 @@ public abstract class RubikObjectMovement
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Convert the 3D point3D into a 2D point on the same face surface, but in a different
+// coordinate system: a in-plane 2D coord where the origin is in the point where the axis intersects
+// the surface, and whose Y axis points 'north' i.e. is in the plane given by the 3D origin, the
+// original 3D Y axis and our 2D in-plane origin.
+// If those 3 points constitute a degenerate triangle which does not define a plane - which can only
+// happen if axis is vertical (or in theory when 2D origin and 3D origin meet, but that would have to
+// mean that the distance between the center of the Object and its faces is 0) - then we arbitrarily
+// decide that 2D Y = (0,0,-1) in the North Pole and (0,0,1) in the South Pole)
+
+  private void convertTo2Dcoords(float[] point3D, Static3D axis, int lr, float[] output)
+    {
+    float y0,y1,y2, x0,x1,x2;  // base X and Y vectors of the 2D coord system
+    float a0 = axis.get0();
+    float a1 = axis.get1();
+    float a2 = axis.get2();
+
+    if( lr==0 )
+      {
+      a0=-a0; a1=-a1; a2=-a2;
+      }
+
+    if( a0==0.0f && a2==0.0f )
+      {
+      y0=0; y1=0; y2=-a1;
+      }
+    else if( a1==0.0f )
+      {
+      y0=0; y1=1; y2=0;
+      }
+    else
+      {
+      float norm = (float)(-a1/Math.sqrt(1-a1*a1));
+      y0 = norm*a0; y1= norm*(a1-1/a1); y2=a2;
+      }
+
+    x0 = y1*a2 - y2*a1;  //
+    x1 = y2*a0 - y0*a2;  // (2D coord baseY) x (axis) = 2D coord baseX
+    x2 = y0*a1 - y1*a0;  //
+
+    float originAlpha = point3D[0]*a0 + point3D[1]*a1 + point3D[2]*a2;
+
+    float origin0 = originAlpha*a0; // coords of the point where axis
+    float origin1 = originAlpha*a1; // intersects surface plane i.e.
+    float origin2 = originAlpha*a2; // the origin of our 2D coord system
+
+    float v0 = point3D[0] - origin0;
+    float v1 = point3D[1] - origin1;
+    float v2 = point3D[2] - origin2;
+
+    output[0] = v0*x0 + v1*x1 + v2*x2;
+    output[1] = v0*y0 + v1*y1 + v2*y2;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -122,9 +178,12 @@ public abstract class RubikObjectMovement
         if( faceIsVisible(mAxis[mLastTouchedAxis], mLastTouchedLR) )
           {
           castTouchPointOntoFace(mAxis[mLastTouchedAxis], mLastTouchedLR, mTouch);
+          convertTo2Dcoords(mTouch, mAxis[mLastTouchedAxis], mLastTouchedLR, m2Dpoint);
 
-          if( isInsideFace(mTouch) )
+          if( isInsideFace(m2Dpoint) )
             {
+ // android.util.Log.e("move", "touched "+mLastTouchedAxis+" touch point: ("+m2Dpoint[0]+","+m2Dpoint[1]+")");
+
             fillPossibleRotations(mLastTouchedAxis, mPossible);
             return true;
             }
@@ -150,11 +209,6 @@ public abstract class RubikObjectMovement
     mDiff[2] -= mTouch[2];
 
     float offset = fillUpRotationVectAndOffset(mDiff, mPossible);
-
-    mTouch[0] = mPoint[0];
-    mTouch[1] = mPoint[1];
-    mTouch[2] = mPoint[2];
-
     return new Static2D(mRotationVect,offset);
     }
 
@@ -162,9 +216,9 @@ public abstract class RubikObjectMovement
 
   public float continueRotation(Static4D rotatedTouchPoint)
     {
-    mDiff[0] = rotatedTouchPoint.get0()/RubikObject.OBJECT_SCREEN_RATIO - mTouch[0];
-    mDiff[1] = rotatedTouchPoint.get1()/RubikObject.OBJECT_SCREEN_RATIO - mTouch[1];
-    mDiff[2] = rotatedTouchPoint.get2()/RubikObject.OBJECT_SCREEN_RATIO - mTouch[2];
+    mDiff[0] = rotatedTouchPoint.get0()/RubikObject.OBJECT_SCREEN_RATIO - mPoint[0];
+    mDiff[1] = rotatedTouchPoint.get1()/RubikObject.OBJECT_SCREEN_RATIO - mPoint[1];
+    mDiff[2] = rotatedTouchPoint.get2()/RubikObject.OBJECT_SCREEN_RATIO - mPoint[2];
 
     return (mLastTouchedLR-0.5f)*returnAngle(mDiff, mPossible);
     }
diff --git a/src/main/java/org/distorted/object/RubikPyraminxMovement.java b/src/main/java/org/distorted/object/RubikPyraminxMovement.java
index b16eaa52..cf263846 100644
--- a/src/main/java/org/distorted/object/RubikPyraminxMovement.java
+++ b/src/main/java/org/distorted/object/RubikPyraminxMovement.java
@@ -55,7 +55,11 @@ class RubikPyraminxMovement extends RubikObjectMovement
 
   boolean isInsideFace(float[] p)
     {
-    return false;//( p[0]<=0.5f && p[0]>=-0.5f && p[1]<=0.5f && p[1]>=-0.5f && p[2]<=0.5f && p[2]>=-0.5f );
+    boolean a1 = p[1] >= -SQ3/6;
+    boolean a2 = p[1]*SQ3 <= 1 + 2*p[0];
+    boolean a3 = p[1]*SQ3 <= 1 - 2*p[0];
+
+    return a1 && a2 && a3;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
