Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedCubesGrid.java @ 77fcb24d

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