Project

General

Profile

Download (28.6 KB) Statistics
| Branch: | Revision:

library / src / main / java / org / distorted / library / DistortedCubesGrid.java @ 8d9da98a

1 d333eb6b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 6a06a912 Leszek Koltunski
package org.distorted.library;
21
22
import java.nio.ByteBuffer;
23
import java.nio.ByteOrder;
24
import java.util.ArrayList;
25
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27
28 e458a4ba Leszek Koltunski
class DistortedCubesGrid extends DistortedObjectGrid
29 6a06a912 Leszek Koltunski
   {
30 06d71892 Leszek Koltunski
   private static final float R = 0.0f;//0.2f;
31 6a06a912 Leszek Koltunski
   private static final float FRONTZ = 0.5f;
32
   private static final float BACKZ  =-0.5f;
33
   
34
   private static final int NORTH = 0;
35
   private static final int WEST  = 1;
36
   private static final int EAST  = 2;
37
   private static final int SOUTH = 3;
38 ce7f3833 Leszek Koltunski
39 6a06a912 Leszek Koltunski
   private static final boolean BACK  = true;
40
   private static final boolean FRONT = false;
41
   private static final boolean UPPER = false;
42
   private static final boolean LOWER = true;
43
   
44
   private static final float[] mNormalX = new float[4];
45
   private static final float[] mNormalY = new float[4];
46 ce7f3833 Leszek Koltunski
   private static final float[] mNormalZ = new float[4];
47
48 6a06a912 Leszek Koltunski
   private class Edge
49
     {
50
     final int side; 
51
     final int row;
52
     final int col;
53
     
54 06d71892 Leszek Koltunski
     Edge(int s, int r, int c)
55 6a06a912 Leszek Koltunski
       {
56
       side= s; 
57
       row = r;
58
       col = c;
59
       }
60 39cbf9dc Leszek Koltunski
     }
61 6a06a912 Leszek Koltunski
   
62
   private int mCols, mRows;
63
   private short[][] mCubes;
64 39cbf9dc Leszek Koltunski
   private ArrayList<Edge> mEdges = new ArrayList<>();
65 ce7f3833 Leszek Koltunski
66 84ee2a6a Leszek Koltunski
   private int remainingVert;
67 8d9da98a Leszek Koltunski
   private int mSideBends;
68
   private int mEdgeNum;
69 ce7f3833 Leszek Koltunski
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71
// a Block is split into two triangles along the NE-SW line iff it is in the top-right
72
// or bottom-left quadrant of the grid.
73
74
   private boolean isNE(int row,int col)
75
     {
76 29dd01c6 Leszek Koltunski
     return ( (2*row<mRows)^(2*col<mCols) );
77 ce7f3833 Leszek Koltunski
     }
78
79 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
80 84ee2a6a Leszek Koltunski
// return the number of vertices our grid will contain
81 6a06a912 Leszek Koltunski
82
   private int computeDataLength(boolean frontOnly)
83
      {
84 8d9da98a Leszek Koltunski
      int frontWalls=0, frontSegments=0, sideWalls=0, triangleShifts=0, windingShifts=0;
85 ce7f3833 Leszek Koltunski
      int shiftCol = (mCols-1)/2;
86
87
      boolean lastBlockIsNE=false;
88
      boolean thisBlockIsNE;        // the block we are currently looking at is split into
89
                                    // two triangles along the NE-SW line (rather than NW-SE)
90 29dd01c6 Leszek Koltunski
      for(int row=0; row<mRows; row++)
91 ce7f3833 Leszek Koltunski
         {
92 29dd01c6 Leszek Koltunski
         if( mCols>=2 && (mCubes[row][shiftCol]%2 == 1) && (mCubes[row][shiftCol+1]%2 == 1) ) triangleShifts++;
93 ce7f3833 Leszek Koltunski
94 29dd01c6 Leszek Koltunski
         for(int col=0; col<mCols; col++)
95 6a06a912 Leszek Koltunski
            {
96 29dd01c6 Leszek Koltunski
            if( mCubes[row][col]%2 == 1 )  // land
97 6a06a912 Leszek Koltunski
              {
98 29dd01c6 Leszek Koltunski
              thisBlockIsNE = isNE(row,col);
99 84ee2a6a Leszek Koltunski
              if( thisBlockIsNE^lastBlockIsNE ) windingShifts++;
100 ce7f3833 Leszek Koltunski
              lastBlockIsNE = thisBlockIsNE;
101 6a06a912 Leszek Koltunski
              frontWalls++;
102 29dd01c6 Leszek Koltunski
              if( col==mCols-1 || mCubes[row][col+1]%2 == 0 ) frontSegments++;
103 6a06a912 Leszek Koltunski
              }
104
              
105 29dd01c6 Leszek Koltunski
            if( (row==0 && mCubes[row][col]!=2) || (row!=0 && mCubes[row][col] != mCubes[row-1][col  ]) ) sideWalls++; // up
106
            if( (col==0 && mCubes[row][col]!=2) || (col!=0 && mCubes[row][col] != mCubes[row  ][col-1]) ) sideWalls++; // left
107
            if( row==mRows-1 && mCubes[row][col]!=2                                                     ) sideWalls++; // bottom
108
            if( col==mCols-1 && mCubes[row][col]!=2                                                     ) sideWalls++; // right
109 6a06a912 Leszek Koltunski
            }
110 ce7f3833 Leszek Koltunski
         }
111
112 84ee2a6a Leszek Koltunski
      int frontVert = 2*( frontWalls + 2*frontSegments - 1) +2*triangleShifts + windingShifts;
113 8d9da98a Leszek Koltunski
      int sideVert  = 2*( sideWalls + mSideBends + mEdgeNum -1);
114
      int firstWinding= (!frontOnly && (frontVert+1)%2==1 ) ? 1:0;
115 84ee2a6a Leszek Koltunski
      int dataL = frontOnly ? frontVert : (frontVert+1) +firstWinding+ (1+sideVert+1) + (1+frontVert);
116 8d9da98a Leszek Koltunski
/*
117
      android.util.Log.e("CUBES","triangleShifts="+triangleShifts+" windingShifts="+windingShifts);
118
      android.util.Log.e("CUBES","Winding1="+firstWinding+" frontVert="+frontVert+" sideVert="+sideVert);
119
      android.util.Log.e("CUBES", "frontW="+frontWalls+" fSegments="+frontSegments+" sWalls="+sideWalls+" sSegments="+mEdgeNum+" sideBends="+mSideBends+" dataLen="+dataL );
120
*/
121 6a06a912 Leszek Koltunski
      return dataL<0 ? 0:dataL;
122
      }
123
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125
/*
126
   private static String debug(short[] val)
127
     {
128 ce7f3833 Leszek Koltunski
     String ret="";j
129 6a06a912 Leszek Koltunski
     
130
     for(int i=0; i<val.length; i++) ret+=(" "+val[i]); 
131
     
132
     return ret;
133
     }
134
*/
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136
/*
137
   private static String debug(float[] val, int stop)
138
     {
139
     String ret="";
140
141
     for(int i=0; i<val.length; i++) 
142
        {
143
        if( i%stop==0 ) ret+="\n";
144
        ret+=(" "+val[i]);
145
        }
146
147
     return ret;
148
     }
149
*/  
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151
/*
152
   private static String debug(Edge e)
153
     {
154
     String d = "";
155
     
156
     switch(e.side)
157
       {
158
       case NORTH: d+="NORTH "; break;
159
       case SOUTH: d+="SOUTH "; break;
160
       case WEST : d+="WEST  "; break;
161
       case EAST : d+="EAST  "; break;
162
       }
163
     
164
     d+=("("+e.row+","+e.col+")");
165
     
166
     return d;
167
     }   
168 8d9da98a Leszek Koltunski
*/
169 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
170 0729bc41 Leszek Koltunski
// desc is guaranteed to be padded with 0s in the end (DistortedCubes constructor does it)
171 6a06a912 Leszek Koltunski
172 2e96ee72 Leszek Koltunski
   private void prepareDataStructures(int cols, String desc, boolean frontOnly)
173 6a06a912 Leszek Koltunski
     {
174
     mRows     =0;
175
     mCols     =0;
176
     dataLength=0;
177
     
178 0729bc41 Leszek Koltunski
     if( cols>0 && desc.contains("1") )
179 6a06a912 Leszek Koltunski
       {
180 0729bc41 Leszek Koltunski
       mCols = cols;
181
       mRows = desc.length()/cols;
182 6a06a912 Leszek Koltunski
183 0729bc41 Leszek Koltunski
       mCubes = new short[mRows][mCols];
184 6a06a912 Leszek Koltunski
       
185 0729bc41 Leszek Koltunski
       for(int j=0; j<mCols; j++)
186
         for(int i=0; i<mRows; i++)
187
           mCubes[i][j] = (short)(desc.charAt(i*mCols+j) == '1' ? 1:0);
188 6a06a912 Leszek Koltunski
       
189 0729bc41 Leszek Koltunski
       markRegions();
190
       dataLength = computeDataLength(frontOnly);
191 84ee2a6a Leszek Koltunski
192
       remainingVert = dataLength;
193 6a06a912 Leszek Koltunski
       }
194
     }
195 665e2c45 Leszek Koltunski
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197
// full grid
198
199
   private void prepareDataStructures(int cols, int rows, boolean frontOnly)
200
     {
201
     mRows     =rows;
202
     mCols     =cols;
203
     dataLength=   0;
204
205
     if( cols>0 && rows>0 )
206
       {
207
       mCubes = new short[mRows][mCols];
208
209
       for(int j=0; j<mCols; j++)
210
         for(int i=0; i<mRows; i++)
211
           mCubes[i][j] = (short)1;
212
213
       markRegions();
214
       dataLength = computeDataLength(frontOnly);
215
216
       remainingVert = dataLength;
217
       }
218
     }
219
220 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
221
// Mark all the 'regions' of our grid  - i.e. separate pieces of 'land' (connected blocks that will 
222
// be rendered) and 'water' (connected holes in between) with integers. Each connected block of land
223
// gets a unique odd integer, each connected block of water a unique even integer.
224
//
225
// Water on the edges of the grid is also considered connected to itself!   
226
//   
227
// This function also creates a list of 'Edges'. Each Edge is a data structure from which later on we
228 2e96ee72 Leszek Koltunski
// will start building the side walls of each connected block of land (and sides of holes of water
229 8d9da98a Leszek Koltunski
// inside). Each Edge needs to point from Land to Water (thus the '(SOUTH,i-1,j)' below) - otherwise
230
// later on setting up normal vectors wouldn't work.
231 6a06a912 Leszek Koltunski
   
232
   private void markRegions()
233
     {
234
     int i, j, numWater=1, numLand=0;
235
     
236
     for(i=0; i<mRows;i++) if( mCubes[      i][      0]==0 ) markRegion((short)2,      i,       0);
237
     for(i=0; i<mRows;i++) if( mCubes[      i][mCols-1]==0 ) markRegion((short)2,      i, mCols-1);
238
     for(i=0; i<mCols;i++) if( mCubes[0      ][      i]==0 ) markRegion((short)2,      0,       i);
239
     for(i=0; i<mCols;i++) if( mCubes[mRows-1][      i]==0 ) markRegion((short)2,mRows-1,       i);
240
           
241
     for(i=0; i<mRows; i++)
242
        for(j=0; j<mCols; j++)
243
           {
244 8d9da98a Leszek Koltunski
           if( mCubes[i][j] == 0 ) { numWater++; markRegion( (short)(2*numWater ),i,j); mEdges.add(new Edge(SOUTH,i-1,j)); }
245
           if( mCubes[i][j] == 1 ) { numLand ++; markRegion( (short)(2*numLand+1),i,j); mEdges.add(new Edge(NORTH,i  ,j)); }
246 6a06a912 Leszek Koltunski
           }
247
     
248 8d9da98a Leszek Koltunski
     // now we potentially need to kick out some Edges . Otherwise the following does not work:
249 6a06a912 Leszek Koltunski
     //
250
     // 0 1 0
251
     // 1 0 1
252
     // 0 1 0
253
     
254 8d9da98a Leszek Koltunski
     mEdgeNum= mEdges.size();
255
     int initCol, initRow, initSide, lastSide;
256
     Edge e1,e2;
257 6a06a912 Leszek Koltunski
     
258 8d9da98a Leszek Koltunski
     for(i=0; i<mEdgeNum; i++)
259 6a06a912 Leszek Koltunski
       {
260 8d9da98a Leszek Koltunski
       e1 = mEdges.get(i);
261
       initRow= e1.row;
262
       initCol= e1.col;
263
       initSide=e1.side;
264
265
       do
266 6a06a912 Leszek Koltunski
         {
267 8d9da98a Leszek Koltunski
         //android.util.Log.d("CUBES", "checking edge "+debug(e1));
268
269
         if( e1.side==NORTH || e1.side==SOUTH )
270 6a06a912 Leszek Koltunski
           {
271 8d9da98a Leszek Koltunski
           for(j=i+1;j<mEdgeNum;j++)
272 6a06a912 Leszek Koltunski
             {
273 8d9da98a Leszek Koltunski
             e2 = mEdges.get(j);
274
275
             if( e2.side==e1.side && e2.row==e1.row && e2.col==e1.col )
276
               {
277
               mEdges.remove(j);
278
               mEdgeNum--;
279
               j--;
280
281
               //android.util.Log.e("CUBES", "removing edge "+debug(e2));
282
               }
283 6a06a912 Leszek Koltunski
             }
284
           }
285 8d9da98a Leszek Koltunski
286
         lastSide = e1.side;
287
         e1 = getNextEdge(e1);
288
         if( e1.side!=lastSide ) mSideBends++;
289 6a06a912 Leszek Koltunski
         }
290 8d9da98a Leszek Koltunski
       while( e1.col!=initCol || e1.row!=initRow || e1.side!=initSide );
291 6a06a912 Leszek Koltunski
       }
292
     }
293
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295
// when calling, make sure that newVal != val
296
   
297
   private void markRegion(short newVal, int row, int col)
298
     {
299
     short val = mCubes[row][col];
300
     mCubes[row][col] = newVal;
301
     
302
     if( row>0       && mCubes[row-1][col  ]==val ) markRegion(newVal, row-1, col  );
303
     if( row<mRows-1 && mCubes[row+1][col  ]==val ) markRegion(newVal, row+1, col  );
304
     if( col>0       && mCubes[row  ][col-1]==val ) markRegion(newVal, row  , col-1);
305
     if( col<mCols-1 && mCubes[row  ][col+1]==val ) markRegion(newVal, row  , col+1);
306
     }
307
   
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309
   
310 ce7f3833 Leszek Koltunski
   private void createNormals(boolean front, int row, int col)
311 6a06a912 Leszek Koltunski
     {
312
     int td,lr; 
313
      
314 2e96ee72 Leszek Koltunski
     int nw = (col>0       && row>0      ) ? (mCubes[row-1][col-1]%2) : 0;
315
     int w  = (col>0                     ) ? (mCubes[row  ][col-1]%2) : 0;
316
     int n  = (               row>0      ) ? (mCubes[row-1][col  ]%2) : 0;
317
     int c  =                                (mCubes[row  ][col  ]%2);
318
     int sw = (col>0       && row<mRows-1) ? (mCubes[row+1][col-1]%2) : 0;
319 6a06a912 Leszek Koltunski
     int s  = (               row<mRows-1) ? (mCubes[row+1][col  ]%2) : 0;
320
     int ne = (col<mCols-1 && row>0      ) ? (mCubes[row-1][col+1]%2) : 0;
321
     int e  = (col<mCols-1               ) ? (mCubes[row  ][col+1]%2) : 0;
322
     int se = (col<mCols-1 && row<mRows-1) ? (mCubes[row+1][col+1]%2) : 0;
323 ce7f3833 Leszek Koltunski
324
     if(front)
325
       {
326
       mNormalZ[0] = 1.0f;
327
       mNormalZ[1] = 1.0f;
328
       mNormalZ[2] = 1.0f;
329
       mNormalZ[3] = 1.0f;
330
       }
331
     else
332
       {
333
       mNormalZ[0] =-1.0f;
334
       mNormalZ[1] =-1.0f;
335
       mNormalZ[2] =-1.0f;
336
       mNormalZ[3] =-1.0f;
337
       }
338
339 6a06a912 Leszek Koltunski
     td = nw+n-w-c;
340
     lr = c+n-w-nw;
341
     if( td<0 ) td=-1;
342
     if( td>0 ) td= 1;
343
     if( lr<0 ) lr=-1;
344
     if( lr>0 ) lr= 1;
345
     mNormalX[0] = lr*R;
346
     mNormalY[0] = td*R;
347
     
348
     td = w+c-sw-s;
349
     lr = c+s-w-sw;
350
     if( td<0 ) td=-1;
351
     if( td>0 ) td= 1;
352
     if( lr<0 ) lr=-1;
353
     if( lr>0 ) lr= 1;
354
     mNormalX[1] = lr*R;
355
     mNormalY[1] = td*R;
356
     
357
     td = n+ne-c-e;
358
     lr = e+ne-c-n;
359
     if( td<0 ) td=-1;
360
     if( td>0 ) td= 1;
361
     if( lr<0 ) lr=-1;
362
     if( lr>0 ) lr= 1;
363
     mNormalX[2] = lr*R;
364
     mNormalY[2] = td*R;
365
     
366
     td = c+e-s-se;
367
     lr = e+se-c-s;
368
     if( td<0 ) td=-1;
369
     if( td>0 ) td= 1;
370
     if( lr<0 ) lr=-1;
371
     if( lr>0 ) lr= 1;
372
     mNormalX[3] = lr*R;
373
     mNormalY[3] = td*R;
374
     /*
375 2e96ee72 Leszek Koltunski
     android.util.Log.d("CUBES", "row="+row+" col="+col);
376
     android.util.Log.d("CUBES", mNormalX[0]+" "+mNormalY[0]);
377
     android.util.Log.d("CUBES", mNormalX[1]+" "+mNormalY[1]);
378
     android.util.Log.d("CUBES", mNormalX[2]+" "+mNormalY[2]);
379
     android.util.Log.d("CUBES", mNormalX[3]+" "+mNormalY[3]);
380 6a06a912 Leszek Koltunski
     */
381
     }
382
   
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384 ce7f3833 Leszek Koltunski
385 e5d9b235 Leszek Koltunski
   private int addFrontVertex(int vertex, int index, float vectZ, int col, int row, float[] position, float[] normal, float[] texture)
386 ce7f3833 Leszek Koltunski
     {
387 84ee2a6a Leszek Koltunski
     remainingVert--;
388 15873844 Leszek Koltunski
389 e5d9b235 Leszek Koltunski
     float x = (float)col/mCols;
390
     float y = (float)row/mRows;
391 ce7f3833 Leszek Koltunski
392 15873844 Leszek Koltunski
     position[3*vertex  ] = x-0.5f;
393
     position[3*vertex+1] = 0.5f-y;
394
     position[3*vertex+2] = vectZ;
395
     normal[3*vertex  ]   = mNormalX[index];
396
     normal[3*vertex+1]   = mNormalY[index];
397
     normal[3*vertex+2]   = mNormalZ[index];
398
     texture[2*vertex  ]  = x;
399 985ea9c5 Leszek Koltunski
     texture[2*vertex+1]  = 1.0f-y;
400 15873844 Leszek Koltunski
401
     return vertex+1;
402 ce7f3833 Leszek Koltunski
     }
403
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405
406 6a06a912 Leszek Koltunski
   private int buildFrontBackGrid(boolean front, int vertex, float[] position, float[] normal, float[] texture)
407
     {
408
     short last, current;
409 ce7f3833 Leszek Koltunski
     boolean seenLand=false;
410
     boolean lastBlockIsNE = false;
411
     boolean currentBlockIsNE;
412
     float vectZ = front?FRONTZ:BACKZ;
413
414 84ee2a6a Leszek Koltunski
     //android.util.Log.d("CUBES", "buildFrontBack");
415
416 e5d9b235 Leszek Koltunski
     for(int row=0; row<mRows; row++)
417 6a06a912 Leszek Koltunski
       {
418
       last =0;
419
         
420 e5d9b235 Leszek Koltunski
       for(int col=0; col<mCols; col++)
421 6a06a912 Leszek Koltunski
         {
422 e5d9b235 Leszek Koltunski
         current = mCubes[row][col];
423 ce7f3833 Leszek Koltunski
424 6a06a912 Leszek Koltunski
         if( current%2 == 1 )
425
           {
426 e5d9b235 Leszek Koltunski
           currentBlockIsNE = isNE(row,col);
427 84ee2a6a Leszek Koltunski
428
           if( !seenLand && !front && ((vertex%2==1)^currentBlockIsNE) )
429
             {
430
             //android.util.Log.d("CUBES","repeating winding2 vertex");
431
432
             vertex = repeatLast(vertex,position,normal,texture);
433
             }
434
435 e5d9b235 Leszek Koltunski
           createNormals(front,row,col);
436 ce7f3833 Leszek Koltunski
437 e5d9b235 Leszek Koltunski
           if( currentBlockIsNE )
438 6a06a912 Leszek Koltunski
             {
439 e5d9b235 Leszek Koltunski
             if( (last!=current) || !lastBlockIsNE )
440
               {
441
               if( seenLand  && (last != current) ) vertex = repeatLast(vertex,position,normal,texture);
442
               vertex= addFrontVertex( vertex, 0, vectZ, col, row, position, normal, texture);
443
               if( seenLand  && (last != current) ) vertex = repeatLast(vertex,position,normal,texture);
444
               if( !lastBlockIsNE || (!front && !seenLand) ) vertex = repeatLast(vertex,position,normal,texture);
445
               vertex= addFrontVertex( vertex, 1, vectZ, col, row+1, position, normal, texture);
446
               }
447
             vertex= addFrontVertex( vertex, 2, vectZ, col+1, row, position, normal, texture);
448
             vertex= addFrontVertex( vertex, 3, vectZ, col+1, row+1, position, normal, texture);
449
             }
450
           else
451
             {
452
             if( (last!=current) || lastBlockIsNE )
453
               {
454
               if( seenLand  && (last != current) ) vertex = repeatLast(vertex,position,normal,texture);
455
               vertex= addFrontVertex( vertex, 1, vectZ, col, row+1, position, normal, texture);
456
               if( seenLand  && (last != current) ) vertex = repeatLast(vertex,position,normal,texture);
457
               if( lastBlockIsNE || (!front && !seenLand) ) vertex = repeatLast(vertex,position,normal,texture);
458
               vertex= addFrontVertex( vertex, 0, vectZ, col, row, position, normal, texture);
459
               }
460
             vertex= addFrontVertex( vertex, 3, vectZ, col+1, row+1, position, normal, texture);
461
             vertex= addFrontVertex( vertex, 2, vectZ, col+1, row  , position, normal, texture);
462 6a06a912 Leszek Koltunski
             }
463 ce7f3833 Leszek Koltunski
464
           seenLand = true;
465
           lastBlockIsNE = currentBlockIsNE;
466 6a06a912 Leszek Koltunski
           }
467
            
468
         last = current;
469
         }
470
       }
471
     
472
     return vertex;
473
     }
474
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476
477
   private int repeatLast(int vertex, float[] position, float[] normal, float[] texture)
478
     {
479 84ee2a6a Leszek Koltunski
     //android.util.Log.e("CUBES", "repeating last vertex!");
480
481 6a06a912 Leszek Koltunski
     if( vertex>0 )
482
       {
483 e5d9b235 Leszek Koltunski
       remainingVert--;
484
485 39cbf9dc Leszek Koltunski
       position[3*vertex  ] = position[3*vertex-3];
486 6a06a912 Leszek Koltunski
       position[3*vertex+1] = position[3*vertex-2];
487
       position[3*vertex+2] = position[3*vertex-1];
488
489 39cbf9dc Leszek Koltunski
       normal[3*vertex  ]   = normal[3*vertex-3];
490 6a06a912 Leszek Koltunski
       normal[3*vertex+1]   = normal[3*vertex-2];
491
       normal[3*vertex+2]   = normal[3*vertex-1];
492
493 39cbf9dc Leszek Koltunski
       texture[2*vertex  ]  = texture[2*vertex-2];
494 6a06a912 Leszek Koltunski
       texture[2*vertex+1]  = texture[2*vertex-1];
495
         
496
       vertex++;     
497
       }
498
     
499
     return vertex;
500
     }
501
   
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503
504
   private int buildSideGrid(int vertex, float[] position, float[] normal, float[] texture)
505
     {
506 84ee2a6a Leszek Koltunski
     //android.util.Log.d("CUBES", "buildSide");
507 ce7f3833 Leszek Koltunski
508 8d9da98a Leszek Koltunski
     for(int i=0; i<mEdgeNum; i++)
509 6a06a912 Leszek Koltunski
       {
510
       vertex = buildIthSide(mEdges.get(i), vertex, position, normal, texture);  
511
       } 
512
      
513
     return vertex;
514
     }
515
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517
518
   private int buildIthSide(Edge curr, int vertex, float[] position, float[] normal, float[] texture)
519
     {
520
     Edge prev; 
521
     
522
     if( curr.side==NORTH ) // water outside
523
       {
524
       prev = new Edge(WEST,curr.row,curr.col);
525
       }
526
     else                   // land outside; we need to move forward one link because we are going in opposite direction and we need to start from a bend.
527
       {
528
       prev = curr;
529
       curr = new Edge(EAST,curr.row+1,curr.col-1);
530
       }
531
     
532
     int col = curr.col;
533
     int row = curr.row;
534
     int side= curr.side;  
535
     Edge next = getNextEdge(curr);
536
     
537 84ee2a6a Leszek Koltunski
     addSideVertex(curr,BACK,LOWER,prev.side,vertex,position,normal,texture);
538 6a06a912 Leszek Koltunski
     vertex++;
539
     
540
     do
541
       {
542
       if( prev.side!=curr.side )
543
         {
544 84ee2a6a Leszek Koltunski
         addSideVertex(curr,BACK,LOWER,prev.side,vertex,position,normal,texture);
545 6a06a912 Leszek Koltunski
         vertex++;
546 84ee2a6a Leszek Koltunski
         addSideVertex(curr,BACK,UPPER,prev.side,vertex,position,normal,texture);
547 6a06a912 Leszek Koltunski
         vertex++;
548
         }
549
       
550 84ee2a6a Leszek Koltunski
       addSideVertex(curr,FRONT,LOWER,next.side,vertex,position,normal,texture);
551 6a06a912 Leszek Koltunski
       vertex++;
552 84ee2a6a Leszek Koltunski
       addSideVertex(curr,FRONT,UPPER,next.side,vertex,position,normal,texture);
553 6a06a912 Leszek Koltunski
       vertex++;
554
       
555
       prev = curr;
556
       curr = next; 
557
       next = getNextEdge(curr);
558
       }
559
     while( curr.col!=col || curr.row!=row || curr.side!=side );
560
     
561
     vertex = repeatLast(vertex,position,normal,texture);
562
     
563
     return vertex;
564
     }
565
566
///////////////////////////////////////////////////////////////////////////////////////////////////
567
568
   private Edge getNextEdge(Edge curr)
569
     {
570
     int col = curr.col;
571
     int row = curr.row;
572
      
573
     //android.util.Log.e("CUBES", "row="+row+" col="+col+" mRows="+mRows+" mCols="+mCols);
574
                       
575
     switch(curr.side) 
576
       {
577
       case NORTH: if( col==mCols-1 ) 
578
                     return new Edge(EAST,row,col);
579
                   if( row>0 && mCubes[row-1][col+1]==mCubes[row][col] )
580
                     return new Edge(WEST,row-1,col+1);
581
                   if( mCubes[row][col+1]==mCubes[row][col] )
582
                     return new Edge(NORTH,row,col+1);
583
                   else  
584
                     return new Edge(EAST,row,col);
585
                   
586
       case SOUTH: if( col==0 ) 
587
                     return new Edge(WEST,row,col);
588
                   if( (row<mRows-1) && mCubes[row+1][col-1]==mCubes[row][col] )
589
                     return new Edge(EAST,row+1,col-1); 
590
                   if( mCubes[row][col-1]==mCubes[row][col] )
591
                     return new Edge(SOUTH,row,col-1);
592
                   else
593
                     return new Edge(WEST,row,col); 
594
                     
595
       case EAST : if( row==mRows-1 ) 
596
                     return new Edge(SOUTH,row,col);
597
                   if( (col<mCols-1) && mCubes[row+1][col+1]==mCubes[row][col] )
598
                     return new Edge(NORTH,row+1,col+1);
599
                   if( mCubes[row+1][col]==mCubes[row][col] )
600
                     return new Edge(EAST,row+1,col);
601
                   else 
602
                     return new Edge(SOUTH,row,col);
603
                   
604 8d9da98a Leszek Koltunski
       default   : if( row==0 )
605 6a06a912 Leszek Koltunski
                     return new Edge(NORTH,row,col);
606
                   if( col>0 && mCubes[row-1][col-1]==mCubes[row][col] )
607
                     return new Edge(SOUTH,row-1,col-1);
608
                   if( mCubes[row-1][col]==mCubes[row][col] )
609
                     return new Edge(WEST,row-1,col);
610
                   else
611
                     return new Edge(NORTH,row,col);     
612
       }
613
     }
614
615
///////////////////////////////////////////////////////////////////////////////////////////////////
616
   
617 84ee2a6a Leszek Koltunski
   private void addSideVertex(Edge curr, boolean back, boolean lower,int side, int vertex, float[] position, float[] normal, float[] texture)
618 6a06a912 Leszek Koltunski
     {
619 84ee2a6a Leszek Koltunski
     //android.util.Log.e("CUBES", "adding Side vertex!");
620
621
     remainingVert--;
622
623 985ea9c5 Leszek Koltunski
     float x, y;
624
625 6a06a912 Leszek Koltunski
     switch(curr.side)
626
       {
627 985ea9c5 Leszek Koltunski
       case NORTH: x = (float)(back ? (curr.col  ):(curr.col+1))/mCols;
628
629
                   position[3*vertex  ] = x - 0.5f;
630
                   position[3*vertex+1] = 0.5f - (float)curr.row/mRows;
631 6a06a912 Leszek Koltunski
                   position[3*vertex+2] = lower ? BACKZ : FRONTZ;
632
633 39cbf9dc Leszek Koltunski
                   normal[3*vertex  ]   = side==NORTH ? 0.0f : (side==WEST?-R:R);
634 6a06a912 Leszek Koltunski
                   normal[3*vertex+1]   = 1.0f;
635
                   normal[3*vertex+2]   = lower ? -R:R;
636
637 985ea9c5 Leszek Koltunski
                   texture[2*vertex  ]  = x;
638
                   texture[2*vertex+1]  = 1.0f-(float)(lower? (curr.row-1):(curr.row  ))/mRows;
639 6a06a912 Leszek Koltunski
                   break;
640 985ea9c5 Leszek Koltunski
       case SOUTH: x = (float)(back ? (curr.col+1):(curr.col  ))/mCols;
641
642
                   position[3*vertex  ] = x - 0.5f;
643
                   position[3*vertex+1] = 0.5f - (float)(curr.row+1)/mRows;
644 6a06a912 Leszek Koltunski
                   position[3*vertex+2] = lower ? BACKZ : FRONTZ;  
645
            
646 39cbf9dc Leszek Koltunski
                   normal[3*vertex  ]   = side==SOUTH ? 0.0f: (side==EAST?-R:R);
647 6a06a912 Leszek Koltunski
                   normal[3*vertex+1]   =-1.0f;
648
                   normal[3*vertex+2]   = lower ? -R:R;
649
650 985ea9c5 Leszek Koltunski
                   texture[2*vertex  ]  = x;
651
                   texture[2*vertex+1]  = 1.0f-(float)(lower? (curr.row+2):(curr.row+1))/mRows;
652 6a06a912 Leszek Koltunski
                   break;
653 985ea9c5 Leszek Koltunski
       case WEST : y = (float)(back  ? (curr.row+1):(curr.row))/mRows;
654
655
                   position[3*vertex  ] = (float)curr.col/mCols -0.5f;
656
                   position[3*vertex+1] = 0.5f - y;
657 6a06a912 Leszek Koltunski
                   position[3*vertex+2] = lower ? BACKZ : FRONTZ;
658
659 39cbf9dc Leszek Koltunski
                   normal[3*vertex  ]   =-1.0f;
660 6a06a912 Leszek Koltunski
                   normal[3*vertex+1]   = side==WEST ? 0.0f : (side==NORTH?-R:R);
661
                   normal[3*vertex+2]   = lower ? -R:R;
662
 
663 39cbf9dc Leszek Koltunski
                   texture[2*vertex  ]  = (float)(lower ? (curr.col-1):(curr.col  ))/mCols;
664 985ea9c5 Leszek Koltunski
                   texture[2*vertex+1]  = 1.0f - y;
665 6a06a912 Leszek Koltunski
                   break;
666 985ea9c5 Leszek Koltunski
       case EAST : y = (float)(back  ? (curr.row):(curr.row+1))/mRows;
667
668
                   position[3*vertex  ] = (float)(curr.col+1)/mCols -0.5f;
669
                   position[3*vertex+1] = 0.5f - y;
670 6a06a912 Leszek Koltunski
                   position[3*vertex+2] = lower ? BACKZ : FRONTZ;
671
672 39cbf9dc Leszek Koltunski
                   normal[3*vertex  ]   = 1.0f;
673 6a06a912 Leszek Koltunski
                   normal[3*vertex+1]   = side==EAST ? 0.0f : (side==SOUTH?-R:R);
674
                   normal[3*vertex+2]   = lower ? -R:R; 
675
676 39cbf9dc Leszek Koltunski
                   texture[2*vertex  ]  = (float)(lower ? (curr.col+2):(curr.col+1))/mCols;
677 985ea9c5 Leszek Koltunski
                   texture[2*vertex+1]  = 1.0f - y;
678 6a06a912 Leszek Koltunski
                   break;
679
       }
680
     
681 39cbf9dc Leszek Koltunski
     if(texture[2*vertex  ]>1.0f) texture[2*vertex  ] =2.0f-texture[2*vertex  ];
682
     if(texture[2*vertex  ]<0.0f) texture[2*vertex  ] =    -texture[2*vertex  ];
683 6a06a912 Leszek Koltunski
     if(texture[2*vertex+1]>1.0f) texture[2*vertex+1] =2.0f-texture[2*vertex+1];
684
     if(texture[2*vertex+1]<0.0f) texture[2*vertex+1] =    -texture[2*vertex+1];
685
     }
686
687 665e2c45 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
688
689
   private void build(boolean frontOnly)
690
     {
691
     int numVertices=0;
692
     float[] positionData= new float[POSITION_DATA_SIZE*dataLength];
693
     float[] normalData  = new float[NORMAL_DATA_SIZE  *dataLength];
694
     float[] textureData = new float[TEX_DATA_SIZE     *dataLength];
695
696
     //android.util.Log.d("CUBES","building front grid...");
697
698
     numVertices = buildFrontBackGrid(true, numVertices,positionData,normalData,textureData);
699
700
     if( !frontOnly )
701
       {
702
       numVertices = repeatLast(numVertices,positionData,normalData,textureData);
703
       if( numVertices%2==1 )
704
         {
705
         //android.util.Log.d("CUBES","repeating winding1 vertex");
706
707
         numVertices = repeatLast(numVertices,positionData,normalData,textureData);
708
         }
709
710
       //android.util.Log.d("CUBES","building side grid...");
711
712
       numVertices = buildSideGrid (numVertices,positionData,normalData,textureData);
713
714
       //android.util.Log.d("CUBES","building back grid...");
715
716
       numVertices = buildFrontBackGrid (false,numVertices,positionData,normalData,textureData);
717
       }
718
719
     /*
720
     android.util.Log.e("CUBES","dataLen="+dataLength+" vertex="+numVertices);
721
     android.util.Log.d("CUBES", "position: "+debug(positionData,3) );
722
     android.util.Log.d("CUBES", "normal: "  +debug(  normalData,3) );
723
     android.util.Log.d("CUBES", "texture: " +debug( textureData,2) );
724
     */
725 16d8b8f3 Leszek Koltunski
726 8d9da98a Leszek Koltunski
     mEdges.clear();
727
     mEdges = null;
728
     mCubes = null;
729
730 16d8b8f3 Leszek Koltunski
     if( remainingVert!=0 )
731
       android.util.Log.d("CUBES", "remainingVert " +remainingVert );
732 665e2c45 Leszek Koltunski
733
     mGridPositions = ByteBuffer.allocateDirect(POSITION_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
734
     mGridPositions.put(positionData).position(0);
735
736
     mGridNormals = ByteBuffer.allocateDirect(NORMAL_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
737
     mGridNormals.put(normalData).position(0);
738
739
     mGridTexture = ByteBuffer.allocateDirect(TEX_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
740
     mGridTexture.put(textureData).position(0);
741
     }
742
743 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
744
// PUBLIC API
745
///////////////////////////////////////////////////////////////////////////////////////////////////
746
/**
747
 * Creates the underlying grid of vertices, normals, texture coords and colors.
748
 *    
749 39cbf9dc Leszek Koltunski
 * @param cols      See {@link DistortedCubes#DistortedCubes(int,String,int,boolean)}
750
 * @param desc      See {@link DistortedCubes#DistortedCubes(int,String,int,boolean)}
751
 * @param frontOnly See {@link DistortedCubes#DistortedCubes(int,String,int,boolean)}
752 6a06a912 Leszek Koltunski
 */
753 665e2c45 Leszek Koltunski
   DistortedCubesGrid(int cols, String desc, boolean frontOnly)
754 6a06a912 Leszek Koltunski
      {
755 2e96ee72 Leszek Koltunski
      prepareDataStructures(cols,desc,frontOnly);
756 665e2c45 Leszek Koltunski
      build(frontOnly);
757
      }
758 6a06a912 Leszek Koltunski
759 665e2c45 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
760
/**
761
 * Creates a full, hole-less underlying grid of vertices, normals, texture coords and colors.
762
 *
763
 * @param cols      See {@link DistortedCubes#DistortedCubes(int,int,int,boolean)}
764
 * @param rows      See {@link DistortedCubes#DistortedCubes(int,int,int,boolean)}
765
 * @param frontOnly See {@link DistortedCubes#DistortedCubes(int,int,int,boolean)}
766
 */
767
   DistortedCubesGrid(int cols, int rows, boolean frontOnly)
768
      {
769
      prepareDataStructures(cols,rows,frontOnly);
770
      build(frontOnly);
771 6a06a912 Leszek Koltunski
      }
772
   }
773
///////////////////////////////////////////////////////////////////////////////////////////////////