commit 5caf2641f905b8e23f8630532f472d838c90b57d
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Dec 1 22:36:10 2022 +0100

    Beginnings of support for TouchControl of Icosehedral and Ball-shaped objects.

diff --git a/src/main/java/org/distorted/objectlib/main/TwistyObject.java b/src/main/java/org/distorted/objectlib/main/TwistyObject.java
index 6ffc8a43..853c1b16 100644
--- a/src/main/java/org/distorted/objectlib/main/TwistyObject.java
+++ b/src/main/java/org/distorted/objectlib/main/TwistyObject.java
@@ -2112,9 +2112,13 @@ public abstract class TwistyObject
                                    break;
         case TC_DODECAHEDRON     : mTouchControl = new TouchControlDodecahedron(this);
                                    break;
+        case TC_ICOSAHEDRON      : mTouchControl = new TouchControlIcosahedron(this);
+                                   break;
         case TC_CUBOID           : int[] numLayers = getNumLayers();
                                    mTouchControl = new TouchControlCuboids(this,getDist3D(numLayers));
                                    break;
+        case TC_BALL             : mTouchControl = new TouchControlBall(this);
+                                   break;
         case TC_CHANGING_MIRROR  : mTouchControl = new TouchControlMirror(this);
                                    break;
         case TC_CHANGING_SQUARE  : mTouchControl = new TouchControlSquare(this);
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControl.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControl.java
index 360e7c8f..e9100296 100644
--- a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControl.java
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControl.java
@@ -26,7 +26,9 @@ public abstract class TouchControl
   public static final int TC_TETRAHEDRON       =   4;
   public static final int TC_OCTAHEDRON        =   8;
   public static final int TC_DODECAHEDRON      =  12;
+  public static final int TC_ICOSAHEDRON       =  20;
   public static final int TC_CUBOID            =   0;
