Revision 168b6b56
Added by Leszek Koltunski over 5 years ago
| src/main/java/org/distorted/main/RubikPreRender.java | ||
|---|---|---|
| 65 | 65 |
private ActionFinishedListener mAddActionListener; |
| 66 | 66 |
private long mAddRotationID, mRemoveRotationID; |
| 67 | 67 |
private int mCubit, mFace, mNewColor; |
| 68 |
private int mNearestAngle; |
|
| 68 | 69 |
|
| 69 | 70 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 70 | 71 |
|
| ... | ... | |
| 224 | 225 |
mFinishRotation = false; |
| 225 | 226 |
mCanRotate = false; |
| 226 | 227 |
mCanPlay = false; |
| 227 |
mRotationFinishedID = mNewObject.finishRotationNow(this); |
|
| 228 |
mRotationFinishedID = mNewObject.finishRotationNow(this, mNearestAngle);
|
|
| 228 | 229 |
|
| 229 | 230 |
if( mRotationFinishedID==0 ) // failed to add effect - should never happen |
| 230 | 231 |
{
|
| ... | ... | |
| 366 | 367 |
|
| 367 | 368 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 368 | 369 |
|
| 369 |
void finishRotation() |
|
| 370 |
void finishRotation(int nearestAngle)
|
|
| 370 | 371 |
{
|
| 372 |
mNearestAngle = nearestAngle; |
|
| 371 | 373 |
mFinishRotation = true; |
| 372 | 374 |
} |
| 373 | 375 |
|
| src/main/java/org/distorted/main/RubikSurfaceView.java | ||
|---|---|---|
| 40 | 40 |
|
| 41 | 41 |
public class RubikSurfaceView extends GLSurfaceView |
| 42 | 42 |
{
|
| 43 |
private static final int NUM_SPEED_PROBES = 10; |
|
| 44 |
|
|
| 43 | 45 |
public static final int MODE_ROTATE = 0; |
| 44 | 46 |
public static final int MODE_DRAG = 1; |
| 45 | 47 |
public static final int MODE_REPLACE = 2; |
| ... | ... | |
| 75 | 77 |
private float mRotationFactor; |
| 76 | 78 |
private int mLastCubitColor, mLastCubitFace, mLastCubit; |
| 77 | 79 |
private int mCurrentAxis, mCurrentRow; |
| 78 |
private float mCurrentAngle; |
|
| 80 |
private float mCurrentAngle, mCurrRotSpeed; |
|
| 81 |
private float[] mLastAngles; |
|
| 82 |
private long[] mLastTimestamps; |
|
| 83 |
private int mFirstIndex, mLastIndex; |
|
| 79 | 84 |
|
| 80 | 85 |
private static Static4D mQuatCurrent = new Static4D(0,0,0,1); |
| 81 | 86 |
private static Static4D mQuatAccumulated= new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f); |
| ... | ... | |
| 315 | 320 |
return quatMultiply(tmp,quat); |
| 316 | 321 |
} |
| 317 | 322 |
|
| 323 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 324 |
|
|
| 325 |
private void addSpeedProbe(float angle) |
|
| 326 |
{
|
|
| 327 |
long currTime = System.currentTimeMillis(); |
|
| 328 |
boolean theSame = mLastIndex==mFirstIndex; |
|
| 329 |
|
|
| 330 |
mLastIndex++; |
|
| 331 |
if( mLastIndex>=NUM_SPEED_PROBES ) mLastIndex=0; |
|
| 332 |
|
|
| 333 |
mLastTimestamps[mLastIndex] = currTime; |
|
| 334 |
mLastAngles[mLastIndex] = angle; |
|
| 335 |
|
|
| 336 |
if( mLastIndex==mFirstIndex) |
|
| 337 |
{
|
|
| 338 |
mFirstIndex++; |
|
| 339 |
if( mFirstIndex>=NUM_SPEED_PROBES ) mFirstIndex=0; |
|
| 340 |
} |
|
| 341 |
|
|
| 342 |
if( theSame ) |
|
| 343 |
{
|
|
| 344 |
mLastTimestamps[mFirstIndex] = currTime; |
|
| 345 |
mLastAngles[mFirstIndex] = angle; |
|
| 346 |
} |
|
| 347 |
} |
|
| 348 |
|
|
| 349 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 350 |
|
|
| 351 |
private void computeCurrentSpeed() |
|
| 352 |
{
|
|
| 353 |
long firstTime = mLastTimestamps[mFirstIndex]; |
|
| 354 |
long lastTime = mLastTimestamps[mLastIndex]; |
|
| 355 |
float firstAngle = mLastAngles[mFirstIndex]; |
|
| 356 |
float lastAngle = mLastAngles[mLastIndex]; |
|
| 357 |
|
|
| 358 |
long timeDiff = lastTime-firstTime; |
|
| 359 |
|
|
| 360 |
mLastIndex = 0; |
|
| 361 |
mFirstIndex= 0; |
|
| 362 |
|
|
| 363 |
mCurrRotSpeed = timeDiff>0 ? (lastAngle-firstAngle)/timeDiff : 0; |
|
| 364 |
} |
|
| 365 |
|
|
| 318 | 366 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 319 | 367 |
// PUBLIC API |
| 320 | 368 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 326 | 374 |
if(!isInEditMode()) |
| 327 | 375 |
{
|
| 328 | 376 |
mLastCubitColor = -1; |
| 377 |
mCurrRotSpeed = 0.0f; |
|
| 378 |
|
|
| 379 |
mLastAngles = new float[NUM_SPEED_PROBES]; |
|
| 380 |
mLastTimestamps = new long[NUM_SPEED_PROBES]; |
|
| 381 |
mFirstIndex =0; |
|
| 382 |
mLastIndex =0; |
|
| 329 | 383 |
|
| 330 | 384 |
mRenderer = new RubikRenderer(this); |
| 331 | 385 |
mPreRender = new RubikPreRender(this); |
| ... | ... | |
| 390 | 444 |
}); |
| 391 | 445 |
} |
| 392 | 446 |
|
| 447 |
addSpeedProbe(0.0f); |
|
| 448 |
|
|
| 393 | 449 |
mBeginningRotation = false; |
| 394 | 450 |
mContinuingRotation= true; |
| 395 | 451 |
} |
| ... | ... | |
| 399 | 455 |
float angle = continueRotation(x-mStartRotX,y-mStartRotY); |
| 400 | 456 |
mCurrentAngle = SWIPING_SENSITIVITY*angle; |
| 401 | 457 |
mPreRender.getObject().continueRotation(mCurrentAngle); |
| 458 |
|
|
| 459 |
addSpeedProbe(mCurrentAngle); |
|
| 402 | 460 |
} |
| 403 | 461 |
else if( mDragging ) |
| 404 | 462 |
{
|
| ... | ... | |
| 430 | 488 |
|
| 431 | 489 |
if( mContinuingRotation ) |
| 432 | 490 |
{
|
| 433 |
mPreRender.finishRotation(); |
|
| 491 |
computeCurrentSpeed(); |
|
| 492 |
int angle = mPreRender.getObject().computeNearestAngle(mCurrentAngle, mCurrRotSpeed); |
|
| 493 |
mPreRender.finishRotation(angle); |
|
| 434 | 494 |
|
| 435 | 495 |
if( RubikState.getCurrentState()==RubikState.SOLV ) |
| 436 | 496 |
{
|
| 437 | 497 |
RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass(); |
| 438 | 498 |
|
| 439 |
int angle = mPreRender.getObject().computeNearestAngle(mCurrentAngle); |
|
| 440 |
|
|
| 441 | 499 |
if( angle!=0 ) |
| 442 | 500 |
solving.addMove(mCurrentAxis, mCurrentRow, angle); |
| 443 | 501 |
} |
| src/main/java/org/distorted/objects/RubikObject.java | ||
|---|---|---|
| 520 | 520 |
|
| 521 | 521 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 522 | 522 |
|
| 523 |
public long finishRotationNow(EffectListener listener) |
|
| 523 |
public long finishRotationNow(EffectListener listener, int nearestAngleInDegrees)
|
|
| 524 | 524 |
{
|
| 525 | 525 |
float angle = getAngle(); |
| 526 |
int nearestAngleInDegrees = computeNearestAngle(angle); |
|
| 527 | 526 |
mRotationAngleStatic.set0(angle); |
| 528 | 527 |
mRotationAngleFinal.set0(nearestAngleInDegrees); |
| 529 | 528 |
mRotationAngleMiddle.set0( nearestAngleInDegrees + (nearestAngleInDegrees-angle)*0.2f ); |
| ... | ... | |
| 561 | 560 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 562 | 561 |
|
| 563 | 562 |
public void removeRotationNow() |
| 564 |
{
|
|
| 565 |
float angle = getAngle(); |
|
| 566 |
int nearestAngleInDegrees = computeNearestAngle(angle); |
|
| 567 |
double nearestAngleInRadians = nearestAngleInDegrees*Math.PI/180; |
|
| 568 |
float sinA =-(float)Math.sin(nearestAngleInRadians*0.5); |
|
| 569 |
float cosA = (float)Math.cos(nearestAngleInRadians*0.5); |
|
| 570 |
float axisX = ROTATION_AXIS[mRotAxis].get0(); |
|
| 571 |
float axisY = ROTATION_AXIS[mRotAxis].get1(); |
|
| 572 |
float axisZ = ROTATION_AXIS[mRotAxis].get2(); |
|
| 573 |
Static4D quat = new Static4D( axisX*sinA, axisY*sinA, axisZ*sinA, cosA); |
|
| 574 |
|
|
| 575 |
mRotationAngle.removeAll(); |
|
| 576 |
mRotationAngleStatic.set0(0); |
|
| 577 |
|
|
| 578 |
for(int i=0; i<NUM_CUBITS; i++) |
|
| 579 |
if( belongsToRotation(i,mRotAxis,mRotRowBitmap) ) |
|
| 580 |
{
|
|
| 581 |
int index = mCubits[i].removeRotationNow(quat); |
|
| 582 |
mMesh.setEffectAssociation(i,mCubits[i].computeAssociation(),index); |
|
| 583 |
} |
|
| 584 |
} |
|
| 563 |
{
|
|
| 564 |
float angle = getAngle(); |
|
| 565 |
double nearestAngleInRadians = angle*Math.PI/180; |
|
| 566 |
float sinA =-(float)Math.sin(nearestAngleInRadians*0.5); |
|
| 567 |
float cosA = (float)Math.cos(nearestAngleInRadians*0.5); |
|
| 568 |
float axisX = ROTATION_AXIS[mRotAxis].get0(); |
|
| 569 |
float axisY = ROTATION_AXIS[mRotAxis].get1(); |
|
| 570 |
float axisZ = ROTATION_AXIS[mRotAxis].get2(); |
|
| 571 |
Static4D quat = new Static4D( axisX*sinA, axisY*sinA, axisZ*sinA, cosA); |
|
| 572 |
|
|
| 573 |
mRotationAngle.removeAll(); |
|
| 574 |
mRotationAngleStatic.set0(0); |
|
| 575 |
|
|
| 576 |
for(int i=0; i<NUM_CUBITS; i++) |
|
| 577 |
if( belongsToRotation(i,mRotAxis,mRotRowBitmap) ) |
|
| 578 |
{
|
|
| 579 |
int index = mCubits[i].removeRotationNow(quat); |
|
| 580 |
mMesh.setEffectAssociation(i,mCubits[i].computeAssociation(),index); |
|
| 581 |
} |
|
| 582 |
} |
|
| 585 | 583 |
|
| 586 | 584 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 587 | 585 |
|
| ... | ... | |
| 618 | 616 |
|
| 619 | 617 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 620 | 618 |
|
| 621 |
public int computeNearestAngle(float angle) |
|
| 619 |
public int computeNearestAngle(float angle, float speed)
|
|
| 622 | 620 |
{
|
| 623 | 621 |
final int NEAREST = 360/getBasicAngle(); |
| 624 | 622 |
|
| 625 |
int tmp = (int)((angle+NEAREST/2)/NEAREST); |
|
| 626 |
if( angle< -(NEAREST*0.5) ) tmp-=1; |
|
| 623 |
float angleAndSpeed = angle + 100*speed; |
|
| 624 |
|
|
| 625 |
int tmp1 = (int)((angle+NEAREST/2)/NEAREST); |
|
| 626 |
if( angle< -(NEAREST*0.5) ) tmp1-=1; |
|
| 627 |
|
|
| 628 |
int tmp2 = (int)((angleAndSpeed+NEAREST/2)/NEAREST); |
|
| 629 |
if( angleAndSpeed< -(NEAREST*0.5) ) tmp2-=1; |
|
| 627 | 630 |
|
| 628 |
return NEAREST*tmp;
|
|
| 631 |
return NEAREST*(tmp1==0 ? tmp2 : tmp1);
|
|
| 629 | 632 |
} |
| 630 | 633 |
|
| 631 | 634 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
Also available in: Unified diff
Improvements for the way we rotate layers of Objects. (take the speed into account - so even if we rotated a layer of a Cube to less than 45 degrees, but we did it fast, do a 90 degree rotation!)