commit 84ee2a6ad0ab16fc0f1e57e988ae6a1c1b8a2bbc
Author: Leszek Koltunski <leszek@distorted.org>
Date:   Sun Jul 31 15:13:44 2016 +0100

    Advanced tesselation of DistortedCubes should be done! This fixes Bug #22

diff --git a/src/main/java/org/distorted/library/DistortedCubesGrid.java b/src/main/java/org/distorted/library/DistortedCubesGrid.java
index 3ca785c..087d9fc 100644
--- a/src/main/java/org/distorted/library/DistortedCubesGrid.java
+++ b/src/main/java/org/distorted/library/DistortedCubesGrid.java
@@ -68,14 +68,7 @@ class DistortedCubesGrid extends DistortedObjectGrid
    private short[][] mCubes;
    private ArrayList<Edge> mEdges = new ArrayList<>();
 
-   private boolean addEmpty1; // add an initial empty vertex? ( that would be because the initial block
-                              // of land is in the top-right quarter (or bottom-left) and thus the very
-                              // first triangle is counter-clockwise)
-   private boolean addEmpty2; // add an empty vertex when shifting from front to the side (that happens
-                              // iff the last front block is in the front-left or bottom-right quarter)
-   private boolean addEmpty3; // add an empty vertex when shifting from the side to the back. (that
-                              // happens iff the first back block is in the top right or bottom-left
-                              // quarter, i.e. actually addEmpty3 = addEmpty1.
+   private int remainingVert;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // a Block is split into two triangles along the NE-SW line iff it is in the top-right
@@ -87,15 +80,16 @@ class DistortedCubesGrid extends DistortedObjectGrid
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// return the number of vertices our grid will contain
 
    private int computeDataLength(boolean frontOnly)
       {
-      int frontWalls=0, frontSegments=0, sideWalls=0, sideBends=0, triangleShifts=0, rowJumpShifts=0;
+      int frontWalls=0, frontSegments=0, sideWalls=0, sideBends=0, triangleShifts=0, windingShifts=0;
       int shiftCol = (mCols-1)/2;
 
-      boolean seenLand=false;
+      //boolean seenLand=false;
+      //boolean firstBlockIsNE=false;
       boolean lastBlockIsNE=false;
-      boolean seenBlockInRow;
       boolean thisBlockIsNE;        // the block we are currently looking at is split into
                                     // two triangles along the NE-SW line (rather than NW-SE)
 
@@ -103,28 +97,20 @@ class DistortedCubesGrid extends DistortedObjectGrid
          {
          if( mCols>=2 && (mCubes[i][shiftCol]%2 == 1) && (mCubes[i][shiftCol+1]%2 == 1) ) triangleShifts++;
 
-         seenBlockInRow=false;
-
          for(int j=0; j<mCols; j++)
             {
             if( mCubes[i][j]%2 == 1 )  // land
               {
               thisBlockIsNE = isNE(i,j);
-
-              if( !seenBlockInRow )
-                {
-                if( thisBlockIsNE^lastBlockIsNE ) rowJumpShifts++;
-                seenBlockInRow=true;
-                }
-
+              if( thisBlockIsNE^lastBlockIsNE ) windingShifts++;
               lastBlockIsNE = thisBlockIsNE;
-
+/*
               if( !seenLand )
                 {
-                addEmpty1 = addEmpty3 = lastBlockIsNE;
                 seenLand=true;
+                firstBlockIsNE = thisBlockIsNE;
                 }
-
+*/
               frontWalls++;
               if( j==mCols-1 || mCubes[i][j+1]%2 == 0 ) frontSegments++;
               }
@@ -136,8 +122,6 @@ class DistortedCubesGrid extends DistortedObjectGrid
             }
          }
 
-      addEmpty2 = !lastBlockIsNE;
-
       int edges= mEdges.size();
       
       for(int i=0; i<edges; i++) 
@@ -157,16 +141,23 @@ class DistortedCubesGrid extends DistortedObjectGrid
         while( curr.col!=startX || curr.row!=startY || curr.side!=startS );
         }
 
-      int frontVert = 2*( frontWalls + 2*frontSegments - 1) +3*triangleShifts + rowJumpShifts;
+      int frontVert = 2*( frontWalls + 2*frontSegments - 1) +2*triangleShifts + windingShifts;
       int sideVert  = 2*( sideWalls + sideBends + edges -1);
