commit 8d9da98a96ef6983094583bb61111e3a3e4b2f50
Author: Leszek Koltunski <leszek@distorted.org>
Date:   Sat Dec 10 21:59:54 2016 +0000

    Fix a long-standing buf in CubesGrid (incorrect Grid in case of 5x5 11111 11011 10101 11011 11111)

diff --git a/src/main/java/org/distorted/library/DistortedCubesGrid.java b/src/main/java/org/distorted/library/DistortedCubesGrid.java
index 6df2e6f..4eb02b8 100644
--- a/src/main/java/org/distorted/library/DistortedCubesGrid.java
+++ b/src/main/java/org/distorted/library/DistortedCubesGrid.java
@@ -64,6 +64,8 @@ class DistortedCubesGrid extends DistortedObjectGrid
    private ArrayList<Edge> mEdges = new ArrayList<>();
 
    private int remainingVert;
+   private int mSideBends;
+   private int mEdgeNum;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // a Block is split into two triangles along the NE-SW line iff it is in the top-right
@@ -79,15 +81,12 @@ class DistortedCubesGrid extends DistortedObjectGrid
 
    private int computeDataLength(boolean frontOnly)
       {
-      int frontWalls=0, frontSegments=0, sideWalls=0, sideBends=0, triangleShifts=0, windingShifts=0;
+      int frontWalls=0, frontSegments=0, sideWalls=0, triangleShifts=0, windingShifts=0;
       int shiftCol = (mCols-1)/2;
 
-      //boolean seenLand=false;
-      //boolean firstBlockIsNE=false;
       boolean lastBlockIsNE=false;
       boolean thisBlockIsNE;        // the block we are currently looking at is split into
                                     // two triangles along the NE-SW line (rather than NW-SE)
-
       for(int row=0; row<mRows; row++)
          {
          if( mCols>=2 && (mCubes[row][shiftCol]%2 == 1) && (mCubes[row][shiftCol+1]%2 == 1) ) triangleShifts++;
@@ -99,13 +98,6 @@ class DistortedCubesGrid extends DistortedObjectGrid
               thisBlockIsNE = isNE(row,col);
               if( thisBlockIsNE^lastBlockIsNE ) windingShifts++;
               lastBlockIsNE = thisBlockIsNE;
-/*
-              if( !seenLand )
-                {
-                seenLand=true;
-                firstBlockIsNE = thisBlockIsNE;
-                }
-*/
               frontWalls++;
               if( col==mCols-1 || mCubes[row][col+1]%2 == 0 ) frontSegments++;
               }
@@ -117,43 +109,15 @@ class DistortedCubesGrid extends DistortedObjectGrid
             }
          }
 
-      int edges= mEdges.size();
-      
-      for(int i=0; i<edges; i++) 
-        {
-        Edge curr = mEdges.get(i);
-        Edge next = getNextEdge(curr);
-        int startX = curr.col;
-        int startY = curr.row;
-        int startS = curr.side;
-        
-        do
-          {
-          if( next.side != curr.side ) sideBends++; 
-          curr  = next; 
-          next = getNextEdge(curr);
-          }
-        while( curr.col!=startX || curr.row!=startY || curr.side!=startS );
-        }
-
       int frontVert = 2*( frontWalls + 2*frontSegments - 1) +2*triangleShifts + windingShifts;
-      int sideVert  = 2*( sideWalls + sideBends + edges -1);
-      int firstWinding=0;
-      //int secondWinding=0;
-
-      if( !frontOnly )
-        {
-        if( (frontVert+1)%2==1 ) firstWinding=1;
-        //if( (((frontVert+1)+firstWinding+(1+sideVert+1))%2==1)^firstBlockIsNE ) secondWinding=1;
-        }
-
+      int sideVert  = 2*( sideWalls + mSideBends + mEdgeNum -1);
+      int firstWinding= (!frontOnly && (frontVert+1)%2==1 ) ? 1:0;
       int dataL = frontOnly ? frontVert : (frontVert+1) +firstWinding+ (1+sideVert+1) + (1+frontVert);
-
-      //android.util.Log.e("CUBES","triangleShifts="+triangleShifts+" windingShifts="+windingShifts);
-      //android.util.Log.e("CUBES","Winding1="+firstWinding+" Winding2="+secondWinding);
-      //android.util.Log.e("CUBES","frontVert="+frontVert+" sideVert="+sideVert);
-      //android.util.Log.e("CUBES", "frontW="+frontWalls+" fSegments="+frontSegments+" sWalls="+sideWalls+" sSegments="+edges+" sideBends="+sideBends+" dataLen="+dataL );
-      
+/*
+      android.util.Log.e("CUBES","triangleShifts="+triangleShifts+" windingShifts="+windingShifts);
+      android.util.Log.e("CUBES","Winding1="+firstWinding+" frontVert="+frontVert+" sideVert="+sideVert);
+      android.util.Log.e("CUBES", "frontW="+frontWalls+" fSegments="+frontSegments+" sWalls="+sideWalls+" sSegments="+mEdgeNum+" sideBends="+mSideBends+" dataLen="+dataL );
+*/
       return dataL<0 ? 0:dataL;
       }
 
@@ -201,7 +165,7 @@ class DistortedCubesGrid extends DistortedObjectGrid
      
      return d;
      }   
-*/ 
+*/
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // desc is guaranteed to be padded with 0s in the end (DistortedCubes constructor does it)
 
@@ -262,7 +226,8 @@ class DistortedCubesGrid extends DistortedObjectGrid
 //   
 // This function also creates a list of 'Edges'. Each Edge is a data structure from which later on we
 // will start building the side walls of each connected block of land (and sides of holes of water
