commit ce7f383390afbf6c5fac307cce0ff072afdb460f
Author: Leszek Koltunski <leszek@distorted.org>
Date:   Sun Jul 31 02:25:31 2016 +0100

    beginnings of support for advanced tesselation in DistortedCubes target (still doesn't quite work)

diff --git a/src/main/java/org/distorted/library/DistortedCubesGrid.java b/src/main/java/org/distorted/library/DistortedCubesGrid.java
index 9675f76..3ca785c 100644
--- a/src/main/java/org/distorted/library/DistortedCubesGrid.java
+++ b/src/main/java/org/distorted/library/DistortedCubesGrid.java
@@ -35,7 +35,12 @@ class DistortedCubesGrid extends DistortedObjectGrid
    private static final int WEST  = 1;
    private static final int EAST  = 2;
    private static final int SOUTH = 3;
-   
+
+   private static final int NW = 0;
+   private static final int NE = 1;
+   private static final int SW = 2;
+   private static final int SE = 3;
+
    private static final boolean BACK  = true;
    private static final boolean FRONT = false;
    private static final boolean UPPER = false;
@@ -43,7 +48,8 @@ class DistortedCubesGrid extends DistortedObjectGrid
    
    private static final float[] mNormalX = new float[4];
    private static final float[] mNormalY = new float[4];
-   
+   private static final float[] mNormalZ = new float[4];
+
    private class Edge
      {
      final int side; 
@@ -61,18 +67,64 @@ class DistortedCubesGrid extends DistortedObjectGrid
    private int mCols, mRows;
    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.
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// a Block is split into two triangles along the NE-SW line iff it is in the top-right
+// or bottom-left quadrant of the grid.
+
+   private boolean isNE(int row,int col)
+     {
+     return ( (row<=(mRows-1)/2)^(col<=(mCols-1)/2) );
+     }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    private int computeDataLength(boolean frontOnly)
       {
-      int frontWalls=0, frontSegments=0, sideWalls=0, sideBends=0;
-      
+      int frontWalls=0, frontSegments=0, sideWalls=0, sideBends=0, triangleShifts=0, rowJumpShifts=0;
+      int shiftCol = (mCols-1)/2;
+
+      boolean seenLand=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)
+
       for(int i=0; i<mRows; i++)
+         {
+         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;
+                }
+
+              lastBlockIsNE = thisBlockIsNE;
+
+              if( !seenLand )
+                {
+                addEmpty1 = addEmpty3 = lastBlockIsNE;
+                seenLand=true;
+                }
+
               frontWalls++;
               if( j==mCols-1 || mCubes[i][j+1]%2 == 0 ) frontSegments++;
               }
@@ -82,6 +134,9 @@ class DistortedCubesGrid extends DistortedObjectGrid
             if( i==mRows-1 && mCubes[i][j]!=2                                           ) sideWalls++; // bottom
             if( j==mCols-1 && mCubes[i][j]!=2                                           ) sideWalls++; // right
             }
+         }
+
+      addEmpty2 = !lastBlockIsNE;
 
       int edges= mEdges.size();
       
@@ -101,14 +156,17 @@ class DistortedCubesGrid extends DistortedObjectGrid
           }
         while( curr.col!=startX || curr.row!=startY || curr.side!=startS );
         }
-      
-      int frontVert = 2*( frontWalls + 2*frontSegments - 1);
+
+      int frontVert = 2*( frontWalls + 2*frontSegments - 1) +3*triangleShifts + rowJumpShifts;
       int sideVert  = 2*( sideWalls + sideBends + edges -1);
-      
-      int dataL = frontOnly ? frontVert : (frontVert+1) + (1+sideVert+1) + (1+frontVert);
-      
-      //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 );
+
+      // 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);
+
+      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 );
       
       return dataL<0 ? 0:dataL;
       }
