commit 20a0214b2a0bb4edd6e5ddd7ffbdfe9d4ea5fe53
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Sep 17 23:31:38 2020 +0100

    More support for the Helicopter.

diff --git a/src/main/java/org/distorted/objects/RubikHelicopter.java b/src/main/java/org/distorted/objects/RubikHelicopter.java
index 76fde3b5..938dc037 100644
--- a/src/main/java/org/distorted/objects/RubikHelicopter.java
+++ b/src/main/java/org/distorted/objects/RubikHelicopter.java
@@ -34,6 +34,7 @@ import org.distorted.library.mesh.MeshBase;
 import org.distorted.library.mesh.MeshJoined;
 import org.distorted.library.mesh.MeshPolygon;
 import org.distorted.library.mesh.MeshSquare;
+import org.distorted.library.mesh.MeshTriangle;
 import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
@@ -160,8 +161,8 @@ public class RubikHelicopter extends RubikObject
   private static final int[][] mFaceMap = new int[][]
          {
            { 4,2,0, 6,6,6 },
-           { 2,5,0, 6,6,6 },
-           { 3,4,0, 6,6,6 },
+           { 0,2,5, 6,6,6 },
+           { 4,0,3, 6,6,6 },
            { 5,3,0, 6,6,6 },
            { 1,2,4, 6,6,6 },
            { 5,2,1, 6,6,6 },
@@ -199,6 +200,9 @@ public class RubikHelicopter extends RubikObject
            { 5 , 6,6,6,6,6 },
          };
 
+  private static int[] QUAT_INDICES =
+      { 0,13,14,1,12,2,3,7,20,6,13,17,7,23,18,12,22,10,8,16,11,21,19,9,3,15,14,0,5,2,1,4 };
+
   private static MeshBase mCornerMesh, mFaceMesh;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -239,7 +243,7 @@ public class RubikHelicopter extends RubikObject
     float[] vertices1 = { -F,-1.0f/12, +F,-1.0f/12, 0,1.0f/6 };
     float[] bands1 = { 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f };
 
-    meshes[3] = new MeshPolygon(vertices1,bands1,1,3);
+    meshes[3] = new MeshPolygon(vertices1,bands1,1,5);
     meshes[3].setEffectAssociation(0,8,0);
     meshes[4] = meshes[3].copy(true);
     meshes[4].setEffectAssociation(0,16,0);
@@ -338,9 +342,12 @@ public class RubikHelicopter extends RubikObject
 
   private void createFaceMesh()
     {
+    MeshBase[] meshes = new MeshBase[6];
+
     float D = 0.02f;
     float E = 0.5f;
     float F = SQ2/4;
+    float G = 1.0f/12;
 
     float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
 
@@ -352,12 +359,113 @@ public class RubikHelicopter extends RubikObject
                        0.30f   , D*1.375f,
                        0.0f    , D*1.4f };
 
-    MeshBase[] meshes = new MeshBase[6];
-
     meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
     meshes[0].setEffectAssociation(0,1,0);
 