+      int firstWinding=0;
+      //int secondWinding=0;
 
-      // no we don't add addEmpty1 because this is already included in the rowJumpShifts
-      int dataL = frontOnly ? frontVert : (frontVert+1) + (1+sideVert+1) + (1+frontVert) +(addEmpty2?1:0) + (addEmpty3?1:0);
+      if( !frontOnly )
+        {
+        if( (frontVert+1)%2==1 ) firstWinding=1;
+        //if( (((frontVert+1)+firstWinding+(1+sideVert+1))%2==1)^firstBlockIsNE ) secondWinding=1;
+        }
 
-      android.util.Log.e("CUBES","triangleShifts="+triangleShifts+" rowJumpShifts="+rowJumpShifts);
-      android.util.Log.e("CUBES","addEmpty1="+addEmpty1+" addEmpty2="+addEmpty2+" addEmpty3="+addEmpty3);
-      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 );
+      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 );
       
       return dataL<0 ? 0:dataL;
       }
@@ -238,6 +229,8 @@ class DistortedCubesGrid extends DistortedObjectGrid
        
        markRegions();
        dataLength = computeDataLength(frontOnly);
+
+       remainingVert = dataLength;
        }
      }
  
@@ -422,6 +415,20 @@ class DistortedCubesGrid extends DistortedObjectGrid
 
    private int addFrontVertex(int corner, int vertex, float centerX, float centerY, float vectZ, int col, int row, float[] position, float[] normal, float[] texture)
      {
+     remainingVert--;
+     /*
+     switch(corner)
+       {
+       case NW: android.util.Log.e("CUBES", "adding NW vertex!");
+                break;
+       case SW: android.util.Log.e("CUBES", "adding SW vertex!");
+                break;
+       case SE: android.util.Log.e("CUBES", "adding SE vertex!");
+                break;
+       case NE: android.util.Log.e("CUBES", "adding NE vertex!");
+                break;
+       }
+     */
      switch(corner)
        {
        case NW: position[3*vertex  ] = (centerX-0.5f)/mCols;
@@ -459,6 +466,7 @@ class DistortedCubesGrid extends DistortedObjectGrid
                 normal[3*vertex+2]   = mNormalZ[3];
                 texture[2*vertex  ]  = (float)(col+1)/mCols;
                 texture[2*vertex+1]  = (float)(row+1)/mRows;
+                return vertex+1;
        }
 
      return vertex;
@@ -475,6 +483,8 @@ class DistortedCubesGrid extends DistortedObjectGrid
      float centerX, centerY;
      float vectZ = front?FRONTZ:BACKZ;
 
+     //android.util.Log.d("CUBES", "buildFrontBack");
+
      for(int i=0; i<mRows; i++)
        {
        last =0;
@@ -488,7 +498,14 @@ class DistortedCubesGrid extends DistortedObjectGrid
            currentBlockIsNE = isNE(i,j);
            centerX = j-(mCols-1.0f)/2.0f;
            centerY = (mRows-1.0f)/2.0f-i;
-      
+
+           if( !seenLand && !front && ((vertex%2==1)^currentBlockIsNE) )
+             {
+             //android.util.Log.d("CUBES","repeating winding2 vertex");
+
+             vertex = repeatLast(vertex,position,normal,texture);
+             }
+
            createNormals(front,i,j);
 
            if( (last!=current) || (lastBlockIsNE^currentBlockIsNE) )
@@ -496,7 +513,8 @@ class DistortedCubesGrid extends DistortedObjectGrid
              if( seenLand  && (last != current) ) vertex = repeatLast(vertex,position,normal,texture);
              vertex= addFrontVertex( currentBlockIsNE ? NW:SW, vertex, centerX, centerY, vectZ, j, i, position, normal, texture);
              if( seenLand  && (last != current) ) vertex = repeatLast(vertex,position,normal,texture);
-             if( lastBlockIsNE^currentBlockIsNE ) vertex = repeatLast(vertex,position,normal,texture);
+             if( (lastBlockIsNE^currentBlockIsNE)
+                 || (!front && !seenLand)       ) vertex = repeatLast(vertex,position,normal,texture);
              vertex= addFrontVertex( currentBlockIsNE ? SW:NW, vertex, centerX, centerY, vectZ, j, i, position, normal, texture);
              }
            vertex= addFrontVertex( currentBlockIsNE ? NE:SE, vertex, centerX, centerY, vectZ, j, i, position, normal, texture);
@@ -517,6 +535,10 @@ class DistortedCubesGrid extends DistortedObjectGrid
 
    private int repeatLast(int vertex, float[] position, float[] normal, float[] texture)
      {
+     remainingVert--;
+
+     //android.util.Log.e("CUBES", "repeating last vertex!");
+
      if( vertex>0 )
        {
        position[3*vertex  ] = position[3*vertex-3];
@@ -540,9 +562,9 @@ class DistortedCubesGrid extends DistortedObjectGrid
 
    private int buildSideGrid(int vertex, float[] position, float[] normal, float[] texture)
      {
-     int edges= mEdges.size();
+     //android.util.Log.d("CUBES", "buildSide");
 
-     if( addEmpty2 ) vertex = repeatLast(vertex,position,normal,texture);
+     int edges= mEdges.size();
 
      for(int i=0; i<edges; i++) 
        {
@@ -573,22 +595,22 @@ class DistortedCubesGrid extends DistortedObjectGrid
      int side= curr.side;  
      Edge next = getNextEdge(curr);
      
-     addVertex(curr,BACK,LOWER,prev.side,vertex,position,normal,texture);
+     addSideVertex(curr,BACK,LOWER,prev.side,vertex,position,normal,texture);
      vertex++;
      
      do
        {
        if( prev.side!=curr.side )
          {
-         addVertex(curr,BACK,LOWER,prev.side,vertex,position,normal,texture);
+         addSideVertex(curr,BACK,LOWER,prev.side,vertex,position,normal,texture);
          vertex++;
-         addVertex(curr,BACK,UPPER,prev.side,vertex,position,normal,texture);
+         addSideVertex(curr,BACK,UPPER,prev.side,vertex,position,normal,texture);
          vertex++;
          }
        
-       addVertex(curr,FRONT,LOWER,next.side,vertex,position,normal,texture);
+       addSideVertex(curr,FRONT,LOWER,next.side,vertex,position,normal,texture);
        vertex++;
-       addVertex(curr,FRONT,UPPER,next.side,vertex,position,normal,texture);
+       addSideVertex(curr,FRONT,UPPER,next.side,vertex,position,normal,texture);
        vertex++;
        
        prev = curr;
@@ -655,8 +677,12 @@ class DistortedCubesGrid extends DistortedObjectGrid
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
-   private void addVertex(Edge curr, boolean back, boolean lower,int side, int vertex, float[] position, float[] normal, float[] texture)
+   private void addSideVertex(Edge curr, boolean back, boolean lower,int side, int vertex, float[] position, float[] normal, float[] texture)
      {
+     //android.util.Log.e("CUBES", "adding Side vertex!");
+
+     remainingVert--;
+
      float centerX = curr.col-(mCols-1.0f)/2.0f;
      float centerY = (mRows-1.0f)/2.0f-curr.row;
   
@@ -739,6 +765,12 @@ class DistortedCubesGrid extends DistortedObjectGrid
       if( !frontOnly )
         {
         numVertices = repeatLast(numVertices,positionData,normalData,textureData);
+        if( numVertices%2==1 )
+          {
+          //android.util.Log.d("CUBES","repeating winding1 vertex");
+
+          numVertices = repeatLast(numVertices,positionData,normalData,textureData);
+          }
         numVertices = buildSideGrid (numVertices,positionData,normalData,textureData);
         numVertices = buildFrontBackGrid (false,numVertices,positionData,normalData,textureData);
         }
@@ -749,6 +781,7 @@ class DistortedCubesGrid extends DistortedObjectGrid
       android.util.Log.d("CUBES", "normal: "  +debug(  normalData,3) );
       android.util.Log.d("CUBES", "texture: " +debug( textureData,2) );
       */
+      android.util.Log.d("CUBES", "remainingVert " +remainingVert );
 
       mGridPositions = ByteBuffer.allocateDirect(POSITION_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();                                                        
       mGridPositions.put(positionData).position(0); 
