commit fd527acd7bf93a21cf379158b48fbcfb7bb92421
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Jun 18 22:22:07 2023 +0200

    improve MeshPolygon. Now Multigon's meshes are close to perfect.

diff --git a/src/main/java/org/distorted/library/mesh/MeshPolygon.java b/src/main/java/org/distorted/library/mesh/MeshPolygon.java
index 1fd26ea..c18acb2 100644
--- a/src/main/java/org/distorted/library/mesh/MeshPolygon.java
+++ b/src/main/java/org/distorted/library/mesh/MeshPolygon.java
@@ -52,7 +52,8 @@ public class MeshPolygon extends MeshBase
   private int extraIndex, extraVertices;
 
   private float[] mCurveCache;
-  private float[] mEdgeQuots;
+  private float mVecX, mVecY;
+  private int[] mEdgeShape;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // polygonVertices>=3 , polygonBands>=2
@@ -118,34 +119,6 @@ public class MeshPolygon extends MeshBase
     mCurveCache[NUM_CACHE-1] = tmpD[mNumPolygonBands];
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void computeQuots()
-    {
-    mEdgeQuots = new float[mNumPolygonVertices];
-
-    for(int i=0; i<mNumPolygonVertices; i++)
-      {
-      int n = (i==mNumPolygonVertices-1 ? 0:i+1);
-
-      float x1 = mPolygonVertices[2*i];
-      float y1 = mPolygonVertices[2*i+1];
-      float x2 = mPolygonVertices[2*n];
-      float y2 = mPolygonVertices[2*n+1];
-      float A = x1-x2;
-      float B = y1-y2;
-      float C = A*A+B*B;
-
-      float x = (B*B*x1-A*B*y1)/C;
-      float y = (A*A*y1-A*B*x1)/C;
-
-      float dx = x1-x;
-      float dy = y1-y;
-
-      mEdgeQuots[i] = (float)Math.sqrt((dx*dx+dy*dy)/C);
-      }
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private float getSpecialQuot(int index)
@@ -225,7 +198,7 @@ public class MeshPolygon extends MeshBase
     {
     if( x>=1.0f )
       {
-      return mCurveCache[NUM_CACHE-1];
+      return 0.0f;
       }
     else
       {
@@ -238,51 +211,107 @@ public class MeshPolygon extends MeshBase
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void doNormals(float[] attribs1, int index, float quot, int edgeShape,
-                         float xEdge, float yEdge, float zEdge, int polyVertex, int polyBand)
+  private void figureOutNormalVector2D(int edgeShape, int polyVertex, int polyEndVer, float quot, float xEdge, float yEdge )
     {
-    if( ( quot<=0.5f && (edgeShape==SHAPE_UD || edgeShape==SHAPE_UU) ) ||
-        ( quot> 0.5f && (edgeShape==SHAPE_DU || edgeShape==SHAPE_UU) )  )
+    if( edgeShape==SHAPE_DD )
       {
-      attribs1[index  ] = 0;
-      attribs1[index+1] = 0;
-      attribs1[index+2] = 1;
+      if( quot<0.5f )
+        {
+        int p = polyVertex>0 ? polyVertex-1 : mNumPolygonVertices-1;
+        int prvShape = mEdgeShape[p];
+
+        switch(prvShape)
+          {
+          case SHAPE_DD : mVecX = xEdge;
+                          mVecY = yEdge;
+                          break;
+          case SHAPE_UD :
+          case SHAPE_DUD: float a = 2*quot;
+                          float xCurr= mPolygonVertices[2*polyVertex  ];
+                          float yCurr= mPolygonVertices[2*polyVertex+1];
+                          float xPrev= mPolygonVertices[2*p  ];
+                          float yPrev= mPolygonVertices[2*p+1];
+                          float xVec = xCurr-xPrev;
+                          float yVec = yCurr-yPrev;
+
+                          mVecX = a*xEdge + (1-a)*xVec;
+                          mVecY = a*yEdge + (1-a)*yVec;
+
+                          break;
+          default: throw new RuntimeException("figureOutNormalVector2D: impossible1: "+prvShape);
+          }
+        }
+      else
+        {
+        int n = polyEndVer==mNumPolygonVertices-1 ? 0 : polyEndVer+1;
+        int nxtShape = mEdgeShape[polyEndVer];
+
+        switch(nxtShape)
+          {
+          case SHAPE_DD : mVecX = xEdge;
+                          mVecY = yEdge;
+                          break;
+          case SHAPE_DU :
+          case SHAPE_DUD: float a = 2-2*quot;
+                          float xCurr= mPolygonVertices[2*polyEndVer  ];
+                          float yCurr= mPolygonVertices[2*polyEndVer+1];
+                          float xNext= mPolygonVertices[2*n  ];
+                          float yNext= mPolygonVertices[2*n+1];
+                          float xVec = xCurr-xNext;
+                          float yVec = yCurr-yNext;
+
+                          mVecX = a*xEdge + (1-a)*xVec;
+                          mVecY = a*yEdge + (1-a)*yVec;
+                          break;
+          default: throw new RuntimeException("figureOutNormalVector2D: impossible2: "+nxtShape);
+          }
+        }
+      }
+    else if( edgeShape==SHAPE_UU || (quot>=0.5f && edgeShape==SHAPE_DU) || (quot<0.5f && edgeShape==SHAPE_UD) )
+      {
+      mVecX = 1;
+      mVecY = 0;
       }
     else
       {
-      float d,x = 1-mPolygonBands[2*polyBand];
+      float dx = mPolygonVertices[2*polyVertex  ] - mPolygonVertices[2*polyEndVer  ];
+      float dy = mPolygonVertices[2*polyVertex+1] - mPolygonVertices[2*polyEndVer+1];
 
-      if( quot==0.0f || quot==1.0f || edgeShape==SHAPE_DD )
+      if( quot<0.5 )
         {
-        float t = mPolygonBands[2*mNumPolygonBands-1];
-        d = ((t-zEdge)/t)*derivative(x);
+        mVecX = dx;
+        mVecY = dy;
         }
       else
         {
-        float q = quot + x*(mEdgeQuots[polyVertex]-quot);
-        d = (q<0.5f ? derivative(2*q) : -derivative(2-2*q));
-        int nextVertex = polyVertex==mNumPolygonVertices-1 ? 0:polyVertex+1;
-        xEdge = mPolygonVertices[2*polyVertex  ] - mPolygonVertices[2*nextVertex  ];
-        yEdge = mPolygonVertices[2*polyVertex+1] - mPolygonVertices[2*nextVertex+1];
-
-        //android.util.Log.e("D", "normals: edgeQuot="+mEdgeQuots[polyVertex]+" vertex="+polyVertex+" d="+d+" xEdge="+xEdge+" yEdge="+yEdge+" q="+q+" quot="+quot);
+        mVecX = -dx;
+        mVecY = -dy;
         }
+      }
+    }
 
-      float vx = d*xEdge;
-      float vy = d*yEdge;
-      float vz = xEdge*xEdge + yEdge*yEdge;
-      float len = (float)Math.sqrt(vx*vx + vy*vy + vz*vz);
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-      attribs1[index  ] = vx/len;
-      attribs1[index+1] = vy/len;
-      attribs1[index+2] = vz/len;
+  private float figureOutDerivative(int edgeShape, int polyBand, float quot)
+    {
+    if( edgeShape==SHAPE_DD )
+      {
+      return derivative(1-mPolygonBands[2*polyBand]);
+      }
+    if( edgeShape==SHAPE_UU || (quot>=0.5f && edgeShape==SHAPE_DU) || (quot<0.5f && edgeShape==SHAPE_UD) )
+      {
+      return 0;
       }
+
+    float x = 1-mPolygonBands[2*polyBand];
+    float q = quot>=0.5f ? 2-2*quot : 2*quot;
+    return derivative((1-x)*q+x);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private int addVertex(int vertex, int polyBand, int polyVertex, int polyEndVer, float quot,
-                        int edgeShape, float[] attribs1, float[] attribs2)
+                        float[] attribs1, float[] attribs2)
     {
     remainingVert--;
 
@@ -299,7 +328,9 @@ public class MeshPolygon extends MeshBase
     float o = mPolygonBands[2*polyBand+1];
     float t = mPolygonBands[2*mNumPolygonBands-1];
 
-    switch(edgeShape)
+    int shape = mEdgeShape[polyVertex];
+
+    switch(shape)
       {
       case SHAPE_DD : zEdge = 0.0f; break;
       case SHAPE_UU : zEdge = t;    break;
@@ -316,8 +347,18 @@ public class MeshPolygon extends MeshBase
     attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y;
     attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = z;
 
+    figureOutNormalVector2D(shape, polyVertex, polyEndVer, quot, xEdge, yEdge);
+    float d = figureOutDerivative(shape,polyBand,quot);
+
+    float vx = d*mVecX;
+    float vy = d*mVecY;
+    float vz = mVecX*mVecX + mVecY*mVecY;
+    float len = (float)Math.sqrt(vx*vx + vy*vy + vz*vz);
+
     int index = VERT1_ATTRIBS*vertex + NOR_ATTRIB;
-    doNormals(attribs1,index, quot, edgeShape, xEdge, yEdge, zEdge, polyVertex, polyBand);
+    attribs1[index  ] = vx/len;
+    attribs1[index+1] = vy/len;
+    attribs1[index+2] = vz/len;
 
     attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB  ] = x+0.5f;
     attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f;
@@ -327,12 +368,12 @@ public class MeshPolygon extends MeshBase
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private int createBandStrip(int vertex, int polyBand, int polyVertex, int edgeShape, float[] attribs1, float[] attribs2)
+  private int createBandStrip(int vertex, int polyBand, int polyVertex, float[] attribs1, float[] attribs2)
     {
     if( polyVertex==0 )
       {
-      vertex = addVertex(vertex,polyBand,0,1,0,edgeShape,attribs1,attribs2);
-      if( polyBand>0 ) vertex = addVertex(vertex,polyBand,0,1,0,edgeShape,attribs1,attribs2);
+      vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
+      if( polyBand>0 ) vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
       }
 
     boolean specialCase = mNumPolygonBands==2 && polyBand==0 && extraIndex>0;
@@ -356,8 +397,8 @@ public class MeshPolygon extends MeshBase
         quot2 = getQuot(index+1,polyBand  , isExtra);
         }
 
-      vertex = addVertex(vertex,polyBand+1,polyVertex,polyEndVer,quot1,edgeShape,attribs1,attribs2);
-      vertex = addVertex(vertex,polyBand  ,polyVertex,polyEndVer,quot2,edgeShape,attribs1,attribs2);
+      vertex = addVertex(vertex,polyBand+1,polyVertex,polyEndVer,quot1,attribs1,attribs2);
+      vertex = addVertex(vertex,polyBand  ,polyVertex,polyEndVer,quot2,attribs1,attribs2);
       }
 
     return vertex;
@@ -384,18 +425,14 @@ public class MeshPolygon extends MeshBase
     {
     int vertex=0;
 
-    int[] edgeShape = new int[mNumPolygonVertices];
+    mEdgeShape = new int[mNumPolygonVertices];
 
     for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
-      edgeShape[polyVertex] = computeEdgeShape(polyVertex);
+      mEdgeShape[polyVertex] = computeEdgeShape(polyVertex);
 
     for(int polyBand=0; polyBand<mNumPolygonBands-1; polyBand++)
       for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
-        {
-       // android.util.Log.e("D", "creating strip polyBand="+polyBand+" polyVertex="+polyVertex+" : "+vertex);
-        vertex = createBandStrip(vertex,polyBand,polyVertex,edgeShape[polyVertex],attribs1,attribs2);
-       // android.util.Log.e("D", "  "+vertex);
-        }
+        vertex = createBandStrip(vertex,polyBand,polyVertex,attribs1,attribs2);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -457,7 +494,6 @@ public class MeshPolygon extends MeshBase
 
     computeNumberOfVertices();
     computeCache();
-    computeQuots();
 
     float[] attribs1= new float[VERT1_ATTRIBS*numVertices];
     float[] attribs2= new float[VERT2_ATTRIBS*numVertices];
