commit 462b983db01548e3267df123e3a156477aa2137a
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sat May 13 11:35:05 2023 +0200

    Introduce BandagedObjectPyraminx.

diff --git a/src/main/java/org/distorted/bandaged/BandagedObjectCuboid.java b/src/main/java/org/distorted/bandaged/BandagedObjectCuboid.java
index fe9cf01d..fac0be95 100644
--- a/src/main/java/org/distorted/bandaged/BandagedObjectCuboid.java
+++ b/src/main/java/org/distorted/bandaged/BandagedObjectCuboid.java
@@ -12,7 +12,7 @@ package org.distorted.bandaged;
 import org.distorted.library.main.DistortedScreen;
 import org.distorted.library.mesh.MeshBase;
 import org.distorted.library.type.Static3D;
-import org.distorted.objectlib.helpers.FactoryBandagedCubit;
+import org.distorted.objectlib.helpers.FactoryBandagedCuboid;
 import org.distorted.objectlib.main.InitData;
 import org.distorted.objectlib.main.TwistyObject;
 import org.distorted.objectlib.objects.TwistyBandagedCuboid;
@@ -69,42 +69,6 @@ public class BandagedObjectCuboid extends BandagedObject
     return dx*dx + dy*dy + dz*dz == 1;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  boolean tryChangeObject(int x, int y, int z)
-     {
-     if( mSize[0]!=x || mSize[1]!=y || mSize[2]!=z )
-       {
-       mSize[0] = x;
-       mSize[1] = y;
-       mSize[2] = z;
-       mMax = x>y ? Math.max(x,z) : Math.max(y,z);
-       mNumCubits = ( x<=1 || y<=1 || z<=1 ) ? x*y*z : x*y*z-(x-2)*(y-2)*(z-2);
-       return true;
-       }
-
-     return false;
-     }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  int computeProjectionAngle()
-     {
-     float quot1 = mSize[2]/ (float)mSize[0];
-     float quot2 = mSize[2]/ (float)mSize[1];
-     float quot3 = mSize[0]/ (float)mSize[2];
-     float quot4 = mSize[0]/ (float)mSize[1];
-
-     float quot5 = Math.max(quot1,quot2);
-     float quot6 = Math.max(quot3,quot4);
-     float quot7 = Math.max(quot5,quot6);
-
-          if( quot7<=1.0f ) return 120;
-     else if( quot7<=1.5f ) return 90;
-     else if( quot7<=2.0f ) return 60;
-     else                   return 30;
-     }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   float[][] getPositions()
@@ -167,6 +131,42 @@ public class BandagedObjectCuboid extends BandagedObject
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  boolean tryChangeObject(int x, int y, int z)
+     {
+     if( mSize[0]!=x || mSize[1]!=y || mSize[2]!=z )
+       {
+       mSize[0] = x;
+       mSize[1] = y;
+       mSize[2] = z;
+       mMax = x>y ? Math.max(x,z) : Math.max(y,z);
+       mNumCubits = ( x<=1 || y<=1 || z<=1 ) ? x*y*z : x*y*z-(x-2)*(y-2)*(z-2);
+       return true;
+       }
+
+     return false;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  int computeProjectionAngle()
+     {
+     float quot1 = mSize[2]/ (float)mSize[0];
+     float quot2 = mSize[2]/ (float)mSize[1];
+     float quot3 = mSize[0]/ (float)mSize[2];
+     float quot4 = mSize[0]/ (float)mSize[1];
+
+     float quot5 = Math.max(quot1,quot2);
+     float quot6 = Math.max(quot3,quot4);
+     float quot7 = Math.max(quot5,quot6);
+
+          if( quot7<=1.0f ) return 120;
+     else if( quot7<=1.5f ) return 90;
+     else if( quot7<=2.0f ) return 60;
+     else                   return 30;
+     }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   boolean isInsideFace(int face, float[] p)
@@ -187,9 +187,8 @@ public class BandagedObjectCuboid extends BandagedObject
 
   MeshBase createMesh(float[] pos, boolean round)
      {
-     FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
-     int[] size = getSize();
-     return factory.createMesh(pos,size[0],size[1],size[2],false,round);
+     FactoryBandagedCuboid factory = FactoryBandagedCuboid.getInstance();
+     return factory.createMesh(pos,mSize[0],mSize[1],mSize[2],false,round);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/bandaged/BandagedObjectPyraminx.java b/src/main/java/org/distorted/bandaged/BandagedObjectPyraminx.java
new file mode 100644
index 00000000..74f5d2d7
--- /dev/null
+++ b/src/main/java/org/distorted/bandaged/BandagedObjectPyraminx.java
@@ -0,0 +1,135 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2023 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.bandaged;
+
+import static org.distorted.objectlib.main.TwistyObject.SQ3;
+import static org.distorted.objectlib.main.TwistyObject.SQ6;
+
+import org.distorted.library.main.DistortedScreen;
+import org.distorted.library.mesh.MeshBase;
+import org.distorted.library.type.Static3D;
+import org.distorted.objectlib.helpers.FactoryBandagedPyraminx;
+import org.distorted.objectlib.main.InitData;
+import org.distorted.objectlib.main.TwistyObject;
+import org.distorted.objectlib.objects.TwistyBandagedPyraminx;
+import org.distorted.objectlib.shape.ShapeTetrahedron;
+import org.distorted.objectlib.touchcontrol.TouchControlTetrahedron;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class BandagedObjectPyraminx extends BandagedObject
+{
+   BandagedObjectPyraminx(DistortedScreen screen)
+     {
+     super(screen);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   float[] getDist3D()
+     {
+     float d = mSize[0]*SQ6/12;
+     return new float[] {d,d,d,d};
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   float getDist2D()
+     {
+     return SQ3/6;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   int[] getColors()
+     {
+     return ShapeTetrahedron.FACE_COLORS;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  Static3D[] getFaceAxis()
+    {
+    return TouchControlTetrahedron.FACE_AXIS;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  boolean tryChangeObject(int x, int y, int z)
+     {
+     if( mSize[0]!=x )
+       {
+       mSize[0] = x;
+       mMax = mSize[0];
+       int numOcta = (x-1)*x*(x+1)/6;
+       int numTetra= x*(x+1)*(x+2)/6;
+       mNumCubits = numOcta + numTetra;
+       return true;
+       }
+
+     return false;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  int computeProjectionAngle()
+     {
+     return 120;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// TODO
+
+  boolean isAdjacent(float dx, float dy, float dz)
+    {
+    return false;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// TODO
+
+  float[][] getPositions()
+    {
+    return null;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// TODO
+
+  void getTouchedPosition(float[] output, int face, float pointX, float pointY)
+    {
+
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// TODO
+
+  boolean isInsideFace(int face, float[] p)
+    {
+    return false;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  MeshBase createMesh(float[] pos, boolean round)
+     {
+     FactoryBandagedPyraminx factory = FactoryBandagedPyraminx.getInstance();
+     return factory.createMesh(pos,mSize[0],false,round);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  TwistyObject createObject(int mode, float size)
+     {
+     float[][] pos = getCubitPositions();
+     InitData data = new InitData( mSize,pos);
+     return new TwistyBandagedPyraminx( TwistyObject.MESH_NICE, mode, ShapeTetrahedron.DEFAULT_ROT, new Static3D(0,0,0), size, data, null );
+     }
+}
