Project

General

Profile

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

library / src / main / java / org / distorted / library / GridCubes.java @ 6a06a912

1
package org.distorted.library;
2

    
3
import java.nio.ByteBuffer;
4
import java.nio.ByteOrder;
5
import java.util.ArrayList;
6

    
7
///////////////////////////////////////////////////////////////////////////////////////////////////
8

    
9
class GridCubes extends GridObject
10
   {
11
   private static final float R = 0.2f;
12
   private static final float FRONTZ = 0.5f;
13
   private static final float BACKZ  =-0.5f;
14
   
15
   private static final int NORTH = 0;
16
   private static final int WEST  = 1;
17
   private static final int EAST  = 2;
18
   private static final int SOUTH = 3;
19
   
20
   private static final boolean BACK  = true;
21
   private static final boolean FRONT = false;
22
   private static final boolean UPPER = false;
23
   private static final boolean LOWER = true;
24
   
25
   private static final float[] mNormalX = new float[4];
26
   private static final float[] mNormalY = new float[4];
27
   
28
   private class Edge
29
     {
30
     final int side; 
31
     final int row;
32
     final int col;
33
     
34
     public Edge(int s, int r, int c)
35
       {
36
       side= s; 
37
       row = r;
38
       col = c;
39
       }
40
     };
41
   
42
   private int frontVert, sideVert;
43
   private int mCols, mRows;
44
   private short[][] mCubes;
45
   private ArrayList<Edge> mEdges = new ArrayList<Edge>();
46
   
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48

    
49
   private int computeDataLength(boolean frontOnly)
50
      {
51
      int frontWalls=0, frontSegments=0, sideWalls=0, sideBends=0;
52
      
53
      for(int i=0; i<mRows; i++)
54
         for(int j=0; j<mCols; j++)
55
            {
56
            if( mCubes[i][j]%2 == 1 )  // land
57
              {
58
              frontWalls++;
59
              if( j==mCols-1 || mCubes[i][j+1]%2 == 0 ) frontSegments++;
60
              }
61
              
62
            if( (i==0 && mCubes[i][j]!=2) || (i!=0 && mCubes[i][j] != mCubes[i-1][j  ]) ) sideWalls++; // up
63
            if( (j==0 && mCubes[i][j]!=2) || (j!=0 && mCubes[i][j] != mCubes[i  ][j-1]) ) sideWalls++; // left
64
            if( i==mRows-1 && mCubes[i][j]!=2                                           ) sideWalls++; // bottom
65
            if( j==mCols-1 && mCubes[i][j]!=2                                           ) sideWalls++; // right
66
            }
67

    
68
      int edges= mEdges.size();
69
      
70
      for(int i=0; i<edges; i++) 
71
        {
72
        Edge curr = mEdges.get(i);
73
        Edge next = getNextEdge(curr);
74
        int startX = curr.col;
75
        int startY = curr.row;
76
        int startS = curr.side;
77
        
78
        do
79
          {
80
          if( next.side != curr.side ) sideBends++; 
81
          curr  = next; 
82
          next = getNextEdge(curr);
83
          }
84
        while( curr.col!=startX || curr.row!=startY || curr.side!=startS );
85
        }
86
      
87
      frontVert = 2*( frontWalls + 2*frontSegments - 1);
88
      sideVert  = 2*( sideWalls + sideBends + edges -1);
89
      
90
      int dataL = frontOnly ? frontVert : (frontVert+1) + (1+sideVert+1) + (1+frontVert);
91
      
92
      android.util.Log.e("CUBES","frontVert="+frontVert+" sideVert="+sideVert);
93
      android.util.Log.e("CUBES", "frontW="+frontWalls+" fSegments="+frontSegments+" sWalls="+sideWalls+" sSegments="+edges+" sideBends="+sideBends+" dataLen="+dataL );
94
      
95
      return dataL<0 ? 0:dataL;
96
      }
97

    
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99
/*
100
   private static String debug(short[] val)
101
     {
102
     String ret="";
103
     
104
     for(int i=0; i<val.length; i++) ret+=(" "+val[i]); 
105
     
106
     return ret;
107
     }
108
*/
109
///////////////////////////////////////////////////////////////////////////////////////////////////
110
/*
111
   private static String debug(float[] val, int stop)
112
     {
113
     String ret="";
114

    
115
     for(int i=0; i<val.length; i++) 
116
        {
117
        if( i%stop==0 ) ret+="\n";
118
        ret+=(" "+val[i]);
119
        }
120

    
121
     return ret;
122
     }
123
*/  
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125
/*
126
   private static String debug(Edge e)
127
     {
128
     String d = "";
129
     
130
     switch(e.side)
131
       {
132
       case NORTH: d+="NORTH "; break;
133
       case SOUTH: d+="SOUTH "; break;
134
       case WEST : d+="WEST  "; break;
135
       case EAST : d+="EAST  "; break;
136
       }
137
     
138
     d+=("("+e.row+","+e.col+")");
139
     
140
     return d;
141
     }   
142
*/ 
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

    
145
   private void buildGrid(int cols, String desc, boolean frontOnly)
146
     {
147
     mRows     =0;
148
     mCols     =0;
149
     dataLength=0;
150
     
151
     if( cols>0 )
152
       {
153
       int reallen = desc.length();
154
       int len = reallen;
155

    
156
       if( (reallen/cols)*cols != reallen )
157
         {
158
         len = ((reallen/cols)+1)*cols; 
159
         for(int i=reallen; i<len; i++) desc += "0";
160
         }
161
    
162
       if( desc.indexOf("1")>=0 )
163
         {
164
         mCols = cols;
165
         mRows = len/cols;
166

    
167
         mCubes = new short[mRows][mCols];
168
       
169
         for(int j=0; j<mCols; j++) 
170
           for(int i=0; i<mRows; i++)
171
             mCubes[i][j] = (short)(desc.charAt(i*mCols+j) == '1' ? 1:0); 
172
       
173
         markRegions();
174
         dataLength = computeDataLength(frontOnly);
175
         }
176
       }
177
     }
178
 
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180
// Mark all the 'regions' of our grid  - i.e. separate pieces of 'land' (connected blocks that will 
181
// be rendered) and 'water' (connected holes in between) with integers. Each connected block of land
182
// gets a unique odd integer, each connected block of water a unique even integer.
183
//
184
// Water on the edges of the grid is also considered connected to itself!   
185
//   
186
// This function also creates a list of 'Edges'. Each Edge is a data structure from which later on we
187
// will start building the side walls of each connected black of land (and sides of holes of water 
188
// inside)   
189
   
190
   private void markRegions()
191
     {
192
     int i, j, numWater=1, numLand=0;
193
     
194
     for(i=0; i<mRows;i++) if( mCubes[      i][      0]==0 ) markRegion((short)2,      i,       0);
195
     for(i=0; i<mRows;i++) if( mCubes[      i][mCols-1]==0 ) markRegion((short)2,      i, mCols-1);
196
     for(i=0; i<mCols;i++) if( mCubes[0      ][      i]==0 ) markRegion((short)2,      0,       i);
197
     for(i=0; i<mCols;i++) if( mCubes[mRows-1][      i]==0 ) markRegion((short)2,mRows-1,       i);
198
           
199
     for(i=0; i<mRows; i++)
200
        for(j=0; j<mCols; j++)
201
           {
202
           if( mCubes[i][j] == 0 ) { numWater++; markRegion( (short)(2*numWater ),i,j); mEdges.add(new Edge(NORTH,i,j)); }
203
           if( mCubes[i][j] == 1 ) { numLand ++; markRegion( (short)(2*numLand+1),i,j); mEdges.add(new Edge(NORTH,i,j)); }
204
           }
205
     
206
     // now we potentially need to kick out some Edges - precisely the edges with water inside -
207
     // which are surrounded by more than one type of land. Otherwise the following does not work:
208
     //
209
     // 0 1 0
210
     // 1 0 1
211
     // 0 1 0
212
     //
213
     // The 'water inside' edges that did not get kicked out by this procedure need to be transformed
214
     // with Edge(NORTH,row,col) -> Edge(SOUTH,row-1,col) so that later on normals work correctly
215
     // (Edge always needs to point out from land to water for that)
216
     
217
     int numEdges= mEdges.size();
218
     short initLand;
219
     int initCol, initRow;
220
     boolean kicked;
221
     Edge e;
222
     
223
     for(i=0; i<numEdges; i++) 
224
       {
225
       e = mEdges.get(i);
226
       initRow= e.row;
227
       initCol= e.col;
228
         
229
       //android.util.Log.e("CUBES", "checking edge "+debug(e));
230
             
231
       if( mCubes[initRow][initCol]%2==0 )
232
         {
233
         kicked = false; 
234
         initLand = mCubes[initRow-1][initCol];
235
         
236
         do
237
           {
238
           e = getNextEdge(e); 
239
           //android.util.Log.e("CUBES", " next edge "+debug(e));   
240
       
241
           switch(e.side)
242
             {
243
             case NORTH: if( initLand!=mCubes[e.row-1][e.col  ] ) kicked=true; break;
244
             case SOUTH: if( initLand!=mCubes[e.row+1][e.col  ] ) kicked=true; break;
245
             case WEST:  if( initLand!=mCubes[e.row  ][e.col-1] ) kicked=true; break;
246
             case EAST:  if( initLand!=mCubes[e.row  ][e.col+1] ) kicked=true; break;
247
             }
248
           
249
           if( kicked )
250
             {
251
             //android.util.Log.e("CUBES", "kicking out edge!");
252
             mEdges.remove(i);
253
             i--;
254
             numEdges--; 
255
             }
256
           }
257
         while( kicked==false && (e.col!=initCol || e.row!=initRow || e.side!=NORTH) );
258
         
259
         if( kicked==false )
260
           {
261
           mEdges.set(i, new Edge(SOUTH,e.row-1,e.col)); 
262
           }
263
         }
264
       }
265
     }
266

    
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268
// when calling, make sure that newVal != val
269
   
270
   private void markRegion(short newVal, int row, int col)
271
     {
272
     short val = mCubes[row][col];
273
     mCubes[row][col] = newVal;
274
     
275
     if( row>0       && mCubes[row-1][col  ]==val ) markRegion(newVal, row-1, col  );
276
     if( row<mRows-1 && mCubes[row+1][col  ]==val ) markRegion(newVal, row+1, col  );
277
     if( col>0       && mCubes[row  ][col-1]==val ) markRegion(newVal, row  , col-1);
278
     if( col<mCols-1 && mCubes[row  ][col+1]==val ) markRegion(newVal, row  , col+1);
279
     }
280
   
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282
   
283
   private void createNormals(int row, int col)
284
     {
285
     int td,lr; 
286
      
287
	  int nw = (col>0       && row>0      ) ? (mCubes[row-1][col-1]%2) : 0;
288
	  int w  = (col>0                     ) ? (mCubes[row  ][col-1]%2) : 0;
289
	  int n  = (               row>0      ) ? (mCubes[row-1][col  ]%2) : 0;
290
	  int c  =                                (mCubes[row  ][col  ]%2);
291
	  int sw = (col>0       && row<mRows-1) ? (mCubes[row+1][col-1]%2) : 0;
292
     int s  = (               row<mRows-1) ? (mCubes[row+1][col  ]%2) : 0;
293
     int ne = (col<mCols-1 && row>0      ) ? (mCubes[row-1][col+1]%2) : 0;
294
     int e  = (col<mCols-1               ) ? (mCubes[row  ][col+1]%2) : 0;
295
     int se = (col<mCols-1 && row<mRows-1) ? (mCubes[row+1][col+1]%2) : 0;
296
     
297
     td = nw+n-w-c;
298
     lr = c+n-w-nw;
299
     if( td<0 ) td=-1;
300
     if( td>0 ) td= 1;
301
     if( lr<0 ) lr=-1;
302
     if( lr>0 ) lr= 1;
303
     mNormalX[0] = lr*R;
304
     mNormalY[0] = td*R;
305
     
306
     td = w+c-sw-s;
307
     lr = c+s-w-sw;
308
     if( td<0 ) td=-1;
309
     if( td>0 ) td= 1;
310
     if( lr<0 ) lr=-1;
311
     if( lr>0 ) lr= 1;
312
     mNormalX[1] = lr*R;
313
     mNormalY[1] = td*R;
314
     
315
     td = n+ne-c-e;
316
     lr = e+ne-c-n;
317
     if( td<0 ) td=-1;
318
     if( td>0 ) td= 1;
319
     if( lr<0 ) lr=-1;
320
     if( lr>0 ) lr= 1;
321
     mNormalX[2] = lr*R;
322
     mNormalY[2] = td*R;
323
     
324
     td = c+e-s-se;
325
     lr = e+se-c-s;
326
     if( td<0 ) td=-1;
327
     if( td>0 ) td= 1;
328
     if( lr<0 ) lr=-1;
329
     if( lr>0 ) lr= 1;
330
     mNormalX[3] = lr*R;
331
     mNormalY[3] = td*R;
332
     /*
333
	  android.util.Log.d("CUBES", "row="+row+" col="+col);
334
	  android.util.Log.d("CUBES", mNormalX[0]+" "+mNormalY[0]);
335
	  android.util.Log.d("CUBES", mNormalX[1]+" "+mNormalY[1]);
336
	  android.util.Log.d("CUBES", mNormalX[2]+" "+mNormalY[2]);
337
	  android.util.Log.d("CUBES", mNormalX[3]+" "+mNormalY[3]);
338
     */
339
     }
340
   
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342
   
343
   private int buildFrontBackGrid(boolean front, int vertex, float[] position, float[] normal, float[] texture)
344
     {
345
     short last, current;
346
     boolean seenland=false;
347
     float centerX, centerY;
348
    
349
     for(int i=0; i<mRows; i++)
350
       {
351
       last =0;
352
         
353
       for(int j=0; j<mCols; j++)
354
         {
355
         current = mCubes[i][j];
356
            
357
         if( current%2 == 1 )
358
           {
359
           centerX = j-(mCols-1.0f)/2.0f;
360
           centerY = (mRows-1.0f)/2.0f-i;
361
      
362
           createNormals(i,j);
363
          
364
           if( last != current )
365
             {
366
             if( seenland ) vertex = repeatLast(vertex,position,normal,texture);    
367

    
368
             if( front ) // NW corner
369
               {
370
               position[3*vertex+0] = (centerX-0.5f)/mCols;
371
               position[3*vertex+1] = (centerY+0.5f)/mRows;
372
               position[3*vertex+2] = FRONTZ;
373
               normal[3*vertex+0]   = mNormalX[0];
374
               normal[3*vertex+1]   = mNormalY[0];
375
               normal[3*vertex+2]   = 1.0f;
376
               texture[2*vertex+0]  = (float)j/mCols;
377
               texture[2*vertex+1]  = (float)i/mRows;     
378
               vertex++;
379
               }
380
             else  // SW corner
381
               { 
382
               position[3*vertex+0] = (centerX-0.5f)/mCols;
383
               position[3*vertex+1] = (centerY-0.5f)/mRows; 
384
               position[3*vertex+2] = BACKZ; 
385
               normal[3*vertex+0]   = mNormalX[1];
386
               normal[3*vertex+1]   = mNormalY[1];
387
               normal[3*vertex+2]   =-1.0f;
388
               texture[2*vertex+0]  = (float)j/mCols;
389
               texture[2*vertex+1]  = (float)(i+1)/mRows;
390
               vertex++;
391
               
392
               if( !seenland ) vertex = repeatLast(vertex,position,normal,texture);   //  if drawing the back, repeat the very first vertex
393
               }
394
             
395
             if( seenland ) vertex = repeatLast(vertex,position,normal,texture);    
396

    
397
             if( front ) // SW corner
398
               {
399
               position[3*vertex+0] = (centerX-0.5f)/mCols;
400
               position[3*vertex+1] = (centerY-0.5f)/mRows; 
401
               position[3*vertex+2] = FRONTZ; 
402
               normal[3*vertex+0]   = mNormalX[1];
403
               normal[3*vertex+1]   = mNormalY[1];
404
               normal[3*vertex+2]   = 1.0f;
405
               texture[2*vertex+0]  = (float)j/mCols;
406
               texture[2*vertex+1]  = (float)(i+1)/mRows;
407
               vertex++; 
408
               }
409
             else  // NW corner
410
               {
411
               position[3*vertex+0] = (centerX-0.5f)/mCols;
412
               position[3*vertex+1] = (centerY+0.5f)/mRows;
413
               position[3*vertex+2] = BACKZ;
414
               normal[3*vertex+0]   = mNormalX[0];
415
               normal[3*vertex+1]   = mNormalY[0];
416
               normal[3*vertex+2]   =-1.0f;
417
               texture[2*vertex+0]  = (float)j/mCols;
418
               texture[2*vertex+1]  = (float)i/mRows;     
419
               vertex++; 
420
               }
421
             }
422
              
423
           if( front )  // NE corner
424
             {
425
             position[3*vertex+0] = (centerX+0.5f)/mCols;
426
             position[3*vertex+1] = (centerY+0.5f)/mRows;
427
             position[3*vertex+2] = FRONTZ; 
428
             normal[3*vertex+0]   = mNormalX[2];
429
             normal[3*vertex+1]   = mNormalY[2];
430
             normal[3*vertex+2]   = 1.0f;
431
             texture[2*vertex+0]  = (float)(j+1)/mCols;
432
             texture[2*vertex+1]  = (float)i/mRows;
433
             vertex++;
434
             }
435
           else // SE corner
436
             {
437
             position[3*vertex+0] = (centerX+0.5f)/mCols;
438
             position[3*vertex+1] = (centerY-0.5f)/mRows;
439
             position[3*vertex+2] = BACKZ; 
440
             normal[3*vertex+0]   = mNormalX[3];
441
             normal[3*vertex+1]   = mNormalY[3];
442
             normal[3*vertex+2]   =-1.0f;
443
             texture[2*vertex+0]  = (float)(j+1)/mCols;
444
             texture[2*vertex+1]  = (float)(i+1)/mRows;
445
             vertex++; 
446
             }
447
           
448
           if( front )  // SE corner
449
             {
450
             position[3*vertex+0] = (centerX+0.5f)/mCols;
451
             position[3*vertex+1] = (centerY-0.5f)/mRows;
452
             position[3*vertex+2] = FRONTZ; 
453
             normal[3*vertex+0]   = mNormalX[3];
454
             normal[3*vertex+1]   = mNormalY[3];
455
             normal[3*vertex+2]   = 1.0f;
456
             texture[2*vertex+0]  = (float)(j+1)/mCols;
457
             texture[2*vertex+1]  = (float)(i+1)/mRows;
458
             vertex++;
459
             }
460
           else // NE corner
461
             {
462
             position[3*vertex+0] = (centerX+0.5f)/mCols;
463
             position[3*vertex+1] = (centerY+0.5f)/mRows;
464
             position[3*vertex+2] = BACKZ; 
465
             normal[3*vertex+0]   = mNormalX[2];
466
             normal[3*vertex+1]   = mNormalY[2];
467
             normal[3*vertex+2]   =-1.0f;
468
             texture[2*vertex+0]  = (float)(j+1)/mCols;
469
             texture[2*vertex+1]  = (float)i/mRows;
470
             vertex++; 
471
             }
472
           
473
           seenland = true;
474
           }
475
            
476
         last = current;
477
         }
478
       }
479
     
480
     return vertex;
481
     }
482

    
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484

    
485
   private int repeatLast(int vertex, float[] position, float[] normal, float[] texture)
486
     {
487
     if( vertex>0 )
488
       {
489
       position[3*vertex+0] = position[3*vertex-3]; 
490
       position[3*vertex+1] = position[3*vertex-2];
491
       position[3*vertex+2] = position[3*vertex-1];
492

    
493
       normal[3*vertex+0]   = normal[3*vertex-3]; 
494
       normal[3*vertex+1]   = normal[3*vertex-2];
495
       normal[3*vertex+2]   = normal[3*vertex-1];
496

    
497
       texture[2*vertex+0]  = texture[2*vertex-2];
498
       texture[2*vertex+1]  = texture[2*vertex-1];
499
         
500
       vertex++;     
501
       }
502
     
503
     return vertex;
504
     }
505
   
506
///////////////////////////////////////////////////////////////////////////////////////////////////
507

    
508
   private int buildSideGrid(int vertex, float[] position, float[] normal, float[] texture)
509
     {
510
     int edges= mEdges.size();
511
     
512
     for(int i=0; i<edges; i++) 
513
       {
514
       vertex = buildIthSide(mEdges.get(i), vertex, position, normal, texture);  
515
       } 
516
      
517
     return vertex;
518
     }
519

    
520
///////////////////////////////////////////////////////////////////////////////////////////////////
521

    
522
   private int buildIthSide(Edge curr, int vertex, float[] position, float[] normal, float[] texture)
523
     {
524
     Edge prev; 
525
     
526
     if( curr.side==NORTH ) // water outside
527
       {
528
       prev = new Edge(WEST,curr.row,curr.col);
529
       }
530
     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.
531
       {
532
       prev = curr;
533
       curr = new Edge(EAST,curr.row+1,curr.col-1);
534
       }
535
     
536
     int col = curr.col;
537
     int row = curr.row;
538
     int side= curr.side;  
539
     Edge next = getNextEdge(curr);
540
     
541
     addVertex(curr,BACK,LOWER,prev.side,vertex,position,normal,texture);
542
     vertex++;
543
     
544
     do
545
       {
546
       if( prev.side!=curr.side )
547
         {
548
         addVertex(curr,BACK,LOWER,prev.side,vertex,position,normal,texture);
549
         vertex++;
550
         addVertex(curr,BACK,UPPER,prev.side,vertex,position,normal,texture);
551
         vertex++;
552
         }
553
       
554
       addVertex(curr,FRONT,LOWER,next.side,vertex,position,normal,texture);
555
       vertex++;
556
       addVertex(curr,FRONT,UPPER,next.side,vertex,position,normal,texture);
557
       vertex++;
558
       
559
       prev = curr;
560
       curr = next; 
561
       next = getNextEdge(curr);
562
       }
563
     while( curr.col!=col || curr.row!=row || curr.side!=side );
564
     
565
     vertex = repeatLast(vertex,position,normal,texture);
566
     
567
     return vertex;
568
     }
569

    
570
///////////////////////////////////////////////////////////////////////////////////////////////////
571

    
572
   private Edge getNextEdge(Edge curr)
573
     {
574
     int col = curr.col;
575
     int row = curr.row;
576
      
577
     //android.util.Log.e("CUBES", "row="+row+" col="+col+" mRows="+mRows+" mCols="+mCols);
578
                       
579
     switch(curr.side) 
580
       {
581
       case NORTH: if( col==mCols-1 ) 
582
                     return new Edge(EAST,row,col);
583
                   if( row>0 && mCubes[row-1][col+1]==mCubes[row][col] )
584
                     return new Edge(WEST,row-1,col+1);
585
                   if( mCubes[row][col+1]==mCubes[row][col] )
586
                     return new Edge(NORTH,row,col+1);
587
                   else  
588
                     return new Edge(EAST,row,col);
589
                   
590
       case SOUTH: if( col==0 ) 
591
                     return new Edge(WEST,row,col);
592
                   if( (row<mRows-1) && mCubes[row+1][col-1]==mCubes[row][col] )
593
                     return new Edge(EAST,row+1,col-1); 
594
                   if( mCubes[row][col-1]==mCubes[row][col] )
595
                     return new Edge(SOUTH,row,col-1);
596
                   else
597
                     return new Edge(WEST,row,col); 
598
                     
599
       case EAST : if( row==mRows-1 ) 
600
                     return new Edge(SOUTH,row,col);
601
                   if( (col<mCols-1) && mCubes[row+1][col+1]==mCubes[row][col] )
602
                     return new Edge(NORTH,row+1,col+1);
603
                   if( mCubes[row+1][col]==mCubes[row][col] )
604
                     return new Edge(EAST,row+1,col);
605
                   else 
606
                     return new Edge(SOUTH,row,col);
607
                   
608
       case WEST : if( row==0 )
609
                     return new Edge(NORTH,row,col);
610
                   if( col>0 && mCubes[row-1][col-1]==mCubes[row][col] )
611
                     return new Edge(SOUTH,row-1,col-1);
612
                   if( mCubes[row-1][col]==mCubes[row][col] )
613
                     return new Edge(WEST,row-1,col);
614
                   else
615
                     return new Edge(NORTH,row,col);     
616
       }
617
     
618
     return null;
619
     }
620

    
621
///////////////////////////////////////////////////////////////////////////////////////////////////
622
   
623
   private void addVertex(Edge curr, boolean back, boolean lower,int side, int vertex, float[] position, float[] normal, float[] texture)
624
     {
625
     float centerX = curr.col-(mCols-1.0f)/2.0f;
626
     float centerY = (mRows-1.0f)/2.0f-curr.row;
627
  
628
     switch(curr.side)
629
       {
630
       case NORTH: position[3*vertex+0] = (back ? (centerX-0.5f) : (centerX+0.5f))/mCols; 
631
                   position[3*vertex+1] = (centerY+0.5f)/mRows;
632
                   position[3*vertex+2] = lower ? BACKZ : FRONTZ;
633

    
634
                   normal[3*vertex+0]   = side==NORTH ? 0.0f : (side==WEST?-R:R);
635
                   normal[3*vertex+1]   = 1.0f;
636
                   normal[3*vertex+2]   = lower ? -R:R;
637

    
638
                   texture[2*vertex+0]  = (float)(back ? (curr.col  ):(curr.col+1))/mCols;
639
                   texture[2*vertex+1]  = (float)(lower? (curr.row-1):(curr.row  ))/mRows;  
640
                   break;
641
       case SOUTH: position[3*vertex+0] = (back ? (centerX+0.5f) : (centerX-0.5f))/mCols;
642
                   position[3*vertex+1] = (centerY-0.5f)/mRows;
643
                   position[3*vertex+2] = lower ? BACKZ : FRONTZ;  
644
            
645
                   normal[3*vertex+0]   = side==SOUTH ? 0.0f: (side==EAST?-R:R);
646
                   normal[3*vertex+1]   =-1.0f;
647
                   normal[3*vertex+2]   = lower ? -R:R;
648

    
649
                   texture[2*vertex+0]  = (float)(back ? (curr.col+1):(curr.col  ))/mCols;
650
                   texture[2*vertex+1]  = (float)(lower? (curr.row+2):(curr.row+1))/mRows;
651
                   break;
652
       case WEST : position[3*vertex+0] = (centerX-0.5f)/mCols;
653
                   position[3*vertex+1] = (back ? (centerY-0.5f):(centerY+0.5f))/mRows;
654
                   position[3*vertex+2] = lower ? BACKZ : FRONTZ;
655

    
656
                   normal[3*vertex+0]   =-1.0f;
657
                   normal[3*vertex+1]   = side==WEST ? 0.0f : (side==NORTH?-R:R);
658
                   normal[3*vertex+2]   = lower ? -R:R;
659
 
660
                   texture[2*vertex+0]  = (float)(lower ? (curr.col-1):(curr.col  ))/mCols;
661
                   texture[2*vertex+1]  = (float)(back  ? (curr.row+1):(curr.row  ))/mRows;
662
                   break;
663
       case EAST : position[3*vertex+0] = (centerX+0.5f)/mCols;
664
                   position[3*vertex+1] = (back ? (centerY+0.5f):(centerY-0.5f))/mRows;
665
                   position[3*vertex+2] = lower ? BACKZ : FRONTZ;
666

    
667
                   normal[3*vertex+0]   = 1.0f;
668
                   normal[3*vertex+1]   = side==EAST ? 0.0f : (side==SOUTH?-R:R);
669
                   normal[3*vertex+2]   = lower ? -R:R; 
670

    
671
                   texture[2*vertex+0]  = (float)(lower ? (curr.col+2):(curr.col+1))/mCols;
672
                   texture[2*vertex+1]  = (float)(back  ? (curr.row  ):(curr.row+1))/mRows;
673
                   break;
674
       }
675
     
676
     if(texture[2*vertex+0]>1.0f) texture[2*vertex+0] =2.0f-texture[2*vertex+0];
677
     if(texture[2*vertex+0]<0.0f) texture[2*vertex+0] =    -texture[2*vertex+0];
678
     if(texture[2*vertex+1]>1.0f) texture[2*vertex+1] =2.0f-texture[2*vertex+1];
679
     if(texture[2*vertex+1]<0.0f) texture[2*vertex+1] =    -texture[2*vertex+1];
680
     }
681

    
682
///////////////////////////////////////////////////////////////////////////////////////////////////
683
// PUBLIC API
684
///////////////////////////////////////////////////////////////////////////////////////////////////
685
   
686
/**
687
 * Creates the underlying grid of vertices, normals, texture coords and colors.
688
 *    
689
 * @param rows See {@link DistortedCubes#DistortedCubes(String)} 
690
 * @param desc See {@link DistortedCubes#DistortedCubes(String)}
691
 */
692
   public GridCubes(int cols, String desc, boolean frontOnly) 
693
      {
694
      buildGrid(cols,desc,frontOnly);
695
       
696
      int numVertices=0;
697
      float[] colorData   = new float[COLOR_DATA_SIZE   *dataLength];
698
      float[] positionData= new float[POSITION_DATA_SIZE*dataLength];
699
      float[] normalData  = new float[NORMAL_DATA_SIZE  *dataLength];
700
      float[] textureData = new float[TEX_DATA_SIZE     *dataLength];
701
      
702
      for(int i=0; i<dataLength; i++)
703
        {
704
        colorData[COLOR_DATA_SIZE*i+0] = 1.0f; // r
705
        colorData[COLOR_DATA_SIZE*i+1] = 1.0f; // g
706
        colorData[COLOR_DATA_SIZE*i+2] = 1.0f; // b
707
        colorData[COLOR_DATA_SIZE*i+3] = 1.0f; // a
708
        }
709

    
710
      numVertices = buildFrontBackGrid(true, numVertices,positionData,normalData,textureData);
711
      
712
      if( !frontOnly )
713
        {
714
        numVertices = repeatLast(numVertices,positionData,normalData,textureData);
715
        numVertices = buildSideGrid (numVertices,positionData,normalData,textureData);
716
        numVertices = buildFrontBackGrid (false,numVertices,positionData,normalData,textureData);
717
        }
718
      
719
      /*
720
      android.util.Log.e("CUBES","dataLen="+dataLength+" vertex="+numVertices);
721
      android.util.Log.d("CUBES", "position: "+debug(positionData,3) );
722
      android.util.Log.d("CUBES", "normal: "  +debug(  normalData,3) );
723
      android.util.Log.d("CUBES", "texture: " +debug( textureData,2) );
724
      */
725
      mGridColors = ByteBuffer.allocateDirect(COLOR_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();                                                        
726
      mGridColors.put(colorData).position(0); 
727

    
728
      mGridPositions = ByteBuffer.allocateDirect(POSITION_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();                                                        
729
      mGridPositions.put(positionData).position(0); 
730
      
731
      mGridNormals = ByteBuffer.allocateDirect(NORMAL_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();                                                        
732
      mGridNormals.put(normalData).position(0); 
733

    
734
      mGridTexture = ByteBuffer.allocateDirect(TEX_DATA_SIZE*dataLength*BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();                                                        
735
      mGridTexture.put(textureData).position(0); 
736
      }
737
   }
738
///////////////////////////////////////////////////////////////////////////////////////////////////
739

    
(21-21/28)