commit 7695a3be8257fa9b3847bd20fa8d4c0765319be1
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sat Jun 20 00:52:12 2020 +0100

    Two-fingered object rotation seems to be finished.

diff --git a/src/main/java/org/distorted/main/RubikSurfaceView.java b/src/main/java/org/distorted/main/RubikSurfaceView.java
index 931f4a2c..ef147934 100644
--- a/src/main/java/org/distorted/main/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/main/RubikSurfaceView.java
@@ -71,6 +71,7 @@ public class RubikSurfaceView extends GLSurfaceView
     private boolean mDragging, mBeginningRotation, mContinuingRotation;
     private int mScreenWidth, mScreenHeight, mScreenMin;
 
+    private float mRotAngle;
     private int mPtrID1, mPtrID2;
     private int mNumFingersDown;
     private float mX, mY;
@@ -362,9 +363,34 @@ public class RubikSurfaceView extends GLSurfaceView
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private void drag(float x, float y)
+    private void drag(MotionEvent event, float x, float y)
       {
-      mTemp.set(quatMultiply(quatFromDrag(mX-x,y-mY), mQuat));
+      if( mPtrID1!=INVALID_POINTER_ID && mPtrID2!=INVALID_POINTER_ID)
+        {
+        int pointer = event.findPointerIndex(mPtrID2);
+
+        float pX = event.getX(pointer);
+        float pY = event.getY(pointer);
+
+        float x2 = (pX - mScreenWidth*0.5f)/mScreenMin;
+        float y2 = (mScreenHeight*0.5f -pY)/mScreenMin;
+
+        float angleNow = getAngle(x,y,x2,y2);
+        float angleDiff = angleNow-mRotAngle;
+        float sinA =-(float)Math.sin(angleDiff);
+        float cosA = (float)Math.cos(angleDiff);
+
+        Static4D dragQuat = quatMultiply(new Static4D(0,0,sinA,cosA), mQuat);
+        mTemp.set(dragQuat);
+
+        mRotAngle = angleNow;
+        }
+      else
+        {
+        Static4D dragQuat = quatMultiply(quatFromDrag(mX-x,y-mY), mQuat);
+        mTemp.set(dragQuat);
+        }
+
       mPreRender.setQuatOnNextRender();
       mX = x;
       mY = y;
@@ -455,12 +481,21 @@ public class RubikSurfaceView extends GLSurfaceView
       mContinuingRotation= true;
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private float getAngle(float x1, float y1, float x2, float y2)
+      {
+      return (float) Math.atan2(y1-y2, x1-x2);
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     private void actionMove(MotionEvent event)
       {
       int pointer = event.findPointerIndex(mPtrID1 != INVALID_POINTER_ID ? mPtrID1:mPtrID2);
 
+      if( pointer<0 ) return;
+
       float pX = event.getX(pointer);
       float pY = event.getY(pointer);
 
@@ -480,7 +515,7 @@ public class RubikSurfaceView extends GLSurfaceView
         }
       else if( mDragging )
         {
-        drag(x,y);
+        drag(event,x,y);
         }
       else
         {
@@ -535,8 +570,18 @@ public class RubikSurfaceView extends GLSurfaceView
       if( mPtrID1==INVALID_POINTER_ID )
         {
         mPtrID1 = event.getPointerId(index);
-        float x = event.getX(index);
-        float y = event.getY(index);
+        float x = event.getX();
+        float y = event.getY();
+
+        if( mPtrID2 != INVALID_POINTER_ID )
+          {
+          int pointer = event.findPointerIndex(mPtrID2);
+
+          float x2 = event.getX(pointer);
+          float y2 = event.getY(pointer);
+
+          mRotAngle = getAngle(x,-y,x2,-y2);
+          }
 
         mX = (x - mScreenWidth*0.5f)/mScreenMin;
         mY = (mScreenHeight*0.5f -y)/mScreenMin;
@@ -545,11 +590,21 @@ public class RubikSurfaceView extends GLSurfaceView
         {
         mPtrID2 = event.getPointerId(index);
 
-        if( mBeginningRotation || mContinuingRotation )
+        float x = event.getX();
+        float y = event.getY();
+
+        if( mPtrID2 != INVALID_POINTER_ID )
           {
-          float x = event.getX();
-          float y = event.getY();
+          int pointer = event.findPointerIndex(mPtrID2);
+
+          float x2 = event.getX(pointer);
+          float y2 = event.getY(pointer);
 
+          mRotAngle = getAngle(x,-y,x2,-y2);
+          }
+
+        if( mBeginningRotation || mContinuingRotation )
+          {
           mX = (x - mScreenWidth*0.5f)/mScreenMin;
           mY = (mScreenHeight*0.5f -y)/mScreenMin;
           }
@@ -575,17 +630,21 @@ public class RubikSurfaceView extends GLSurfaceView
 
       int index = event.getActionIndex();
 
-      if( index==0 )
+      if( index==event.findPointerIndex(mPtrID1) )
         {
         mPtrID1 = INVALID_POINTER_ID;
         int pointer = event.findPointerIndex(mPtrID2);
-        float x1 = event.getX(pointer);
-        float y1 = event.getY(pointer);
 
-        mX = (x1 - mScreenWidth*0.5f)/mScreenMin;
-        mY = (mScreenHeight*0.5f -y1)/mScreenMin;
+        if( pointer>=0 )
+          {
+          float x1 = event.getX(pointer);
+          float y1 = event.getY(pointer);
+
+          mX = (x1 - mScreenWidth*0.5f)/mScreenMin;
+          mY = (mScreenHeight*0.5f -y1)/mScreenMin;
+          }
         }
-      else
+      else if( index==event.findPointerIndex(mPtrID2) )
         {
         mPtrID2 = INVALID_POINTER_ID;
         }
