commit adb2661cd042892a1c0ee34884d1810e74c4a2c9
Author: Leszek Koltunski <leszek@distorted.org>
Date:   Wed Aug 3 00:09:09 2016 +0100

    Correctly tesselate the DistortedBitmap target!

diff --git a/src/main/java/org/distorted/library/DistortedBitmap.java b/src/main/java/org/distorted/library/DistortedBitmap.java
index 355f0aa..ec5f2c8 100644
--- a/src/main/java/org/distorted/library/DistortedBitmap.java
+++ b/src/main/java/org/distorted/library/DistortedBitmap.java
@@ -70,9 +70,9 @@ public class DistortedBitmap extends DistortedObject
  */
    public DistortedBitmap(int width, int height, int cols)
      {     
-     int xsize = (cols+1);
-     int ysize = (cols+1)*height/width;
-     
+     int xsize = cols;
+     int ysize = cols*height/width;
+
      if( xsize<2   ) xsize=  2;
      if( xsize>256 ) xsize=256;
      if( ysize<2   ) ysize=  2;
diff --git a/src/main/java/org/distorted/library/DistortedBitmapGrid.java b/src/main/java/org/distorted/library/DistortedBitmapGrid.java
index e2522fa..30c13bf 100644
--- a/src/main/java/org/distorted/library/DistortedBitmapGrid.java
+++ b/src/main/java/org/distorted/library/DistortedBitmapGrid.java
@@ -26,168 +26,152 @@ import java.nio.ByteOrder;
 
 class DistortedBitmapGrid extends DistortedObjectGrid
   {
+  private int mCols, mRows;
+  private int remainingVert;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// create a flat, full grid
 
-  DistortedBitmapGrid(int xLength, int yLength)
-    {
-    float tmpx,tmpy,tmpz;
-    float[] bufferData;
+   private void computeNumberOfVertices(int cols, int rows)
+     {
+     //android.util.Log.e("BITMAP","preparing data structures, cols="+cols+" rows="+rows);
 
-    dataLength = 2*xLength*(yLength-1)  // (yLength-1) strips, 2*xLength triangles in each,
-                        +2*(yLength-2); // plus 2 degenerate triangles per each of (yLength-2) joins
+     mRows     =0;
+     mCols     =0;
+     dataLength=0;
 
-    if( xLength>2 )
-      {
-      dataLength += 3*(yLength-1); // we change direction of triangles midway through each row (+3 triangles per row)
-      dataLength +=   (yLength-2); // we also need to change direction when pulling back to the left (+1 extra triangle)
+     if( cols>0 )
+       {
+       mCols = cols;
+       mRows = rows;
 
-      if( yLength>2 )
-        dataLength -= 1;           // but if we do a vertical triangle direction shift as well, then one of the 'pull backs'
-                                   // does not have to add an extra triangle.
-      }
+       dataLength = 2*( mRows*mCols +2*mRows - 1) +2*(mCols>=2 ? mRows:0) +
+                    (mCols>=2 && mRows>=2 ? 2*mRows-2 : 1);
 
-    ////////////////////////////////////////////////////////////
-    // vertex indices
+       //android.util.Log.e("BITMAP","vertices="+dataLength);
 
-    int offset=0;
-    final short[] indexData = new short[dataLength];
+       remainingVert = dataLength;
+       }
+     }
 
-    int changePointX = xLength/2;
-    int changePointY = yLength/2;
 
-    for(int y=0; y<yLength-1; y++)
-      {
-      if( y>0 )
-        {
-        if( y<changePointY )
-          {
-          indexData[offset++] = (short) ((y+1)*xLength);
-          if( xLength>2 )
-            indexData[offset++] = (short) ((y+1)*xLength);
-          }
-        else
-          {
-          indexData[offset++] = (short) (y*xLength);
-          if( xLength>2 && y!=changePointY)
-            indexData[offset++] = (short) (y*xLength);
-          }
-        }
-
-      if (y<changePointY)
-        {
-        for(int x=0; x<xLength; x++)
-          {
-          if( x<=changePointX )
-            {
-            indexData[offset++] = (short) (((y+1)*xLength)+x);
-            indexData[offset++] = (short) (( y   *xLength)+x);
-            }
-          else
-            {
-            indexData[offset++] = (short) (( y   *xLength)+x);
-            indexData[offset++] = (short) (((y+1)*xLength)+x);
-            }
-
-          if( x==changePointX && xLength>2 )
-            {
-            indexData[offset++] = (short) (( y   *xLength)+x);
-            indexData[offset++] = (short) (( y   *xLength)+x);
-            indexData[offset++] = (short) (((y+1)*xLength)+x);
-            }
-          }
-        }
-      else
-        {
-        for(int x=0; x<xLength; x++)
-          {
-          if( x<=changePointX )
-            {
-            indexData[offset++] = (short) (( y   *xLength)+x);
-            indexData[offset++] = (short) (((y+1)*xLength)+x);
-            }
-          else
-            {
-            indexData[offset++] = (short) (((y+1)*xLength)+x);
-            indexData[offset++] = (short) (( y   *xLength)+x);
-            }
-
-          if( x==changePointX && xLength>2 )
-            {
-            indexData[offset++] = (short) (((y+1)*xLength)+x);
-            indexData[offset++] = (short) (((y+1)*xLength)+x);
-            indexData[offset++] = (short) (( y   *xLength)+x);
-            }
-          }
-        }
-
-      if (y<changePointY && yLength>2 )
-        {
-        indexData[offset++] = (short) (((y+1)*xLength) + (xLength-1));
-        }
-      else if(y<yLength-2)
-        {
-        indexData[offset++] = (short) ((y    *xLength) + (xLength-1));
-        }
-      }
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-     //android.util.Log.e("grid", "xLength="+xLength+" yLength="+yLength);
-     //for(int g=0; g<dataLength; g++) android.util.Log.e("grid", "index["+g+"]="+indexData[g]);
+   private int addVertex(int vertex, int col, int row, float[] position, float[] normal, float[] texture)
+     {
+     remainingVert--;
 
-    ////////////////////////////////////////////////////////////
-    // texture
+     float x= (float)col/mCols;
+     float y= (float)row/mRows;
 
-    offset=0;
-    bufferData = new float[TEX_DATA_SIZE*dataLength];
+     position[3*vertex  ] = x-0.5f;
+     position[3*vertex+1] = 0.5f-y;
+     position[3*vertex+2] = 0;
 
-    for(int i=0; i<dataLength; i++)
-      {
-      tmpx = ((float)(indexData[i]%xLength))/(xLength-1);
-      tmpy = ((float)(indexData[i]/xLength))/(yLength-1);
+     texture[2*vertex  ]  = x;
+     texture[2*vertex+1]  = y;
 
-      bufferData[offset++] = tmpx; // s=x
-      bufferData[offset++] = tmpy; // t=y
-      }
-    mGridTexture = ByteBuffer.allocateDirect(TEX_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
-    mGridTexture.put(bufferData).position(0);
+     normal[3*vertex  ]   = 0.0f;
+     normal[3*vertex+1]   = 0.0f;
+     normal[3*vertex+2]   = 1.0f;
 
-    //for(int g=0; g<dataLength; g++) Log.e("grid", "tex["+g+"]=("+bufferData[2*g]+","+bufferData[2*g+1]+")");
-    //Log.e("grid", "regWidth="+(2*mRegW)+" regHeight="+(2*mRegH)+" xLength="+xLength+" yLength="+yLength);
+     return vertex+1;
+     }
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    ////////////////////////////////////////////////////////////
-    // vertex positions
+   private int repeatLast(int vertex, float[] position, float[] normal, float[] texture)
+     {
+     remainingVert--;
 
-    offset=0;
-    bufferData= new float[POSITION_DATA_SIZE*dataLength];
+     //android.util.Log.e("BITMAP", "repeating last vertex!");
 
-    for(int i=0; i<dataLength; i++)
-      {
-      tmpx = ((float)(indexData[i]%xLength))/(xLength-1);
-      tmpy = ((float)(indexData[i]/xLength))/(yLength-1);
-      tmpz = 0;
+     if( vertex>0 )
+       {
+       position[3*vertex  ] = position[3*vertex-3];
+       position[3*vertex+1] = position[3*vertex-2];
+       position[3*vertex+2] = position[3*vertex-1];
 
-      bufferData[offset++] = (tmpx-0.5f); // x
-      bufferData[offset++] = (0.5f-tmpy); // y
-      bufferData[offset++] =        tmpz; // z
-      }
-    mGridPositions = ByteBuffer.allocateDirect(POSITION_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
-    mGridPositions.put(bufferData).position(0);
+       normal[3*vertex  ]   = normal[3*vertex-3];
+       normal[3*vertex+1]   = normal[3*vertex-2];
+       normal[3*vertex+2]   = normal[3*vertex-1];
+
+       texture[2*vertex  ]  = texture[2*vertex-2];
+       texture[2*vertex+1]  = texture[2*vertex-1];
 
-    //for(int g=0; g<dataLength; g++) android.util.Log.e("grid", "pos["+g+"]=("+bufferData[3*g]+","+bufferData[3*g+1]+")");
- 
-    ////////////////////////////////////////////////////////////
-    // normals
+       vertex++;
+       }
 
-    offset=0;
-    bufferData = new float[NORMAL_DATA_SIZE*dataLength];
+     return vertex;
+     }
 
-    for(int i=0; i<dataLength; i++)
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   private void buildGrid(float[] position, float[] normal, float[] texture)
+     {
+     boolean lastBlockIsNE = false;
+     boolean currentBlockIsNE;
+     int vertex = 0;
+
+     //android.util.Log.d("BITMAP", "buildGrid");
+
+     for(int row=0; row<mRows; row++)
+       {
+       for(int col=0; col<mCols; col++)
+         {
+         currentBlockIsNE = (2*row<=mRows-1)^(2*col<=mCols-1);
+
+         if( col==0 || (lastBlockIsNE^currentBlockIsNE) )
+           {
+           if( row!=0 && col==0 ) vertex = repeatLast(vertex,position,normal,texture);
+           vertex= addVertex( vertex, col, row+(currentBlockIsNE?0:1), position, normal, texture);
+           if( row!=0 && col==0 ) vertex = repeatLast(vertex,position,normal,texture);
+           if( lastBlockIsNE^currentBlockIsNE)  vertex = repeatLast(vertex,position,normal,texture);
+           vertex= addVertex( vertex, col, row+(currentBlockIsNE?1:0), position, normal, texture);
+           }
+         vertex= addVertex( vertex, col+1, row+(currentBlockIsNE?0:1), position, normal, texture);
+         vertex= addVertex( vertex, col+1, row+(currentBlockIsNE?1:0), position, normal, texture);
+
+         lastBlockIsNE = currentBlockIsNE;
+         }
+       }
+
+     //android.util.Log.d("BITMAP", "buildGrid done");
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Creates the underlying grid of vertices, normals and texture coords.
+ *
+ * @param cols Number of columns in the grid.
+ * @param rows Number of rows in the grid.
+ */
+   public DistortedBitmapGrid(int cols, int rows)
       {
-      bufferData[offset++] = 0.0f; // x
-      bufferData[offset++] = 0.0f; // y
-      bufferData[offset++] = 1.0f; // z
+      computeNumberOfVertices(cols,rows);
+
+      float[] positionData= new float[POSITION_DATA_SIZE*dataLength];
+      float[] normalData  = new float[NORMAL_DATA_SIZE  *dataLength];
+      float[] textureData = new float[TEX_DATA_SIZE     *dataLength];
+
+      buildGrid(positionData,normalData,textureData);
+
+      /*
+      android.util.Log.e("CUBES","dataLen="+dataLength+" vertex="+numVertices);
+      android.util.Log.d("CUBES", "position: "+debug(positionData,3) );
+      android.util.Log.d("CUBES", "normal: "  +debug(  normalData,3) );
+      android.util.Log.d("CUBES", "texture: " +debug( textureData,2) );
+      */
+
+      android.util.Log.d("BITMAP", "remainingVert " +remainingVert );
+
+      mGridPositions = ByteBuffer.allocateDirect(POSITION_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
+      mGridPositions.put(positionData).position(0);
+
+      mGridNormals = ByteBuffer.allocateDirect(NORMAL_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
+      mGridNormals.put(normalData).position(0);
+
+      mGridTexture = ByteBuffer.allocateDirect(TEX_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
+      mGridTexture.put(textureData).position(0);
       }
-    mGridNormals = ByteBuffer.allocateDirect(NORMAL_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();                                                        
-    mGridNormals.put(bufferData).position(0);
-    }
   }
\ No newline at end of file
