Revision ce7f3833
Added by Leszek Koltunski over 8 years ago
src/main/java/org/distorted/library/DistortedCubesGrid.java | ||
---|---|---|
35 | 35 |
private static final int WEST = 1; |
36 | 36 |
private static final int EAST = 2; |
37 | 37 |
private static final int SOUTH = 3; |
38 |
|
|
38 |
|
|
39 |
private static final int NW = 0; |
|
40 |
private static final int NE = 1; |
|
41 |
private static final int SW = 2; |
|
42 |
private static final int SE = 3; |
|
43 |
|
|
39 | 44 |
private static final boolean BACK = true; |
40 | 45 |
private static final boolean FRONT = false; |
41 | 46 |
private static final boolean UPPER = false; |
... | ... | |
43 | 48 |
|
44 | 49 |
private static final float[] mNormalX = new float[4]; |
45 | 50 |
private static final float[] mNormalY = new float[4]; |
46 |
|
|
51 |
private static final float[] mNormalZ = new float[4]; |
|
52 |
|
|
47 | 53 |
private class Edge |
48 | 54 |
{ |
49 | 55 |
final int side; |
... | ... | |
61 | 67 |
private int mCols, mRows; |
62 | 68 |
private short[][] mCubes; |
63 | 69 |
private ArrayList<Edge> mEdges = new ArrayList<>(); |
64 |
|
|
70 |
|
|
71 |
private boolean addEmpty1; // add an initial empty vertex? ( that would be because the initial block |
|
72 |
// of land is in the top-right quarter (or bottom-left) and thus the very |
|
73 |
// first triangle is counter-clockwise) |
|
74 |
private boolean addEmpty2; // add an empty vertex when shifting from front to the side (that happens |
|
75 |
// iff the last front block is in the front-left or bottom-right quarter) |
|
76 |
private boolean addEmpty3; // add an empty vertex when shifting from the side to the back. (that |
|
77 |
// happens iff the first back block is in the top right or bottom-left |
|
78 |
// quarter, i.e. actually addEmpty3 = addEmpty1. |
|
79 |
|
|
80 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
81 |
// a Block is split into two triangles along the NE-SW line iff it is in the top-right |
|
82 |
// or bottom-left quadrant of the grid. |
|
83 |
|
|
84 |
private boolean isNE(int row,int col) |
|
85 |
{ |
|
86 |
return ( (row<=(mRows-1)/2)^(col<=(mCols-1)/2) ); |
|
87 |
} |
|
88 |
|
|
65 | 89 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
66 | 90 |
|
67 | 91 |
private int computeDataLength(boolean frontOnly) |
68 | 92 |
{ |
69 |
int frontWalls=0, frontSegments=0, sideWalls=0, sideBends=0; |
|
70 |
|
|
93 |
int frontWalls=0, frontSegments=0, sideWalls=0, sideBends=0, triangleShifts=0, rowJumpShifts=0; |
|
94 |
int shiftCol = (mCols-1)/2; |
|
95 |
|
|
96 |
boolean seenLand=false; |
|
97 |
boolean lastBlockIsNE=false; |
|
98 |
boolean seenBlockInRow; |
|
99 |
boolean thisBlockIsNE; // the block we are currently looking at is split into |
|
100 |
// two triangles along the NE-SW line (rather than NW-SE) |
|
101 |
|
|
71 | 102 |
for(int i=0; i<mRows; i++) |
103 |
{ |
|
104 |
if( mCols>=2 && (mCubes[i][shiftCol]%2 == 1) && (mCubes[i][shiftCol+1]%2 == 1) ) triangleShifts++; |
|
105 |
|
|
106 |
seenBlockInRow=false; |
|
107 |
|
|
72 | 108 |
for(int j=0; j<mCols; j++) |
73 | 109 |
{ |
74 | 110 |
if( mCubes[i][j]%2 == 1 ) // land |
75 | 111 |
{ |
112 |
thisBlockIsNE = isNE(i,j); |
|
113 |
|
|
114 |
if( !seenBlockInRow ) |
|
115 |
{ |
|
116 |
if( thisBlockIsNE^lastBlockIsNE ) rowJumpShifts++; |
|
117 |
seenBlockInRow=true; |
|
118 |
} |
|
119 |
|
|
120 |
lastBlockIsNE = thisBlockIsNE; |
|
121 |
|
|
122 |
if( !seenLand ) |
|
123 |
{ |
|
124 |
addEmpty1 = addEmpty3 = lastBlockIsNE; |
|
125 |
seenLand=true; |
|
126 |
} |
|
127 |
|
|
76 | 128 |
frontWalls++; |
77 | 129 |
if( j==mCols-1 || mCubes[i][j+1]%2 == 0 ) frontSegments++; |
78 | 130 |
} |
... | ... | |
82 | 134 |
if( i==mRows-1 && mCubes[i][j]!=2 ) sideWalls++; // bottom |
83 | 135 |
if( j==mCols-1 && mCubes[i][j]!=2 ) sideWalls++; // right |
84 | 136 |
} |
137 |
} |
|
138 |
|
|
139 |
addEmpty2 = !lastBlockIsNE; |
|
85 | 140 |
|
86 | 141 |
int edges= mEdges.size(); |
87 | 142 |
|
... | ... | |
101 | 156 |
} |
102 | 157 |
while( curr.col!=startX || curr.row!=startY || curr.side!=startS ); |
103 | 158 |
} |
104 |
|
|
105 |
int frontVert = 2*( frontWalls + 2*frontSegments - 1); |
|
159 |
|
|
160 |
int frontVert = 2*( frontWalls + 2*frontSegments - 1) +3*triangleShifts + rowJumpShifts;
|
|
106 | 161 |
int sideVert = 2*( sideWalls + sideBends + edges -1); |
107 |
|
|
108 |
int dataL = frontOnly ? frontVert : (frontVert+1) + (1+sideVert+1) + (1+frontVert); |
|
109 |
|
|
110 |
//android.util.Log.e("CUBES","frontVert="+frontVert+" sideVert="+sideVert); |
|
111 |
//android.util.Log.e("CUBES", "frontW="+frontWalls+" fSegments="+frontSegments+" sWalls="+sideWalls+" sSegments="+edges+" sideBends="+sideBends+" dataLen="+dataL ); |
|
162 |
|
|
163 |
// no we don't add addEmpty1 because this is already included in the rowJumpShifts |
|
164 |
int dataL = frontOnly ? frontVert : (frontVert+1) + (1+sideVert+1) + (1+frontVert) +(addEmpty2?1:0) + (addEmpty3?1:0); |
|
165 |
|
|
166 |
android.util.Log.e("CUBES","triangleShifts="+triangleShifts+" rowJumpShifts="+rowJumpShifts); |
|
167 |
android.util.Log.e("CUBES","addEmpty1="+addEmpty1+" addEmpty2="+addEmpty2+" addEmpty3="+addEmpty3); |
|
168 |
android.util.Log.e("CUBES","frontVert="+frontVert+" sideVert="+sideVert); |
|
169 |
android.util.Log.e("CUBES", "frontW="+frontWalls+" fSegments="+frontSegments+" sWalls="+sideWalls+" sSegments="+edges+" sideBends="+sideBends+" dataLen="+dataL ); |
|
112 | 170 |
|
113 | 171 |
return dataL<0 ? 0:dataL; |
114 | 172 |
} |
... | ... | |
117 | 175 |
/* |
118 | 176 |
private static String debug(short[] val) |
119 | 177 |
{ |
120 |
String ret=""; |
|
178 |
String ret="";j
|
|
121 | 179 |
|
122 | 180 |
for(int i=0; i<val.length; i++) ret+=(" "+val[i]); |
123 | 181 |
|
... | ... | |
287 | 345 |
|
288 | 346 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
289 | 347 |
|
290 |
private void createNormals(int row, int col) |
|
348 |
private void createNormals(boolean front, int row, int col)
|
|
291 | 349 |
{ |
292 | 350 |
int td,lr; |
293 | 351 |
|
... | ... | |
300 | 358 |
int ne = (col<mCols-1 && row>0 ) ? (mCubes[row-1][col+1]%2) : 0; |
301 | 359 |
int e = (col<mCols-1 ) ? (mCubes[row ][col+1]%2) : 0; |
302 | 360 |
int se = (col<mCols-1 && row<mRows-1) ? (mCubes[row+1][col+1]%2) : 0; |
303 |
|
|
361 |
|
|
362 |
if(front) |
|
363 |
{ |
|
364 |
mNormalZ[0] = 1.0f; |
|
365 |
mNormalZ[1] = 1.0f; |
|
366 |
mNormalZ[2] = 1.0f; |
|
367 |
mNormalZ[3] = 1.0f; |
|
368 |
} |
|
369 |
else |
|
370 |
{ |
|
371 |
mNormalZ[0] =-1.0f; |
|
372 |
mNormalZ[1] =-1.0f; |
|
373 |
mNormalZ[2] =-1.0f; |
|
374 |
mNormalZ[3] =-1.0f; |
|
375 |
} |
|
376 |
|
|
304 | 377 |
td = nw+n-w-c; |
305 | 378 |
lr = c+n-w-nw; |
306 | 379 |
if( td<0 ) td=-1; |
... | ... | |
346 | 419 |
} |
347 | 420 |
|
348 | 421 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
349 |
|
|
422 |
|
|
423 |
private int addFrontVertex(int corner, int vertex, float centerX, float centerY, float vectZ, int col, int row, float[] position, float[] normal, float[] texture) |
|
424 |
{ |
|
425 |
switch(corner) |
|
426 |
{ |
|
427 |
case NW: position[3*vertex ] = (centerX-0.5f)/mCols; |
|
428 |
position[3*vertex+1] = (centerY+0.5f)/mRows; |
|
429 |
position[3*vertex+2] = vectZ; |
|
430 |
normal[3*vertex ] = mNormalX[0]; |
|
431 |
normal[3*vertex+1] = mNormalY[0]; |
|
432 |
normal[3*vertex+2] = mNormalZ[0]; |
|
433 |
texture[2*vertex ] = (float)col/mCols; |
|
434 |
texture[2*vertex+1] = (float)row/mRows; |
|
435 |
return vertex+1; |
|
436 |
case SW: position[3*vertex ] = (centerX-0.5f)/mCols; |
|
437 |
position[3*vertex+1] = (centerY-0.5f)/mRows; |
|
438 |
position[3*vertex+2] = vectZ; |
|
439 |
normal[3*vertex ] = mNormalX[1]; |
|
440 |
normal[3*vertex+1] = mNormalY[1]; |
|
441 |
normal[3*vertex+2] = mNormalZ[1]; |
|
442 |
texture[2*vertex ] = (float)col/mCols; |
|
443 |
texture[2*vertex+1] = (float)(row+1)/mRows; |
|
444 |
return vertex+1; |
|
445 |
case NE: position[3*vertex ] = (centerX+0.5f)/mCols; |
|
446 |
position[3*vertex+1] = (centerY+0.5f)/mRows; |
|
447 |
position[3*vertex+2] = vectZ; |
|
448 |
normal[3*vertex ] = mNormalX[2]; |
|
449 |
normal[3*vertex+1] = mNormalY[2]; |
|
450 |
normal[3*vertex+2] = mNormalZ[2]; |
|
451 |
texture[2*vertex ] = (float)(col+1)/mCols; |
|
452 |
texture[2*vertex+1] = (float)row/mRows; |
|
453 |
return vertex+1; |
|
454 |
case SE: position[3*vertex ] = (centerX+0.5f)/mCols; |
|
455 |
position[3*vertex+1] = (centerY-0.5f)/mRows; |
|
456 |
position[3*vertex+2] = vectZ; |
|
457 |
normal[3*vertex ] = mNormalX[3]; |
|
458 |
normal[3*vertex+1] = mNormalY[3]; |
|
459 |
normal[3*vertex+2] = mNormalZ[3]; |
|
460 |
texture[2*vertex ] = (float)(col+1)/mCols; |
|
461 |
texture[2*vertex+1] = (float)(row+1)/mRows; |
|
462 |
} |
|
463 |
|
|
464 |
return vertex; |
|
465 |
} |
|
466 |
|
|
467 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
468 |
|
|
350 | 469 |
private int buildFrontBackGrid(boolean front, int vertex, float[] position, float[] normal, float[] texture) |
351 | 470 |
{ |
352 | 471 |
short last, current; |
353 |
boolean seenland=false; |
|
472 |
boolean seenLand=false; |
|
473 |
boolean lastBlockIsNE = false; |
|
474 |
boolean currentBlockIsNE; |
|
354 | 475 |
float centerX, centerY; |
355 |
|
|
476 |
float vectZ = front?FRONTZ:BACKZ; |
|
477 |
|
|
356 | 478 |
for(int i=0; i<mRows; i++) |
357 | 479 |
{ |
358 | 480 |
last =0; |
... | ... | |
360 | 482 |
for(int j=0; j<mCols; j++) |
361 | 483 |
{ |
362 | 484 |
current = mCubes[i][j]; |
363 |
|
|
485 |
|
|
364 | 486 |
if( current%2 == 1 ) |
365 | 487 |
{ |
488 |
currentBlockIsNE = isNE(i,j); |
|
366 | 489 |
centerX = j-(mCols-1.0f)/2.0f; |
367 | 490 |
centerY = (mRows-1.0f)/2.0f-i; |
368 | 491 |
|
369 |
createNormals(i,j); |
|
370 |
|
|
371 |
if( last != current ) |
|
372 |
{ |
|
373 |
if( seenland ) vertex = repeatLast(vertex,position,normal,texture); |
|
374 |
|
|
375 |
if( front ) // NW corner |
|
376 |
{ |
|
377 |
position[3*vertex ] = (centerX-0.5f)/mCols; |
|
378 |
position[3*vertex+1] = (centerY+0.5f)/mRows; |
|
379 |
position[3*vertex+2] = FRONTZ; |
|
380 |
normal[3*vertex ] = mNormalX[0]; |
|
381 |
normal[3*vertex+1] = mNormalY[0]; |
|
382 |
normal[3*vertex+2] = 1.0f; |
|
383 |
texture[2*vertex ] = (float)j/mCols; |
|
384 |
texture[2*vertex+1] = (float)i/mRows; |
|
385 |
vertex++; |
|
386 |
} |
|
387 |
else // SW corner |
|
388 |
{ |
|
389 |
position[3*vertex ] = (centerX-0.5f)/mCols; |
|
390 |
position[3*vertex+1] = (centerY-0.5f)/mRows; |
|
391 |
position[3*vertex+2] = BACKZ; |
|
392 |
normal[3*vertex ] = mNormalX[1]; |
|
393 |
normal[3*vertex+1] = mNormalY[1]; |
|
394 |
normal[3*vertex+2] =-1.0f; |
|
395 |
texture[2*vertex ] = (float)j/mCols; |
|
396 |
texture[2*vertex+1] = (float)(i+1)/mRows; |
|
397 |
vertex++; |
|
398 |
|
|
399 |
if( !seenland ) vertex = repeatLast(vertex,position,normal,texture); // if drawing the back, repeat the very first vertex |
|
400 |
} |
|
401 |
|
|
402 |
if( seenland ) vertex = repeatLast(vertex,position,normal,texture); |
|
403 |
|
|
404 |
if( front ) // SW corner |
|
405 |
{ |
|
406 |
position[3*vertex ] = (centerX-0.5f)/mCols; |
|
407 |
position[3*vertex+1] = (centerY-0.5f)/mRows; |
|
408 |
position[3*vertex+2] = FRONTZ; |
|
409 |
normal[3*vertex ] = mNormalX[1]; |
|
410 |
normal[3*vertex+1] = mNormalY[1]; |
|
411 |
normal[3*vertex+2] = 1.0f; |
|
412 |
texture[2*vertex ] = (float)j/mCols; |
|
413 |
texture[2*vertex+1] = (float)(i+1)/mRows; |
|
414 |
vertex++; |
|
415 |
} |
|
416 |
else // NW corner |
|
417 |
{ |
|
418 |
position[3*vertex ] = (centerX-0.5f)/mCols; |
|
419 |
position[3*vertex+1] = (centerY+0.5f)/mRows; |
|
420 |
position[3*vertex+2] = BACKZ; |
|
421 |
normal[3*vertex ] = mNormalX[0]; |
|
422 |
normal[3*vertex+1] = mNormalY[0]; |
|
423 |
normal[3*vertex+2] =-1.0f; |
|
424 |
texture[2*vertex ] = (float)j/mCols; |
|
425 |
texture[2*vertex+1] = (float)i/mRows; |
|
426 |
vertex++; |
|
427 |
} |
|
428 |
} |
|
429 |
|
|
430 |
if( front ) // NE corner |
|
431 |
{ |
|
432 |
position[3*vertex ] = (centerX+0.5f)/mCols; |
|
433 |
position[3*vertex+1] = (centerY+0.5f)/mRows; |
|
434 |
position[3*vertex+2] = FRONTZ; |
|
435 |
normal[3*vertex ] = mNormalX[2]; |
|
436 |
normal[3*vertex+1] = mNormalY[2]; |
|
437 |
normal[3*vertex+2] = 1.0f; |
|
438 |
texture[2*vertex ] = (float)(j+1)/mCols; |
|
439 |
texture[2*vertex+1] = (float)i/mRows; |
|
440 |
vertex++; |
|
441 |
} |
|
442 |
else // SE corner |
|
443 |
{ |
|
444 |
position[3*vertex ] = (centerX+0.5f)/mCols; |
|
445 |
position[3*vertex+1] = (centerY-0.5f)/mRows; |
|
446 |
position[3*vertex+2] = BACKZ; |
|
447 |
normal[3*vertex ] = mNormalX[3]; |
|
448 |
normal[3*vertex+1] = mNormalY[3]; |
|
449 |
normal[3*vertex+2] =-1.0f; |
|
450 |
texture[2*vertex ] = (float)(j+1)/mCols; |
|
451 |
texture[2*vertex+1] = (float)(i+1)/mRows; |
|
452 |
vertex++; |
|
453 |
} |
|
454 |
|
|
455 |
if( front ) // SE corner |
|
456 |
{ |
|
457 |
position[3*vertex ] = (centerX+0.5f)/mCols; |
|
458 |
position[3*vertex+1] = (centerY-0.5f)/mRows; |
|
459 |
position[3*vertex+2] = FRONTZ; |
|
460 |
normal[3*vertex ] = mNormalX[3]; |
|
461 |
normal[3*vertex+1] = mNormalY[3]; |
|
462 |
normal[3*vertex+2] = 1.0f; |
|
463 |
texture[2*vertex ] = (float)(j+1)/mCols; |
|
464 |
texture[2*vertex+1] = (float)(i+1)/mRows; |
|
465 |
vertex++; |
|
466 |
} |
|
467 |
else // NE corner |
|
492 |
createNormals(front,i,j); |
|
493 |
|
|
494 |
if( (last!=current) || (lastBlockIsNE^currentBlockIsNE) ) |
|
468 | 495 |
{ |
469 |
position[3*vertex ] = (centerX+0.5f)/mCols; |
|
470 |
position[3*vertex+1] = (centerY+0.5f)/mRows; |
|
471 |
position[3*vertex+2] = BACKZ; |
|
472 |
normal[3*vertex ] = mNormalX[2]; |
|
473 |
normal[3*vertex+1] = mNormalY[2]; |
|
474 |
normal[3*vertex+2] =-1.0f; |
|
475 |
texture[2*vertex ] = (float)(j+1)/mCols; |
|
476 |
texture[2*vertex+1] = (float)i/mRows; |
|
477 |
vertex++; |
|
496 |
if( seenLand && (last != current) ) vertex = repeatLast(vertex,position,normal,texture); |
|
497 |
vertex= addFrontVertex( currentBlockIsNE ? NW:SW, vertex, centerX, centerY, vectZ, j, i, position, normal, texture); |
|
498 |
if( seenLand && (last != current) ) vertex = repeatLast(vertex,position,normal,texture); |
|
499 |
if( lastBlockIsNE^currentBlockIsNE ) vertex = repeatLast(vertex,position,normal,texture); |
|
500 |
vertex= addFrontVertex( currentBlockIsNE ? SW:NW, vertex, centerX, centerY, vectZ, j, i, position, normal, texture); |
|
478 | 501 |
} |
479 |
|
|
480 |
seenland = true; |
|
502 |
vertex= addFrontVertex( currentBlockIsNE ? NE:SE, vertex, centerX, centerY, vectZ, j, i, position, normal, texture); |
|
503 |
vertex= addFrontVertex( currentBlockIsNE ? SE:NE, vertex, centerX, centerY, vectZ, j, i, position, normal, texture); |
|
504 |
|
|
505 |
seenLand = true; |
|
506 |
lastBlockIsNE = currentBlockIsNE; |
|
481 | 507 |
} |
482 | 508 |
|
483 | 509 |
last = current; |
... | ... | |
515 | 541 |
private int buildSideGrid(int vertex, float[] position, float[] normal, float[] texture) |
516 | 542 |
{ |
517 | 543 |
int edges= mEdges.size(); |
518 |
|
|
544 |
|
|
545 |
if( addEmpty2 ) vertex = repeatLast(vertex,position,normal,texture); |
|
546 |
|
|
519 | 547 |
for(int i=0; i<edges; i++) |
520 | 548 |
{ |
521 | 549 |
vertex = buildIthSide(mEdges.get(i), vertex, position, normal, texture); |
Also available in: Unified diff
beginnings of support for advanced tesselation in DistortedCubes target (still doesn't quite work)