@@ -117,7 +175,7 @@ class DistortedCubesGrid extends DistortedObjectGrid
 /*
    private static String debug(short[] val)
      {
-     String ret="";
+     String ret="";j
      
      for(int i=0; i<val.length; i++) ret+=(" "+val[i]); 
      
@@ -287,7 +345,7 @@ class DistortedCubesGrid extends DistortedObjectGrid
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
-   private void createNormals(int row, int col)
+   private void createNormals(boolean front, int row, int col)
      {
      int td,lr; 
       
@@ -300,7 +358,22 @@ class DistortedCubesGrid extends DistortedObjectGrid
      int ne = (col<mCols-1 && row>0      ) ? (mCubes[row-1][col+1]%2) : 0;
      int e  = (col<mCols-1               ) ? (mCubes[row  ][col+1]%2) : 0;
      int se = (col<mCols-1 && row<mRows-1) ? (mCubes[row+1][col+1]%2) : 0;
-     
+
+     if(front)
+       {
+       mNormalZ[0] = 1.0f;
+       mNormalZ[1] = 1.0f;
+       mNormalZ[2] = 1.0f;
+       mNormalZ[3] = 1.0f;
+       }
+     else
+       {
+       mNormalZ[0] =-1.0f;
+       mNormalZ[1] =-1.0f;
+       mNormalZ[2] =-1.0f;
+       mNormalZ[3] =-1.0f;
+       }
+
      td = nw+n-w-c;
      lr = c+n-w-nw;
      if( td<0 ) td=-1;
@@ -346,13 +419,62 @@ 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)
+     {
+     switch(corner)
+       {
+       case NW: position[3*vertex  ] = (centerX-0.5f)/mCols;
+                position[3*vertex+1] = (centerY+0.5f)/mRows;
+                position[3*vertex+2] = vectZ;
+                normal[3*vertex  ]   = mNormalX[0];
+                normal[3*vertex+1]   = mNormalY[0];
+                normal[3*vertex+2]   = mNormalZ[0];
+                texture[2*vertex  ]  = (float)col/mCols;
+                texture[2*vertex+1]  = (float)row/mRows;
+                return vertex+1;
+       case SW: position[3*vertex  ] = (centerX-0.5f)/mCols;
+                position[3*vertex+1] = (centerY-0.5f)/mRows;
+                position[3*vertex+2] = vectZ;
+                normal[3*vertex  ]   = mNormalX[1];
+                normal[3*vertex+1]   = mNormalY[1];
+                normal[3*vertex+2]   = mNormalZ[1];
+                texture[2*vertex  ]  = (float)col/mCols;
+                texture[2*vertex+1]  = (float)(row+1)/mRows;
+                return vertex+1;
+       case NE: position[3*vertex  ] = (centerX+0.5f)/mCols;
+                position[3*vertex+1] = (centerY+0.5f)/mRows;
+                position[3*vertex+2] = vectZ;
+                normal[3*vertex  ]   = mNormalX[2];
+                normal[3*vertex+1]   = mNormalY[2];
+                normal[3*vertex+2]   = mNormalZ[2];
+                texture[2*vertex  ]  = (float)(col+1)/mCols;
+                texture[2*vertex+1]  = (float)row/mRows;
+                return vertex+1;
+       case SE: position[3*vertex  ] = (centerX+0.5f)/mCols;
+                position[3*vertex+1] = (centerY-0.5f)/mRows;
+                position[3*vertex+2] = vectZ;
+                normal[3*vertex  ]   = mNormalX[3];
+                normal[3*vertex+1]   = mNormalY[3];
+                normal[3*vertex+2]   = mNormalZ[3];
+                texture[2*vertex  ]  = (float)(col+1)/mCols;
+                texture[2*vertex+1]  = (float)(row+1)/mRows;
+       }
+
+     return vertex;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
    private int buildFrontBackGrid(boolean front, int vertex, float[] position, float[] normal, float[] texture)
      {
      short last, current;
-     boolean seenland=false;
+     boolean seenLand=false;
+     boolean lastBlockIsNE = false;
+     boolean currentBlockIsNE;
      float centerX, centerY;
-    
+     float vectZ = front?FRONTZ:BACKZ;
+
      for(int i=0; i<mRows; i++)
        {
        last =0;
@@ -360,124 +482,28 @@ class DistortedCubesGrid extends DistortedObjectGrid
        for(int j=0; j<mCols; j++)
          {
          current = mCubes[i][j];
-            
+
          if( current%2 == 1 )
            {
+           currentBlockIsNE = isNE(i,j);
            centerX = j-(mCols-1.0f)/2.0f;
            centerY = (mRows-1.0f)/2.0f-i;
       
-           createNormals(i,j);
-          
-           if( last != current )
-             {
-             if( seenland ) vertex = repeatLast(vertex,position,normal,texture);    
-
-             if( front ) // NW corner
-               {
-               position[3*vertex  ] = (centerX-0.5f)/mCols;
-               position[3*vertex+1] = (centerY+0.5f)/mRows;
-               position[3*vertex+2] = FRONTZ;
-               normal[3*vertex  ]   = mNormalX[0];
-               normal[3*vertex+1]   = mNormalY[0];
-               normal[3*vertex+2]   = 1.0f;
-               texture[2*vertex  ]  = (float)j/mCols;
-               texture[2*vertex+1]  = (float)i/mRows;     
-               vertex++;
-               }
-             else  // SW corner
-               { 
-               position[3*vertex  ] = (centerX-0.5f)/mCols;
-               position[3*vertex+1] = (centerY-0.5f)/mRows; 
-               position[3*vertex+2] = BACKZ; 
-               normal[3*vertex  ]   = mNormalX[1];
-               normal[3*vertex+1]   = mNormalY[1];
-               normal[3*vertex+2]   =-1.0f;
-               texture[2*vertex  ]  = (float)j/mCols;
-               texture[2*vertex+1]  = (float)(i+1)/mRows;
-               vertex++;
-               
-               if( !seenland ) vertex = repeatLast(vertex,position,normal,texture);   //  if drawing the back, repeat the very first vertex
-               }
-             
-             if( seenland ) vertex = repeatLast(vertex,position,normal,texture);    
-
-             if( front ) // SW corner
-               {
-               position[3*vertex  ] = (centerX-0.5f)/mCols;
-               position[3*vertex+1] = (centerY-0.5f)/mRows; 
-               position[3*vertex+2] = FRONTZ; 
-               normal[3*vertex  ]   = mNormalX[1];
-               normal[3*vertex+1]   = mNormalY[1];
-               normal[3*vertex+2]   = 1.0f;
-               texture[2*vertex  ]  = (float)j/mCols;
-               texture[2*vertex+1]  = (float)(i+1)/mRows;
-               vertex++; 
-               }
-             else  // NW corner
-               {
-               position[3*vertex  ] = (centerX-0.5f)/mCols;
-               position[3*vertex+1] = (centerY+0.5f)/mRows;
-               position[3*vertex+2] = BACKZ;
-               normal[3*vertex  ]   = mNormalX[0];
-               normal[3*vertex+1]   = mNormalY[0];
-               normal[3*vertex+2]   =-1.0f;
-               texture[2*vertex  ]  = (float)j/mCols;
-               texture[2*vertex+1]  = (float)i/mRows;     
-               vertex++; 
-               }
-             }
-              
-           if( front )  // NE corner
-             {
-             position[3*vertex  ] = (centerX+0.5f)/mCols;
-             position[3*vertex+1] = (centerY+0.5f)/mRows;
-             position[3*vertex+2] = FRONTZ; 
-             normal[3*vertex  ]   = mNormalX[2];
-             normal[3*vertex+1]   = mNormalY[2];
-             normal[3*vertex+2]   = 1.0f;
-             texture[2*vertex  ]  = (float)(j+1)/mCols;
-             texture[2*vertex+1]  = (float)i/mRows;
-             vertex++;
-             }
-           else // SE corner
-             {
-             position[3*vertex  ] = (centerX+0.5f)/mCols;
-             position[3*vertex+1] = (centerY-0.5f)/mRows;
-             position[3*vertex+2] = BACKZ; 
-             normal[3*vertex  ]   = mNormalX[3];
-             normal[3*vertex+1]   = mNormalY[3];
-             normal[3*vertex+2]   =-1.0f;
-             texture[2*vertex  ]  = (float)(j+1)/mCols;
-             texture[2*vertex+1]  = (float)(i+1)/mRows;
-             vertex++; 
-             }
-           
-           if( front )  // SE corner
-             {
-             position[3*vertex  ] = (centerX+0.5f)/mCols;
-             position[3*vertex+1] = (centerY-0.5f)/mRows;
-             position[3*vertex+2] = FRONTZ; 
-             normal[3*vertex  ]   = mNormalX[3];
-             normal[3*vertex+1]   = mNormalY[3];
-             normal[3*vertex+2]   = 1.0f;
-             texture[2*vertex  ]  = (float)(j+1)/mCols;
-             texture[2*vertex+1]  = (float)(i+1)/mRows;
-             vertex++;
-             }
-           else // NE corner
+           createNormals(front,i,j);
+
+           if( (last!=current) || (lastBlockIsNE^currentBlockIsNE) )
              {
-             position[3*vertex  ] = (centerX+0.5f)/mCols;
-             position[3*vertex+1] = (centerY+0.5f)/mRows;
-             position[3*vertex+2] = BACKZ; 
-             normal[3*vertex  ]   = mNormalX[2];
-             normal[3*vertex+1]   = mNormalY[2];
-             normal[3*vertex+2]   =-1.0f;
-             texture[2*vertex  ]  = (float)(j+1)/mCols;
-             texture[2*vertex+1]  = (float)i/mRows;
-             vertex++; 
+             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);
+             vertex= addFrontVertex( currentBlockIsNE ? SW:NW, vertex, centerX, centerY, vectZ, j, i, position, normal, texture);
              }
-           
-           seenland = true;
+           vertex= addFrontVertex( currentBlockIsNE ? NE:SE, vertex, centerX, centerY, vectZ, j, i, position, normal, texture);
+           vertex= addFrontVertex( currentBlockIsNE ? SE:NE, vertex, centerX, centerY, vectZ, j, i, position, normal, texture);
+
+           seenLand = true;
+           lastBlockIsNE = currentBlockIsNE;
            }
             
          last = current;
@@ -515,7 +541,9 @@ class DistortedCubesGrid extends DistortedObjectGrid
    private int buildSideGrid(int vertex, float[] position, float[] normal, float[] texture)
      {
      int edges= mEdges.size();
-     
+
+     if( addEmpty2 ) vertex = repeatLast(vertex,position,normal,texture);
+
      for(int i=0; i<edges; i++) 
        {
        vertex = buildIthSide(mEdges.get(i), vertex, position, normal, texture);  
