Project

General

Profile

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

library / src / main / java / org / distorted / library / GridCubes.java @ 3ef3364d

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