-// inside)   
+// inside). Each Edge needs to point from Land to Water (thus the '(SOUTH,i-1,j)' below) - otherwise
+// later on setting up normal vectors wouldn't work.
    
    private void markRegions()
      {
@@ -276,68 +241,53 @@ class DistortedCubesGrid extends DistortedObjectGrid
      for(i=0; i<mRows; i++)
         for(j=0; j<mCols; j++)
            {
-           if( mCubes[i][j] == 0 ) { numWater++; markRegion( (short)(2*numWater ),i,j); mEdges.add(new Edge(NORTH,i,j)); }
-           if( mCubes[i][j] == 1 ) { numLand ++; markRegion( (short)(2*numLand+1),i,j); mEdges.add(new Edge(NORTH,i,j)); }
+           if( mCubes[i][j] == 0 ) { numWater++; markRegion( (short)(2*numWater ),i,j); mEdges.add(new Edge(SOUTH,i-1,j)); }
+           if( mCubes[i][j] == 1 ) { numLand ++; markRegion( (short)(2*numLand+1),i,j); mEdges.add(new Edge(NORTH,i  ,j)); }
            }
      
-     // now we potentially need to kick out some Edges - precisely the edges with water inside -
-     // which are surrounded by more than one type of land. Otherwise the following does not work:
+     // now we potentially need to kick out some Edges . Otherwise the following does not work:
      //
      // 0 1 0
      // 1 0 1
      // 0 1 0
-     //
-     // The 'water inside' edges that did not get kicked out by this procedure need to be transformed
-     // with Edge(NORTH,row,col) -> Edge(SOUTH,row-1,col) so that later on normals work correctly
-     // (Edge always needs to point out from land to water for that)
      
-     int numEdges= mEdges.size();
-     short initLand;
-     int initCol, initRow;
-     boolean kicked;
-     Edge e;
+     mEdgeNum= mEdges.size();
+     int initCol, initRow, initSide, lastSide;
+     Edge e1,e2;
      
-     for(i=0; i<numEdges; i++) 
+     for(i=0; i<mEdgeNum; i++)
        {
-       e = mEdges.get(i);
-       initRow= e.row;
-       initCol= e.col;
-         
-       //android.util.Log.e("CUBES", "checking edge "+debug(e));
-             
-       if( mCubes[initRow][initCol]%2==0 )
+       e1 = mEdges.get(i);
+       initRow= e1.row;
+       initCol= e1.col;
+       initSide=e1.side;
+
+       do
          {
-         kicked = false; 
-         initLand = mCubes[initRow-1][initCol];
-         
-         do
+         //android.util.Log.d("CUBES", "checking edge "+debug(e1));
+
+         if( e1.side==NORTH || e1.side==SOUTH )
            {
-           e = getNextEdge(e); 
-           //android.util.Log.e("CUBES", " next edge "+debug(e));   
-       
-           switch(e.side)
+           for(j=i+1;j<mEdgeNum;j++)
              {
-             case NORTH: if( initLand!=mCubes[e.row-1][e.col  ] ) kicked=true; break;
-             case SOUTH: if( initLand!=mCubes[e.row+1][e.col  ] ) kicked=true; break;
-             case WEST:  if( initLand!=mCubes[e.row  ][e.col-1] ) kicked=true; break;
-             case EAST:  if( initLand!=mCubes[e.row  ][e.col+1] ) kicked=true; break;
-             }
-           
-           if( kicked )
-             {
-             //android.util.Log.e("CUBES", "kicking out edge!");
-             mEdges.remove(i);
-             i--;
-             numEdges--; 
+             e2 = mEdges.get(j);
+
+             if( e2.side==e1.side && e2.row==e1.row && e2.col==e1.col )
+               {
+               mEdges.remove(j);
+               mEdgeNum--;
+               j--;
+
+               //android.util.Log.e("CUBES", "removing edge "+debug(e2));
+               }
              }
            }
-         while( kicked==false && (e.col!=initCol || e.row!=initRow || e.side!=NORTH) );
-         
-         if( kicked==false )
-           {
-           mEdges.set(i, new Edge(SOUTH,e.row-1,e.col)); 
-           }
+
+         lastSide = e1.side;
+         e1 = getNextEdge(e1);
+         if( e1.side!=lastSide ) mSideBends++;
          }
+       while( e1.col!=initCol || e1.row!=initRow || e1.side!=initSide );
        }
      }
 
@@ -555,9 +505,7 @@ class DistortedCubesGrid extends DistortedObjectGrid
      {
      //android.util.Log.d("CUBES", "buildSide");
 
-     int edges= mEdges.size();
-
-     for(int i=0; i<edges; i++) 
+     for(int i=0; i<mEdgeNum; i++)
        {
        vertex = buildIthSide(mEdges.get(i), vertex, position, normal, texture);  
        } 
@@ -653,7 +601,7 @@ class DistortedCubesGrid extends DistortedObjectGrid
                    else 
                      return new Edge(SOUTH,row,col);
                    
-       case WEST : if( row==0 )
+       default   : if( row==0 )
                      return new Edge(NORTH,row,col);
                    if( col>0 && mCubes[row-1][col-1]==mCubes[row][col] )
                      return new Edge(SOUTH,row-1,col-1);
@@ -662,8 +610,6 @@ class DistortedCubesGrid extends DistortedObjectGrid
                    else
                      return new Edge(NORTH,row,col);     
        }
-     
-     return null;
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -777,6 +723,10 @@ class DistortedCubesGrid extends DistortedObjectGrid
      android.util.Log.d("CUBES", "texture: " +debug( textureData,2) );
      */
 
+     mEdges.clear();
+     mEdges = null;
+     mCubes = null;
+
      if( remainingVert!=0 )
        android.util.Log.d("CUBES", "remainingVert " +remainingVert );
 