-    // TODO
+    float[] vertices1 = { -F,-G, +F,-G, 0,2*G};
+
+    float[] bands1 = { 1.0f   , 0.0f,
+                       0.5f   , 0.02f,
+                       0.0f   , 0.03f };
+
+    meshes[1] = new MeshPolygon(vertices1, bands1, 1, 3);
+    meshes[1].setEffectAssociation(0,2,0);
+
+    float[] vertices2 = { -E/2,-F/3, +E/2,-F/3, 0,2*F/3};
+
+    float[] bands2 = { 1.0f   , 0.0f,
+                       0.5f   , 0.02f,
+                       0.0f   , 0.03f };
+
+    meshes[2] = new MeshPolygon(vertices2, bands2, 1, 3);
+    meshes[2].setEffectAssociation(0,4,0);
+    meshes[3] = meshes[2].copy(true);
+    meshes[3].setEffectAssociation(0,8,0);
+    meshes[4] = new MeshTriangle(1);
+    meshes[4].setEffectAssociation(0,16,0);
+    meshes[5] = new MeshTriangle(1);
+    meshes[5].setEffectAssociation(0,32,0);
+
+    mFaceMesh = new MeshJoined(meshes);
+
+    Static3D move0  = new Static3D(-1.0f/8, -1.0f/8, 0);
+    Static3D move1  = new Static3D(-(SQ2/24)-1.0f/4, -(SQ2/24)-1.0f/4, 0);
+    Static3D move2  = new Static3D(-E/2, F/3, 0);
+    Static3D move3  = new Static3D(+E/2, F/3, 0);
+    Static3D move4  = new Static3D(+E/3,+E/3, 0);
+    Static1D angle1 = new Static1D(135);
+    Static1D angle2 = new Static1D(90);
+    Static1D angle3 = new Static1D(-90);
+    Static1D angle4 = new Static1D(-135);
+    Static3D axisX  = new Static3D(1,0,0);
+    Static3D axisY  = new Static3D(0,1,0);
+    Static3D axisZ  = new Static3D(0,0,1);
+    Static3D axis1  = new Static3D(1,-1,0);
+    Static3D center = new Static3D(0,0,0);
+    Static3D center1= new Static3D(-0.25f,-0.25f,0);
+
+    float d0 =-0.04f;
+    float d1 =-0.04f;
+    float r0 = 0.15f;
+    float r1 = 0.10f;
+
+    Static3D vec0   = new Static3D(d0*(+SQ3/3),d0*(+SQ3/3),d0*(+SQ3/3));
+    Static3D vec1   = new Static3D(d1*(-SQ3/3),d1*(+SQ3/3),d1*(+SQ3/3));
+    Static3D vec2   = new Static3D(d1*(+SQ3/3),d1*(-SQ3/3),d1*(+SQ3/3));
+
+    Static1D radius = new Static1D(0.5f);
+
+    Static3D cent0  = new Static3D( 0.0f, 0.0f, 0.0f);
+    Static3D cent1  = new Static3D(-0.5f, 0.0f, 0.0f);
+    Static3D cent2  = new Static3D( 0.0f,-0.5f, 0.0f);
+
+    Static4D reg0   = new Static4D(0,0,0,r0);
+    Static4D reg1   = new Static4D(0,0,0,r1);
+
+    VertexEffectMove   effect0 = new VertexEffectMove(move0);
+    VertexEffectRotate effect1 = new VertexEffectRotate(angle1, axisZ, center);
+    VertexEffectMove   effect2 = new VertexEffectMove(move1);
+    VertexEffectRotate effect3 = new VertexEffectRotate(angle2, axis1, center1);
+    VertexEffectMove   effect4 = new VertexEffectMove(move2);
+    VertexEffectMove   effect5 = new VertexEffectMove(move3);
+    VertexEffectRotate effect6 = new VertexEffectRotate(angle3, axisZ, center);
+    VertexEffectRotate effect7 = new VertexEffectRotate(angle4, axisX, center);
+    VertexEffectRotate effect8 = new VertexEffectRotate(angle1, axisY, center);
+    VertexEffectScale  effect9 = new VertexEffectScale(0);
+    VertexEffectDeform effect10= new VertexEffectDeform(vec0,radius,cent0,reg0);
+    VertexEffectDeform effect11= new VertexEffectDeform(vec1,radius,cent1,reg1);
+    VertexEffectDeform effect12= new VertexEffectDeform(vec2,radius,cent2,reg1);
+    VertexEffectMove   effect13= new VertexEffectMove(move4);
+
+    effect0.setMeshAssociation( 1,-1);  // mesh 0
+    effect1.setMeshAssociation( 2,-1);  // mesh 1
+    effect2.setMeshAssociation( 2,-1);  // mesh 1
+    effect3.setMeshAssociation( 2,-1);  // mesh 1
+    effect4.setMeshAssociation( 4,-1);  // mesh 2
+    effect5.setMeshAssociation( 8,-1);  // mesh 3
+    effect6.setMeshAssociation( 8,-1);  // mesh 3
+    effect7.setMeshAssociation( 4,-1);  // mesh 2
+    effect8.setMeshAssociation( 8,-1);  // mesh 3
+    effect9.setMeshAssociation(48,-1);  // meshes 4,5
+    effect10.setMeshAssociation(15,-1); // meshes 0,1,2,3
+    effect11.setMeshAssociation(15,-1); // meshes 0,1,2,3
+    effect12.setMeshAssociation(15,-1); // meshes 0,1,2,3
+    effect13.setMeshAssociation(15,-1); // meshes 0,1,2,3
+
+    mFaceMesh.apply(effect0);
+    mFaceMesh.apply(effect1);
+    mFaceMesh.apply(effect2);
+    mFaceMesh.apply(effect3);
+    mFaceMesh.apply(effect4);
+    mFaceMesh.apply(effect5);
+    mFaceMesh.apply(effect6);
+    mFaceMesh.apply(effect7);
+    mFaceMesh.apply(effect8);
+    mFaceMesh.apply(effect9);
+    mFaceMesh.apply(effect10);
+    mFaceMesh.apply(effect11);
+    mFaceMesh.apply(effect12);
+    mFaceMesh.apply(effect13);
 
     mFaceMesh.mergeEffComponents();
     }
