Revision 168b6b56
Added by Leszek Koltunski over 4 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!)