commit dc8979baa4145f60847800174a058d71712d8b94
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Apr 7 00:01:16 2019 +0100

    RubikApp: simplifications.

diff --git a/src/main/java/org/distorted/examples/rubik/RubikCube.java b/src/main/java/org/distorted/examples/rubik/RubikCube.java
index 30ab02b..f6e5e4b 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikCube.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikCube.java
@@ -66,7 +66,7 @@ class RubikCube
       mSize = size;
 
       mRotationAngleStatic = new Static1D(0);
-      mRotAxis= RubikSurfaceView.VECTN;
+      mRotAxis= RubikSurfaceView.VECTX;
       mTexture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
 
       mCubes          = new MeshCubes[mSize][mSize][mSize];
diff --git a/src/main/java/org/distorted/examples/rubik/RubikRenderer.java b/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
index ef8d5b0..312cf44 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
@@ -109,7 +109,7 @@ class RubikRenderer implements GLSurfaceView.Renderer
       float h = mCube.getHeight();
       float d = mCube.getDepth();
 
-      mScaleFactor = CUBE_SCREEN_RATIO*(width>height ? height/h:width/w)/ NUM_CUBES;
+      mScaleFactor = CUBE_SCREEN_RATIO*(width>height ? height:width)/mCube.getSizeInModelSpace();
 
       mMove.set( (width-mScaleFactor*w)/2 , (height-mScaleFactor*h)/2 , -mScaleFactor*d/2 );
       mScale.set(mScaleFactor,mScaleFactor,mScaleFactor);
@@ -147,7 +147,7 @@ class RubikRenderer implements GLSurfaceView.Renderer
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    float returnCubeSize()
+    float returnCubeSizeInScreenSpace()
       {
       return mScaleFactor*mCube.getSizeInModelSpace();
       }
diff --git a/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java b/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
index 4b2553e..706e0d9 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
@@ -39,10 +39,11 @@ class RubikSurfaceView extends GLSurfaceView
     private final static int TOP    = 4;  //
     private final static int BOTTOM = 5;  //
 
-    static final int VECTX = 0;
-    static final int VECTY = 1;
-    static final int VECTZ = 2;
-    static final int VECTN = 3;
+    static final int VECTX = 0;  //
+    static final int VECTY = 1;  // dont change this
+    static final int VECTZ = 2;  //
+
+    private static final int[] VECT = {VECTX,VECTY,VECTZ};
 
     private boolean mDragging, mBeginRot;
     private int mX, mY;
@@ -51,8 +52,7 @@ class RubikSurfaceView extends GLSurfaceView
     private RubikRenderer mRenderer;
     private RubikCube mCube;
 
-    private float mPoiX, mPoiY, mPoiZ, mCamX, mCamY, mCamZ;
-    private float mStartX, mStartY, mStartZ;
+    private float[] mPoi, mCam, mTouchedPointCastOntoFace, mDiff; // all in screen space
     private int mLastTouchedFace;
     private int mScreenWidth, mScreenHeight, mScreenMin;
     private float mCameraDistance;
@@ -65,7 +65,12 @@ class RubikSurfaceView extends GLSurfaceView
 
       mDragging = false;
       mBeginRot = false;
-      mRotationVect = VECTN;
+      mRotationVect = VECT[0];
+
+      mPoi   = new float[3];
+      mCam   = new float[3];
+      mDiff  = new float[3];
+      mTouchedPointCastOntoFace = new float[3];
 
       mScreenWidth = mScreenHeight = mScreenMin = 0;
 
@@ -160,40 +165,54 @@ class RubikSurfaceView extends GLSurfaceView
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// mTouchedPointCastOntoFace[x] is the x distance between the x-center of the face and the point
+// we just touched cast onto the face. The face is touched iff -cH <= mTouchedPointCastOntoFace[0,1,2] <= +cH
 