@@ -366,7 +474,7 @@ public class RubikHelicopter extends RubikObject
 
   float getScreenRatio()
     {
-    return 1.0f;
+    return 2.0f;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -404,50 +512,6 @@ public class RubikHelicopter extends RubikObject
     return CENTERS;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// TODO
-
-  private int getQuatIndex(int cubit)
-    {
-    switch(cubit)
-      {
-      case  0:
-      case  1:
-      case  2:
-      case  3:
-      case  4:
-      case  5:
-      case  6:
-      case  7:
-      case  8:
-      case  9:
-      case 10:
-      case 11:
-      case 12:
-      case 13:
-      case 14:
-      case 15:
-      case 16:
-      case 17:
-      case 18:
-      case 19:
-      case 20:
-      case 21:
-      case 22:
-      case 23:
-      case 24:
-      case 25:
-      case 26:
-      case 27:
-      case 28:
-      case 29:
-      case 30:
-      case 31:
-      }
-
-    return -1;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   MeshBase createCubitMesh(int cubit)
@@ -465,7 +529,7 @@ public class RubikHelicopter extends RubikObject
       mesh = mFaceMesh.copy(true);
       }
 
-    int index = getQuatIndex(cubit);
+    int index = QUAT_INDICES[cubit];
     MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[index], new Static3D(0,0,0) );
     mesh.apply(quat,0xffffffff,0);
 
@@ -556,7 +620,7 @@ public class RubikHelicopter extends RubikObject
 
   public int computeRowFromOffset(float offset)
     {
-    return offset<0.25f ? 0:1;
+    return offset<0.125f ? 0:1;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/RubikMovementHelicopter.java b/src/main/java/org/distorted/objects/RubikMovementHelicopter.java
index 020883c4..21ed7b69 100644
--- a/src/main/java/org/distorted/objects/RubikMovementHelicopter.java
+++ b/src/main/java/org/distorted/objects/RubikMovementHelicopter.java
@@ -25,7 +25,7 @@ class RubikMovementHelicopter extends RubikMovement
 {
   RubikMovementHelicopter()
     {
-    super(RubikSkewb.ROT_AXIS, RubikSkewb.FACE_AXIS, 0.25f, 0.25f);
+    super(RubikHelicopter.ROT_AXIS, RubikHelicopter.FACE_AXIS, 0.125f, 0.125f);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -50,7 +50,7 @@ class RubikMovementHelicopter extends RubikMovement
 
   boolean isInsideFace(float[] p)
     {
-    return ( p[0]<=0.25f && p[0]>=-0.25f && p[1]<=0.25f && p[1]>=-0.25f );
+    return ( p[0]<=0.125f && p[0]>=-0.125f && p[1]<=0.125f && p[1]>=-0.125f );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
