Revision 6b6504fe
Added by Leszek Koltunski about 5 years ago
| src/main/java/org/distorted/objects/RubikCube.java | ||
|---|---|---|
| 394 | 394 |
return 0; |
| 395 | 395 |
} |
| 396 | 396 |
|
| 397 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 398 |
|
|
| 399 |
public boolean isSolved() |
|
| 400 |
{
|
|
| 401 |
int index = CUBITS[0].mQuatIndex; |
|
| 402 |
|
|
| 403 |
for(int i=1; i<NUM_CUBITS; i++) |
|
| 404 |
{
|
|
| 405 |
if( !thereIsNoVisibleDifference(CUBITS[i], index) ) return false; |
|
| 406 |
} |
|
| 407 |
|
|
| 408 |
return true; |
|
| 409 |
} |
|
| 410 |
|
|
| 397 | 411 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 398 | 412 |
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different |
| 399 | 413 |
// then if it were rotated by quaternion 'quat'. |
| ... | ... | |
| 404 | 418 |
// a) is a corner or edge and the quaternions are the same |
| 405 | 419 |
// b) is inside one of the faces and after rotations by both quats it ends up on the same face. |
| 406 | 420 |
|
| 407 |
boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex) |
|
| 421 |
private boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex)
|
|
| 408 | 422 |
{
|
| 409 | 423 |
if ( cubit.mQuatIndex == quatIndex ) return true; |
| 410 | 424 |
|
| src/main/java/org/distorted/objects/RubikDino.java | ||
|---|---|---|
| 41 | 41 |
import org.distorted.library.type.Static1D; |
| 42 | 42 |
import org.distorted.library.type.Static3D; |
| 43 | 43 |
import org.distorted.library.type.Static4D; |
| 44 |
import org.distorted.main.RubikSurfaceView; |
|
| 44 | 45 |
|
| 45 | 46 |
import java.util.Random; |
| 46 | 47 |
|
| ... | ... | |
| 442 | 443 |
} |
| 443 | 444 |
|
| 444 | 445 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 445 |
// here it's simple - all cubits have to be rotated with the same quaretnion for the whole thing |
|
| 446 |
// to be solved. |
|
| 446 |
// remember about the double cover or unit quaternions! |
|
| 447 | 447 |
|
| 448 |
boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex)
|
|
| 448 |
private int mulQuat(int q1, int q2)
|
|
| 449 | 449 |
{
|
| 450 |
return cubit.mQuatIndex == quatIndex; |
|
| 450 |
Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]); |
|
| 451 |
|
|
| 452 |
float rX = result.get0(); |
|
| 453 |
float rY = result.get1(); |
|
| 454 |
float rZ = result.get2(); |
|
| 455 |
float rW = result.get3(); |
|
| 456 |
|
|
| 457 |
final float MAX_ERROR = 0.1f; |
|
| 458 |
float dX,dY,dZ,dW; |
|
| 459 |
|
|
| 460 |
for(int i=0; i<QUATS.length; i++) |
|
| 461 |
{
|
|
| 462 |
dX = QUATS[i].get0() - rX; |
|
| 463 |
dY = QUATS[i].get1() - rY; |
|
| 464 |
dZ = QUATS[i].get2() - rZ; |
|
| 465 |
dW = QUATS[i].get3() - rW; |
|
| 466 |
|
|
| 467 |
if( dX<MAX_ERROR && dX>-MAX_ERROR && |
|
| 468 |
dY<MAX_ERROR && dY>-MAX_ERROR && |
|
| 469 |
dZ<MAX_ERROR && dZ>-MAX_ERROR && |
|
| 470 |
dW<MAX_ERROR && dW>-MAX_ERROR ) return i; |
|
| 471 |
|
|
| 472 |
dX = QUATS[i].get0() + rX; |
|
| 473 |
dY = QUATS[i].get1() + rY; |
|
| 474 |
dZ = QUATS[i].get2() + rZ; |
|
| 475 |
dW = QUATS[i].get3() + rW; |
|
| 476 |
|
|
| 477 |
if( dX<MAX_ERROR && dX>-MAX_ERROR && |
|
| 478 |
dY<MAX_ERROR && dY>-MAX_ERROR && |
|
| 479 |
dZ<MAX_ERROR && dZ>-MAX_ERROR && |
|
| 480 |
dW<MAX_ERROR && dW>-MAX_ERROR ) return i; |
|
| 481 |
} |
|
| 482 |
|
|
| 483 |
return -1; |
|
| 484 |
} |
|
| 485 |
|
|
| 486 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 487 |
// Dino is solved if and only if: |
|
| 488 |
// |
|
| 489 |
// All four 'X' cubits (i.e. those whose longest edge goes along the X axis) are rotated |
|
| 490 |
// by the same quaternion qX, similarly all four 'Y' cubits by the same qY and all four 'Z' |
|
| 491 |
// by the same qZ, and then either: |
|
| 492 |
// |
|
| 493 |
// a) qX = qY = qZ |
|
| 494 |
// b) qY = qX*Q2 and qZ = qX*Q8 (i.e. swap of WHITE and YELLOW faces) |
|
| 495 |
// c) qX = qY*Q2 and qZ = qY*Q10 (i.e. swap of BLUE and GREEN faces) |
|
| 496 |
// d) qX = qZ*Q8 and qY = qZ*Q10 (i.e. swap of RED and BROWN faces) |
|
| 497 |
// |
|
| 498 |
// BUT: cases b), c) and d) are really the same - it's all just a mirror image of the original. |
|
| 499 |
// |
|
| 500 |
// X cubits: 0, 2, 8, 10 |
|
| 501 |
// Y cubits: 1, 3, 9, 11 |
|
| 502 |
// Z cubits: 4, 5, 6, 7 |
|
| 503 |
|
|
| 504 |
public boolean isSolved() |
|
| 505 |
{
|
|
| 506 |
int qX = CUBITS[0].mQuatIndex; |
|
| 507 |
int qY = CUBITS[1].mQuatIndex; |
|
| 508 |
int qZ = CUBITS[4].mQuatIndex; |
|
| 509 |
|
|
| 510 |
if( CUBITS[2].mQuatIndex != qX || CUBITS[8].mQuatIndex != qX || CUBITS[10].mQuatIndex != qX || |
|
| 511 |
CUBITS[3].mQuatIndex != qY || CUBITS[9].mQuatIndex != qY || CUBITS[11].mQuatIndex != qY || |
|
| 512 |
CUBITS[5].mQuatIndex != qZ || CUBITS[6].mQuatIndex != qZ || CUBITS[ 7].mQuatIndex != qZ ) |
|
| 513 |
{
|
|
| 514 |
return false; |
|
| 515 |
} |
|
| 516 |
|
|
| 517 |
return ( qX==qY && qX==qZ ) || ( qY==mulQuat(qX,2) && qZ==mulQuat(qX,8) ); |
|
| 451 | 518 |
} |
| 452 | 519 |
|
| 453 | 520 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| src/main/java/org/distorted/objects/RubikObject.java | ||
|---|---|---|
| 68 | 68 |
|
| 69 | 69 |
final Static3D[] ROTATION_AXIS; |
| 70 | 70 |
final Static4D[] QUATS; |
| 71 |
final Cubit[] CUBITS; |
|
| 71 | 72 |
final int NUM_FACES; |
| 72 | 73 |
final int NUM_CUBIT_FACES; |
| 73 | 74 |
final int NUM_AXIS; |
| 75 |
final int NUM_CUBITS; |
|
| 74 | 76 |
|
| 75 | 77 |
private static float mInitScreenRatio,mObjectScreenRatio; |
| 76 | 78 |
|
| 77 |
private final int NUM_CUBITS; |
|
| 78 | 79 |
private final int mNodeSize; |
| 79 | 80 |
private int mRotRowBitmap; |
| 80 | 81 |
private int mRotAxis; |
| 81 | 82 |
private Static3D[] mOrigPos; |
| 82 | 83 |
private Static3D mNodeScale; |
| 83 | 84 |
private Static4D mQuat; |
| 84 |
private Cubit[] mCubits; |
|
| 85 | 85 |
private int mSize; |
| 86 | 86 |
private RubikObjectList mList; |
| 87 | 87 |
private MeshBase mMesh; |
| ... | ... | |
| 146 | 146 |
MatrixEffectScale nodeScaleEffect = new MatrixEffectScale(mNodeScale); |
| 147 | 147 |
nodeEffects.apply(nodeScaleEffect); |
| 148 | 148 |
|
| 149 |
CUBITS = new Cubit[NUM_CUBITS]; |
|
| 149 | 150 |
createMeshAndCubits(list,res); |
| 150 | 151 |
|
| 151 | 152 |
mTexture = new DistortedTexture(); |
| ... | ... | |
| 174 | 175 |
|
| 175 | 176 |
private void createMeshAndCubits(RubikObjectList list, Resources res) |
| 176 | 177 |
{
|
| 177 |
mCubits = new Cubit[NUM_CUBITS]; |
|
| 178 |
|
|
| 179 | 178 |
if( mCreateFromDMesh ) |
| 180 | 179 |
{
|
| 181 | 180 |
int sizeIndex = RubikObjectList.getSizeIndex(list.ordinal(),mSize); |
| ... | ... | |
| 196 | 195 |
|
| 197 | 196 |
for(int i=0; i<NUM_CUBITS; i++) |
| 198 | 197 |
{
|
| 199 |
mCubits[i] = new Cubit(this,mOrigPos[i]);
|
|
| 200 |
mMesh.setEffectAssociation(i, mCubits[i].computeAssociation(), 0);
|
|
| 198 |
CUBITS[i] = new Cubit(this,mOrigPos[i]);
|
|
| 199 |
mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(), 0);
|
|
| 201 | 200 |
} |
| 202 | 201 |
} |
| 203 | 202 |
else |
| ... | ... | |
| 206 | 205 |
|
| 207 | 206 |
for(int i=0; i<NUM_CUBITS; i++) |
| 208 | 207 |
{
|
| 209 |
mCubits[i] = new Cubit(this,mOrigPos[i]);
|
|
| 208 |
CUBITS[i] = new Cubit(this,mOrigPos[i]);
|
|
| 210 | 209 |
cubitMesh[i] = createCubitMesh(i); |
| 211 | 210 |
cubitMesh[i].apply(new MatrixEffectMove(mOrigPos[i]),1,0); |
| 212 |
cubitMesh[i].setEffectAssociation(0, mCubits[i].computeAssociation(), 0);
|
|
| 211 |
cubitMesh[i].setEffectAssociation(0, CUBITS[i].computeAssociation(), 0);
|
|
| 213 | 212 |
} |
| 214 | 213 |
|
| 215 | 214 |
mMesh = new MeshJoined(cubitMesh); |
| ... | ... | |
| 276 | 275 |
|
| 277 | 276 |
private boolean belongsToRotation( int cubit, int axis, int rowBitmap) |
| 278 | 277 |
{
|
| 279 |
int cubitRow = (int)(mCubits[cubit].mRotationRow[axis]+0.5f);
|
|
| 278 |
int cubitRow = (int)(CUBITS[cubit].mRotationRow[axis]+0.5f);
|
|
| 280 | 279 |
return ((1<<cubitRow)&rowBitmap)!=0; |
| 281 | 280 |
} |
| 282 | 281 |
|
| ... | ... | |
| 317 | 316 |
for(int j=0; j<NUM_CUBITS; j++) |
| 318 | 317 |
if( belongsToRotation(j,axis,rowBitmap) ) |
| 319 | 318 |
{
|
| 320 |
index = mCubits[j].removeRotationNow(quat);
|
|
| 321 |
mMesh.setEffectAssociation(j,mCubits[j].computeAssociation(),index);
|
|
| 319 |
index = CUBITS[j].removeRotationNow(quat);
|
|
| 320 |
mMesh.setEffectAssociation(j, CUBITS[j].computeAssociation(),index);
|
|
| 322 | 321 |
} |
| 323 | 322 |
} |
| 324 | 323 |
} |
| ... | ... | |
| 332 | 331 |
boolean isOnFace( int cubit, int axis, int row) |
| 333 | 332 |
{
|
| 334 | 333 |
final float MAX_ERROR = 0.0001f; |
| 335 |
float diff = mCubits[cubit].mRotationRow[axis] - row;
|
|
| 334 |
float diff = CUBITS[cubit].mRotationRow[axis] - row;
|
|
| 336 | 335 |
return diff*diff < MAX_ERROR; |
| 337 | 336 |
} |
| 338 | 337 |
|
| ... | ... | |
| 433 | 432 |
|
| 434 | 433 |
public void savePreferences(SharedPreferences.Editor editor) |
| 435 | 434 |
{
|
| 436 |
for(int i=0; i<NUM_CUBITS; i++) mCubits[i].savePreferences(editor);
|
|
| 435 |
for(int i=0; i<NUM_CUBITS; i++) CUBITS[i].savePreferences(editor);
|
|
| 437 | 436 |
} |
| 438 | 437 |
|
| 439 | 438 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 442 | 441 |
{
|
| 443 | 442 |
for(int i=0; i<NUM_CUBITS; i++) |
| 444 | 443 |
{
|
| 445 |
int index = mCubits[i].restorePreferences(preferences);
|
|
| 446 |
mMesh.setEffectAssociation(i,mCubits[i].computeAssociation(),index);
|
|
| 444 |
int index = CUBITS[i].restorePreferences(preferences);
|
|
| 445 |
mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),index);
|
|
| 447 | 446 |
} |
| 448 | 447 |
} |
| 449 | 448 |
|
| ... | ... | |
| 474 | 473 |
{
|
| 475 | 474 |
for(int i=0; i<NUM_CUBITS; i++) |
| 476 | 475 |
{
|
| 477 |
mCubits[i].solve(); |
|
| 478 |
mMesh.setEffectAssociation(i, mCubits[i].computeAssociation(), 0); |
|
| 479 |
} |
|
| 480 |
} |
|
| 481 |
|
|
| 482 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 483 |
|
|
| 484 |
public boolean isSolved() |
|
| 485 |
{
|
|
| 486 |
int index = mCubits[0].mQuatIndex; |
|
| 487 |
|
|
| 488 |
for(int i=1; i<NUM_CUBITS; i++) |
|
| 489 |
{
|
|
| 490 |
if( !thereIsNoVisibleDifference(mCubits[i], index) ) return false; |
|
| 476 |
CUBITS[i].solve(); |
|
| 477 |
mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(), 0); |
|
| 491 | 478 |
} |
| 492 |
|
|
| 493 |
return true; |
|
| 494 | 479 |
} |
| 495 | 480 |
|
| 496 | 481 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 625 | 610 |
for(int i=0; i<NUM_CUBITS; i++) |
| 626 | 611 |
if( belongsToRotation(i,mRotAxis,mRotRowBitmap) ) |
| 627 | 612 |
{
|
| 628 |
int index = mCubits[i].removeRotationNow(quat);
|
|
| 629 |
mMesh.setEffectAssociation(i,mCubits[i].computeAssociation(),index);
|
|
| 613 |
int index = CUBITS[i].removeRotationNow(quat);
|
|
| 614 |
mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),index);
|
|
| 630 | 615 |
} |
| 631 | 616 |
} |
| 632 | 617 |
|
| ... | ... | |
| 652 | 637 |
|
| 653 | 638 |
for(int i=0; i<NUM_CUBITS; i++) |
| 654 | 639 |
{
|
| 655 |
dist = mCubits[i].getDistSquared(point3D);
|
|
| 640 |
dist = CUBITS[i].getDistSquared(point3D);
|
|
| 656 | 641 |
if( dist<minDist ) |
| 657 | 642 |
{
|
| 658 | 643 |
minDist = dist; |
| ... | ... | |
| 703 | 688 |
abstract int getFaceColor(int cubit, int cubitface, int size); |
| 704 | 689 |
abstract float returnMultiplier(); |
| 705 | 690 |
abstract float[] getRowChances(); |
| 706 |
abstract boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex); |
|
| 707 | 691 |
|
| 692 |
public abstract boolean isSolved(); |
|
| 708 | 693 |
public abstract Static3D[] getRotationAxis(); |
| 709 | 694 |
public abstract int getBasicAngle(); |
| 710 | 695 |
public abstract int computeRowFromOffset(float offset); |
| src/main/java/org/distorted/objects/RubikPyraminx.java | ||
|---|---|---|
| 486 | 486 |
return 0; |
| 487 | 487 |
} |
| 488 | 488 |
|
| 489 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 490 |
|
|
| 491 |
public boolean isSolved() |
|
| 492 |
{
|
|
| 493 |
int index = CUBITS[0].mQuatIndex; |
|
| 494 |
|
|
| 495 |
for(int i=1; i<NUM_CUBITS; i++) |
|
| 496 |
{
|
|
| 497 |
if( !thereIsNoVisibleDifference(CUBITS[i], index) ) return false; |
|
| 498 |
} |
|
| 499 |
|
|
| 500 |
return true; |
|
| 501 |
} |
|
| 502 |
|
|
| 489 | 503 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 490 | 504 |
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different |
| 491 | 505 |
// then if it were rotated by quaternion 'quat'. |
| ... | ... | |
| 496 | 510 |
// a) is a corner or edge and the quaternions are the same |
| 497 | 511 |
// b) is inside one of the faces and after rotations by both quats it ends up on the same face. |
| 498 | 512 |
|
| 499 |
boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex) |
|
| 513 |
private boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex)
|
|
| 500 | 514 |
{
|
| 501 | 515 |
if ( cubit.mQuatIndex == quatIndex ) return true; |
| 502 | 516 |
|
Also available in: Unified diff
Finally fix the Dino's 'isSolved()' - Dino can be mirrored and then it is also solved!