-    private void addNewRotation(int x, int y)
+    private int faceTouched(int xTouch, int yTouch)
       {
-      fillTouchPoint(x,y);
-
-      float cubeHalfSize= mRenderer.returnCubeSize()*0.5f;
-      float A=retA(mLastTouchedFace,cubeHalfSize);
+      float cubeHalfSize= mRenderer.returnCubeSizeInScreenSpace()*0.5f;
 
-      float diffX = (mPoiX-mCamX)*A + mCamX - mStartX;
-      float diffY = (mPoiY-mCamY)*A + mCamY - mStartY;
-      float diffZ = (mPoiZ-mCamZ)*A + mCamZ - mStartZ;
+      convertTouchPointToScreenSpace(xTouch,yTouch);
+      convertCameraPointToScreenSpace();
 
-      switch(mLastTouchedFace)
+      for(int face=FRONT; face<=BOTTOM; face++)
         {
-        case FRONT :
-        case BACK  : mRotationVect = (isVertical(diffX, diffY) ? VECTX:VECTY); break;
-        case LEFT  :
-        case RIGHT : mRotationVect = (isVertical(diffZ, diffY) ? VECTZ:VECTY); break;
-        case TOP   :
-        case BOTTOM: mRotationVect = (isVertical(diffX, diffZ) ? VECTX:VECTZ); break;
-        }
+        if( faceIsVisible(face,cubeHalfSize) )
+          {
+          castTouchPointOntoFace(face,cubeHalfSize, mTouchedPointCastOntoFace);
 
-      float offset=0;
+          float qX= (mTouchedPointCastOntoFace[0]+cubeHalfSize) / (2*cubeHalfSize);
+          float qY= (mTouchedPointCastOntoFace[1]+cubeHalfSize) / (2*cubeHalfSize);
+          float qZ= (mTouchedPointCastOntoFace[2]+cubeHalfSize) / (2*cubeHalfSize);
 
-      switch(mRotationVect)
-        {
-        case VECTX: offset = (mStartX+cubeHalfSize)/(2*cubeHalfSize); break;
-        case VECTY: offset = (mStartY+cubeHalfSize)/(2*cubeHalfSize); break;
-        case VECTZ: offset = (mStartZ+cubeHalfSize)/(2*cubeHalfSize); break;
+          if( qX<=1 && qX>=0 && qY<=1 && qY>=0 && qZ<=1 && qZ>=0 ) return face;
+          }
         }
 
-      mStartX = diffX + mStartX;
-      mStartY = diffY + mStartY;
-      mStartZ = diffZ + mStartZ;
+      return NONE;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void addNewRotation(int x, int y)
+      {
+      float cubeHalfSize= mRenderer.returnCubeSizeInScreenSpace()*0.5f;
+
+      convertTouchPointToScreenSpace(x,y);
+      castTouchPointOntoFace(mLastTouchedFace,cubeHalfSize,mDiff);
+
+      mDiff[0] -= mTouchedPointCastOntoFace[0];
+      mDiff[1] -= mTouchedPointCastOntoFace[1];
+      mDiff[2] -= mTouchedPointCastOntoFace[2];
+
+      int xAxis = retFaceXaxis(mLastTouchedFace);
+      int yAxis = retFaceYaxis(mLastTouchedFace);
+      mRotationVect = (isVertical( mDiff[xAxis], mDiff[yAxis]) ? VECT[xAxis]:VECT[yAxis]);
+      float offset= (mTouchedPointCastOntoFace[mRotationVect]+cubeHalfSize)/(2*cubeHalfSize);
+
+      mTouchedPointCastOntoFace[0] = mDiff[0] + mTouchedPointCastOntoFace[0];
+      mTouchedPointCastOntoFace[1] = mDiff[1] + mTouchedPointCastOntoFace[1];
+      mTouchedPointCastOntoFace[2] = mDiff[2] + mTouchedPointCastOntoFace[2];
 
       mCube.addNewRotation(mRotationVect,offset);
       }
@@ -209,35 +228,28 @@ class RubikSurfaceView extends GLSurfaceView
 
     private void continueRotation(int x, int y)
       {
-      fillTouchPoint(x,y);
+      float cubeHalfSize= mRenderer.returnCubeSizeInScreenSpace()*0.5f;
 
-      float cubeHalfSize= mRenderer.returnCubeSize()*0.5f;
-      float A=retA(mLastTouchedFace,cubeHalfSize);
+      convertTouchPointToScreenSpace(x,y);
+      castTouchPointOntoFace(mLastTouchedFace,cubeHalfSize,mDiff);
 
-      float diffX = (mPoiX-mCamX)*A + mCamX - mStartX;
-      float diffY = (mPoiY-mCamY)*A + mCamY - mStartY;
-      float diffZ = (mPoiZ-mCamZ)*A + mCamZ - mStartZ;
+      mDiff[0] -= mTouchedPointCastOntoFace[0];
+      mDiff[1] -= mTouchedPointCastOntoFace[1];
+      mDiff[2] -= mTouchedPointCastOntoFace[2];
 
-      float angle=0.0f;
+      int xAxis= retFaceXaxis(mLastTouchedFace);
+      int yAxis= retFaceYaxis(mLastTouchedFace);
+      int sign = retFaceRotationSign(mLastTouchedFace);
 
-      switch(mLastTouchedFace)
-        {
-        case FRONT : angle = (mRotationVect==VECTX ? -diffY : diffX); break;
-        case BACK  : angle = (mRotationVect==VECTX ?  diffY :-diffX); break;
-        case LEFT  : angle = (mRotationVect==VECTY ?  diffZ :-diffY); break;
-        case RIGHT : angle = (mRotationVect==VECTY ? -diffZ : diffY); break;
-        case TOP   : angle = (mRotationVect==VECTZ ? -diffX : diffZ); break;
-        case BOTTOM: angle = (mRotationVect==VECTZ ?  diffX :-diffZ); break;
-        }
+      float angle = (mRotationVect==xAxis ? mDiff[yAxis] : -mDiff[xAxis]);
 
-      mCube.continueRotation(200.0f*angle/mScreenMin);
+      mCube.continueRotation(200.0f*sign*angle/mScreenMin);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     private void finishRotation()
       {
-      mRotationVect = VECTN;
       mRenderer.finishRotation();
       }
 
@@ -322,113 +334,121 @@ class RubikSurfaceView extends GLSurfaceView
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private boolean faceIsVisible(int face)
+    private boolean faceIsVisible(int face, float cubeHalfSize)
       {
-      float cubeHalfSize= mRenderer.returnCubeSize()*0.5f;
+      int sign = retFaceSign(face);
+      int zAxis= retFaceZaxis(face);
 
-      Static4D rotated = rotateVectorByInvertedQuat(new Static4D(0,0,mCameraDistance,0), mQuatAccumulated);
+      return sign*mCam[zAxis] > cubeHalfSize;
+      }
 
-      switch(face)
-        {
-        case FRONT : return rotated.get3() >  cubeHalfSize;
-        case BACK  : return rotated.get3() < -cubeHalfSize;
-        case LEFT  : return rotated.get1() < -cubeHalfSize;
-        case RIGHT : return rotated.get1() >  cubeHalfSize;
-        case TOP   : return rotated.get2() >  cubeHalfSize;
-        case BOTTOM: return rotated.get2() < -cubeHalfSize;
-        }
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-      return false;
+    private void convertTouchPointToScreenSpace(int x, int y)
+      {
+      float halfScrWidth  = mScreenWidth *0.5f;
+      float halfScrHeight = mScreenHeight*0.5f;
+      Static4D touchPoint = new Static4D(x-halfScrWidth, halfScrHeight-y, 0, 0);
+      Static4D rotatedTouchPoint= rotateVectorByInvertedQuat(touchPoint, mQuatAccumulated);
+
+      mPoi[0] = rotatedTouchPoint.get1();
+      mPoi[1] = rotatedTouchPoint.get2();
+      mPoi[2] = rotatedTouchPoint.get3();
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private int faceTouched(int xTouch, int yTouch)
+    private void convertCameraPointToScreenSpace()
       {
-      float cubeHalfSize= mRenderer.returnCubeSize()*0.5f;
-
-      fillTouchPoint(xTouch,yTouch);
-      fillCamera();
+      Static4D cameraPoint = new Static4D(0, 0, mCameraDistance, 0);
+      Static4D rotatedCamera= rotateVectorByInvertedQuat(cameraPoint, mQuatAccumulated);
 
-      for(int face=FRONT; face<=BOTTOM; face++)
-        {
-        if( faceIsVisible(face) && faceCondition(face) )
-          {
-          float A = retA(face,cubeHalfSize);
+      mCam[0] = rotatedCamera.get1();
+      mCam[1] = rotatedCamera.get2();
+      mCam[2] = rotatedCamera.get3();
+      }
 
-          mStartX = (mPoiX-mCamX)*A + mCamX;
-          mStartY = (mPoiY-mCamY)*A + mCamY;
-          mStartZ = (mPoiZ-mCamZ)*A + mCamZ;
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// given precomputed mCam and mPoi, respectively camera and touch point positions in ScreenSpace,
+// cast this touch point onto the 'face' and write the cast coords to 'output'.
+// Center of the 'face' = (0,0)
 
-          float qX= (mStartX+cubeHalfSize) / (2*cubeHalfSize);
-          float qY= (mStartY+cubeHalfSize) / (2*cubeHalfSize);
-          float qZ= (mStartZ+cubeHalfSize) / (2*cubeHalfSize);
+    private void castTouchPointOntoFace(int face, float cubeHalfSize, float[] output)
+      {
+      int sign = retFaceSign(face);
+      int zAxis= retFaceZaxis(face);
+      float diff = mPoi[zAxis]-mCam[zAxis];
 
-          if( qX<=1 && qX>=0 && qY<=1 && qY>=0 && qZ<=1 && qZ>=0 ) return face;
-          }
-        }
+      float ratio =  diff!=0.0f ? (sign*cubeHalfSize-mCam[zAxis])/diff : 0.0f;
 
-      return NONE;
+      output[0] = (mPoi[0]-mCam[0])*ratio + mCam[0];
+      output[1] = (mPoi[1]-mCam[1])*ratio + mCam[1];
+      output[2] = (mPoi[2]-mCam[2])*ratio + mCam[2];
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private void fillTouchPoint(int x, int y)
+    private int retFaceSign(int face)
       {
-      float halfScrWidth  = mScreenWidth *0.5f;
-      float halfScrHeight = mScreenHeight*0.5f;
-      Static4D touchPoint = new Static4D(x-halfScrWidth, halfScrHeight-y, 0, 0);
-      Static4D rotatedTouchPoint= rotateVectorByInvertedQuat(touchPoint, mQuatAccumulated);
+      return (face==FRONT || face==RIGHT || face==TOP) ? 1:-1;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-      mPoiX = rotatedTouchPoint.get1();
-      mPoiY = rotatedTouchPoint.get2();
-      mPoiZ = rotatedTouchPoint.get3();
+    private int retFaceRotationSign(int face)
+      {
+      return (face==BACK || face==RIGHT || face==TOP) ? 1:-1;
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private void fillCamera()
+    private int retFaceXaxis(int face)
       {
-      Static4D cameraPoint = new Static4D(0, 0, mCameraDistance, 0);
-      Static4D rotatedCamera= rotateVectorByInvertedQuat(cameraPoint, mQuatAccumulated);
+      switch(face)
+        {
+        case FRONT :
+        case BACK  : return VECTX;
+        case LEFT  :
+        case RIGHT : return VECTZ;
+        case TOP   :
+        case BOTTOM: return VECTX;
+        }
 
-      mCamX = rotatedCamera.get1();
-      mCamY = rotatedCamera.get2();
-      mCamZ = rotatedCamera.get3();
+      return -1;
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private float retA(int face, float cubeHalfSize)
+    private int retFaceYaxis(int face)
       {
       switch(face)
         {
-        case FRONT : return ( mPoiZ!=mCamZ ? ( cubeHalfSize-mCamZ)/(mPoiZ-mCamZ) : 0f);
-        case BACK  : return ( mPoiZ!=mCamZ ? (-cubeHalfSize-mCamZ)/(mPoiZ-mCamZ) : 0f);
-        case LEFT  : return ( mPoiX!=mCamX ? (-cubeHalfSize-mCamX)/(mPoiX-mCamX) : 0f);
-        case RIGHT : return ( mPoiX!=mCamX ? ( cubeHalfSize-mCamX)/(mPoiX-mCamX) : 0f);
-        case TOP   : return ( mPoiY!=mCamY ? ( cubeHalfSize-mCamY)/(mPoiY-mCamY) : 0f);
-        case BOTTOM: return ( mPoiY!=mCamY ? (-cubeHalfSize-mCamY)/(mPoiY-mCamY) : 0f);
+        case FRONT :
+        case BACK  : return VECTY;
+        case LEFT  :
+        case RIGHT : return VECTY;
+        case TOP   :
+        case BOTTOM: return VECTZ;
         }
 
-      return 0.0f;
+      return -1;
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private boolean faceCondition(int face)
+    private int retFaceZaxis(int face)
       {
       switch(face)
         {
         case FRONT :
-        case BACK  : return ( mPoiZ!=mCamZ );
+        case BACK  : return VECTZ;
         case LEFT  :
-        case RIGHT : return ( mPoiX!=mCamX );
+        case RIGHT : return VECTX;
         case TOP   :
-        case BOTTOM: return ( mPoiY!=mCamY );
+        case BOTTOM: return VECTY;
         }
 
-      return false;
+      return -1;
       }
 }
 