+  public static final int TC_BALL              =   1;
   public static final int TC_CHANGING_MIRROR   = 100;
   public static final int TC_CHANGING_SQUARE   = 101;
   public static final int TC_CHANGING_SHAPEMOD = 102;
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlBall.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlBall.java
new file mode 100644
index 00000000..97a85409
--- /dev/null
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlBall.java
@@ -0,0 +1,92 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2022 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Magic Cube.                                                              //
+//                                                                                               //
+// Magic Cube is proprietary software licensed under an EULA which you should have received      //
+// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.objectlib.touchcontrol;
+
+import org.distorted.library.main.QuatHelper;
+import org.distorted.library.type.Static3D;
+import org.distorted.library.type.Static4D;
+import org.distorted.objectlib.main.TwistyObject;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Ball-shaped objects: map the 2D swipes of user's fingers to 3D rotations
+
+public class TouchControlBall extends TouchControl
+{
+  private final Static3D[] mRotAxis;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public TouchControlBall(TwistyObject object)
+    {
+    super(object.getObjectRatio());
+    mRotAxis = object.getRotationAxis();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public float returnRotationFactor(int[] numLayers, int row)
+    {
+    return 1.0f;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getTouchedCubitFace()
+    {
+    return 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getTouchedCubit()
+    {
+    return 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// TODO
+
+  public boolean objectTouched(Static4D rotatedTouchPoint, Static4D rotatedCamera)
+    {
+    return false;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// TODO
+
+  public void newRotation(int[] output, Static4D rotatedTouchPoint, Static4D quat)
+    {
+
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// simply cast the appropriate rotational axis of the object to the screen surface.
+
+  public void getCastedRotAxis(float[] output, Static4D quat, int axisIndex)
+    {
+    Static3D a = mRotAxis[axisIndex];
+    Static4D result = QuatHelper.rotateVectorByQuat(a.get0(),a.get1(),a.get2(),0,quat);
+
+    float cx = result.get0();
+    float cy = result.get1();
+    float len= (float)Math.sqrt(cx*cx+cy*cy);
+
+    if( len!=0 )
+      {
+      output[0] = cx/len;
+      output[1] = cy/len;
+      }
+    else
+      {
+      output[0] = 1;
+      output[1] = 0;
+      }
+    }
+}
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlDodecahedron.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlDodecahedron.java
index a15d6329..418e0a34 100644
--- a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlDodecahedron.java
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlDodecahedron.java
@@ -124,7 +124,7 @@ public class TouchControlDodecahedron extends TouchControlShapeConstant
 // pentagon.
 // Distance from the center to a vertex of the pentagon = 1/(6*COS54)
 
-  int partEdge(float[] point, int face)
+  private int partEdge(float[] point, int face)
     {
     float angle = returnAngle(face);
     float A = (float)(Math.PI/5);
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlIcosahedron.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlIcosahedron.java
new file mode 100644
index 00000000..1ea61749
--- /dev/null
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlIcosahedron.java
@@ -0,0 +1,102 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2022 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Magic Cube.                                                              //
+//                                                                                               //
+// Magic Cube is proprietary software licensed under an EULA which you should have received      //
+// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.objectlib.touchcontrol;
+
+import static org.distorted.objectlib.main.TwistyObject.SQ5;
+
+import org.distorted.library.type.Static3D;
+import org.distorted.objectlib.main.TwistyObject;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Icosahedral objects: map the 2D swipes of user's fingers to 3D rotations
+
+public class TouchControlIcosahedron extends TouchControlShapeConstant
+{
+  public  static final float DIST3D = (3*SQ3 + SQ3*SQ5)/12;
+  private static final float DIST2D = SQ3/6;
+  public static final float[] D3D   = { DIST3D,DIST3D,DIST3D,DIST3D,DIST3D,
+                                        DIST3D,DIST3D,DIST3D,DIST3D,DIST3D,
+                                        DIST3D,DIST3D,DIST3D,DIST3D,DIST3D,
+                                        DIST3D,DIST3D,DIST3D,DIST3D,DIST3D };
+
+  public static final Static3D[] FACE_AXIS = new Static3D[]
+         {
+           // TODO
+         };
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public TouchControlIcosahedron(TwistyObject object)
+    {
+    super(object,D3D,FACE_AXIS);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public float returnRotationFactor(int[] numLayers, int row)
+    {
+    return 1.0f;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private boolean isFaceInverted(int face)
+    {
+    return face<10;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// corner    edge
+//   |       \ 0 /
+// 2 | 0      \ /
+//  / \      2 | 1
+// / 1 \       |
+
+  int returnPart(int type, int face, float[] touchPoint)
+    {
+    switch(type)
+      {
+      case TYPE_NOT_SPLIT   : return 0;
+
+      case TYPE_SPLIT_EDGE  : float y1 = (isFaceInverted(face) ? touchPoint[1] : -touchPoint[1]);
+                              float x1 = touchPoint[0];
+
+                              boolean e0 = x1>0;
+                              boolean e1 = y1>(+SQ3/3)*x1;
+                              boolean e2 = y1>(-SQ3/3)*x1;
+
+                              if(  e1 && e2 ) return 0;
+                              if( !e1 && e0 ) return 1;
+                              if( !e0 &&!e2 ) return 2;
+
+      case TYPE_SPLIT_CORNER: float y2 = (isFaceInverted(face) ? touchPoint[1] : -touchPoint[1]);
+                              float x2 = touchPoint[0];
+
+                              boolean c0 = x2>0;
+                              boolean c1 = y2>(+SQ3/3)*x2;
+                              boolean c2 = y2>(-SQ3/3)*x2;
+
+                              if(  c0 && c2 ) return 0;
+                              if( !c1 &&!c2 ) return 1;
+                              if( !c0 && c1 ) return 2;
+      }
+
+    return 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  boolean isInsideFace(int face, float[] p)
+    {
+    float y = (isFaceInverted(face) ? p[1] : -p[1]);
+    float x = p[0];
+    return (y >= -DIST2D) && (y <= DIST2D*(2-6*x)) && (y <= DIST2D*(2+6*x));
+    }
+}
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java
index 7236702d..d6813a40 100644
--- a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java
@@ -561,9 +561,9 @@ public class TouchControlShapeChanging extends TouchControl
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void getCastedRotAxis(float[] output, Static4D quat, int rotIndex)
+  public void getCastedRotAxis(float[] output, Static4D quat, int axisIndex)
     {
-    Static3D rotAxis = mRotAxis[rotIndex];
+    Static3D rotAxis = mRotAxis[axisIndex];
     float rx = rotAxis.get0();
     float ry = rotAxis.get1();
     float rz = rotAxis.get2();
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeConstant.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeConstant.java
index 4a23c2ce..d4d2e616 100644
--- a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeConstant.java
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeConstant.java
@@ -376,9 +376,9 @@ public abstract class TouchControlShapeConstant extends TouchControl
 // 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
 
-  public void getCastedRotAxis(float[] output, Static4D quat, int rotIndex)
+  public void getCastedRotAxis(float[] output, Static4D quat, int axisIndex)
     {
-    Static4D axis = mCastedRotAxis4D[mLastTouchedFace][rotIndex];
+    Static4D axis = mCastedRotAxis4D[mLastTouchedFace][axisIndex];
     Static4D result = QuatHelper.rotateVectorByQuat(axis, quat);
 
     output[0] =result.get0();
diff --git a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlTetrahedron.java b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlTetrahedron.java
index 522e0815..5a61b5d6 100644
--- a/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlTetrahedron.java
+++ b/src/main/java/org/distorted/objectlib/touchcontrol/TouchControlTetrahedron.java
@@ -82,7 +82,6 @@ public class TouchControlTetrahedron extends TouchControlShapeConstant
   public float returnRotationFactor(int[] numLayers, int row)
     {
     int numL = numLayers[0];
-
     return numL==2 ? 1.0f : ((float)numL)/(numL-row);
     }
 
