Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedCubesGrid.java @ 15873844

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