Revision ce7f3833
Added by Leszek Koltunski over 9 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)