Project

General

Profile

« Previous | Next » 

Revision 8d50e08d

Added by Leszek Koltunski almost 4 years ago

Initial attempt at two-finger rotation.
Mostly works; still, one corner case doesnt:

- put two fingers down, start rotating
- lift one of them up
- put it back down

depending if we lifted the first or second finger, weird things may happen.

View differences:

src/main/java/org/distorted/main/RubikSurfaceView.java
42 42
public class RubikSurfaceView extends GLSurfaceView
43 43
{
44 44
    private static final int NUM_SPEED_PROBES = 10;
45
    private static final int INVALID_POINTER_ID = -1;
45 46

  
46 47
    public static final int MODE_ROTATE  = 0;
47 48
    public static final int MODE_DRAG    = 1;
......
72 73
    private boolean mDragging, mBeginningRotation, mContinuingRotation;
73 74
    private int mScreenWidth, mScreenHeight, mScreenMin;
74 75

  
75
    private float mX, mY;
76
    private int mPtrID1, mPtrID2;
77
    private float mX, mY, mBegX1, mBegY1, mBegX2, mBegY2;
76 78
    private float mStartRotX, mStartRotY;
77 79
    private float mAxisX, mAxisY;
78 80
    private float mRotationFactor;
......
156 158
      mMovement = movement;
157 159
      }
158 160

  
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

  
163
    private Static4D quatFromAngle(float angle)
164
      {
165
      float cosA = (float)Math.cos(angle);
166
      float sinA =-(float)Math.sin(angle);
167

  
168
      return new Static4D(0, 0, sinA, cosA);
169
      }
170

  
159 171
///////////////////////////////////////////////////////////////////////////////////////////////////
160 172

  
161 173
    private Static4D quatFromDrag(float dragX, float dragY)
......
383 395

  
384 396
///////////////////////////////////////////////////////////////////////////////////////////////////
385 397

  
386
    private void actionDown(float x, float y)
398
    private void dragging(float x, float y)
387 399
      {
388
      mX = x;
389
      mY = y;
390
      setUpDragOrRotate(true,x,y);
400
      mTempCurrent.set(quatFromDrag(mX-x,y-mY));
401
      mPreRender.setQuatCurrentOnNextRender();
402

  
403
      if( retFingerDragDistanceInInches(mX,mY,x,y) > DIRECTION_SENSITIVITY )
404
        {
405
        mX = x;
406
        mY = y;
407
        mTempAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated));
408
        mTempCurrent.set(0f, 0f, 0f, 1f);
409
        mPreRender.setQuatCurrentOnNextRender();
410
        mPreRender.setQuatAccumulatedOnNextRender();
411
        }
391 412
      }
392 413

  
393 414
///////////////////////////////////////////////////////////////////////////////////////////////////
394 415

  
395
    private void actionMove(float x, float y)
416
    private void continuingRotation(float x, float y)
396 417
      {
397
      if( mBeginningRotation )
398
        {
399
        if( retFingerDragDistanceInInches(mX,mY,x,y) > ROTATION_SENSITIVITY )
400
          {
401
          mStartRotX = x;
402
          mStartRotY = y;
403

  
404
          Static4D touchPoint2 = new Static4D(x, y, 0, 0);
405
          Static4D rotatedTouchPoint2= rotateVectorByInvertedQuat(touchPoint2, mQuatAccumulated);
418
      float angle = continueRotation(x-mStartRotX,y-mStartRotY);
419
      mCurrentAngle = SWIPING_SENSITIVITY*angle;
420
      mPreRender.getObject().continueRotation(mCurrentAngle);
406 421

  
407
          Static2D res = mMovement.newRotation(rotatedTouchPoint2);
408
          RubikObject object = mPreRender.getObject();
422
      addSpeedProbe(x,y);
423
      }
409 424

  
410
          mCurrentAxis = (int)res.get0();
411
          float offset = res.get1();
412
          mCurrentRow = (int)(object.returnMultiplier()*offset);
413
          computeCurrentAxis( object.getRotationAxis()[mCurrentAxis] );
414
          mRotationFactor = object.returnRotationFactor(offset);
425
///////////////////////////////////////////////////////////////////////////////////////////////////
415 426

  
416
          object.beginNewRotation( mCurrentAxis, mCurrentRow );
427
    private void beginningRotation(float x, float y)
428
      {
429
      mStartRotX = x;
430
      mStartRotY = y;
417 431

  
418
          if( RubikState.getCurrentState()==RubikState.READ )
419
            {
420
            RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
421
            solving.resetElapsed();
432
      Static4D touchPoint2 = new Static4D(x, y, 0, 0);
433
      Static4D rotatedTouchPoint2= rotateVectorByInvertedQuat(touchPoint2, mQuatAccumulated);
422 434

  
423
            final RubikActivity act = (RubikActivity)getContext();
435
      Static2D res = mMovement.newRotation(rotatedTouchPoint2);
436
      RubikObject object = mPreRender.getObject();
424 437

  
425
            act.runOnUiThread(new Runnable()
426
              {
427
              @Override
428
              public void run()
429
                {
430
                RubikState.switchState( act, RubikState.SOLV);
431
                }
432
              });
433
            }
438
      mCurrentAxis = (int)res.get0();
439
      float offset = res.get1();
440
      mCurrentRow = (int)(object.returnMultiplier()*offset);
441
      computeCurrentAxis( object.getRotationAxis()[mCurrentAxis] );
442
      mRotationFactor = object.returnRotationFactor(offset);
434 443

  
435
          addSpeedProbe(x,y);
444
      object.beginNewRotation( mCurrentAxis, mCurrentRow );
436 445

  
437
          mBeginningRotation = false;
438
          mContinuingRotation= true;
439
          }
440
        }
441
      else if( mContinuingRotation )
446
      if( RubikState.getCurrentState()==RubikState.READ )
442 447
        {
443
        float angle = continueRotation(x-mStartRotX,y-mStartRotY);
444
        mCurrentAngle = SWIPING_SENSITIVITY*angle;
445
        mPreRender.getObject().continueRotation(mCurrentAngle);
448
        RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
449
        solving.resetElapsed();
450

  
451
        final RubikActivity act = (RubikActivity)getContext();
446 452

  
447
        addSpeedProbe(x,y);
453
        act.runOnUiThread(new Runnable()
454
          {
455
          @Override
456
          public void run()
457
            {
458
            RubikState.switchState( act, RubikState.SOLV);
459
            }
460
          });
448 461
        }
449
      else if( mDragging )
462

  
463
      addSpeedProbe(x,y);
464

  
465
      mBeginningRotation = false;
466
      mContinuingRotation= true;
467
      }
468

  
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

  
471
    private void actionMove(MotionEvent event)
472
      {
473
      if( mPtrID2 == INVALID_POINTER_ID )
450 474
        {
451
        mTempCurrent.set(quatFromDrag(mX-x,y-mY));
452
        mPreRender.setQuatCurrentOnNextRender();
475
        float x = (event.getX() - mScreenWidth*0.5f)/mScreenMin;
476
        float y = (mScreenHeight*0.5f -event.getY())/mScreenMin;
453 477

  
454
        if( retFingerDragDistanceInInches(mX,mY,x,y) > DIRECTION_SENSITIVITY )
478
        if( mBeginningRotation )
455 479
          {
456
          mX = x;
457
          mY = y;
458
          mTempAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated));
459
          mTempCurrent.set(0f, 0f, 0f, 1f);
460
          mPreRender.setQuatCurrentOnNextRender();
461
          mPreRender.setQuatAccumulatedOnNextRender();
480
          if( retFingerDragDistanceInInches(mX,mY,x,y) > ROTATION_SENSITIVITY )
481
            {
482
            beginningRotation(x,y);
483
            }
484
          }
485
        else if( mContinuingRotation )
486
          {
487
          continuingRotation(x,y);
488
          }
489
        else if( mDragging )
490
          {
491
          dragging(x,y);
492
          }
493
        else
494
          {
495
          setUpDragOrRotate(false,x,y);
462 496
          }
463 497
        }
464 498
      else
465 499
        {
466
        setUpDragOrRotate(false,x,y);
500
        int index1 = event.findPointerIndex(mPtrID1);
501
        int index2 = event.findPointerIndex(mPtrID2);
502

  
503
        float nX1 = event.getX(index1);
504
        float nY1 = event.getY(index1);
505
        float nX2 = event.getX(index2);
506
        float nY2 = event.getY(index2);
507

  
508
        float angle1 = (float) Math.atan2(mBegY1-mBegY2, mBegX1-mBegX2);
509
        float angle2 = (float) Math.atan2( nY1-nY2     , nX1-nX2      );
510

  
511
        mTempCurrent.set(quatFromAngle(angle1-angle2));
512
        mPreRender.setQuatCurrentOnNextRender();
467 513
        }
468 514
      }
469 515

  
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517

  
518
    private void actionDown(MotionEvent event)
519
      {
520
      mPtrID1 = event.getPointerId(0);
521

  
522
      mX = (event.getX() - mScreenWidth*0.5f)/mScreenMin;
523
      mY = (mScreenHeight*0.5f -event.getY())/mScreenMin;
524

  
525
      setUpDragOrRotate(true,mX,mY);
526
      }
527

  
470 528
///////////////////////////////////////////////////////////////////////////////////////////////////
471 529

  
472 530
    private void actionUp()
473 531
      {
532
      mPtrID1 = INVALID_POINTER_ID;
533

  
474 534
      if( mDragging )
475 535
        {
476 536
        mTempAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated));
......
498 558
        }
499 559
      }
500 560

  
561
///////////////////////////////////////////////////////////////////////////////////////////////////
562

  
563
    private void actionDown2(MotionEvent event)
564
      {
565
      mPtrID2 = event.getPointerId(event.getActionIndex());
566

  
567
      int index1 = event.findPointerIndex(mPtrID1);
568
      mBegX1 = event.getX(index1);
569
      mBegY1 = event.getY(index1);
570

  
571
      mX = (mBegX1 - mScreenWidth*0.5f)/mScreenMin;
572
      mY = (mScreenHeight*0.5f -mBegY1)/mScreenMin;
573

  
574
      int index2 = event.findPointerIndex(mPtrID2);
575
      mBegX2 = event.getX(index2);
576
      mBegY2 = event.getY(index2);
577
      }
578

  
579
///////////////////////////////////////////////////////////////////////////////////////////////////
580

  
581
    private void actionUp2()
582
      {
583
      mPtrID2 = INVALID_POINTER_ID;
584
      }
585

  
501 586
///////////////////////////////////////////////////////////////////////////////////////////////////
502 587
// PUBLIC API
503 588
///////////////////////////////////////////////////////////////////////////////////////////////////
......
517 602
        mFirstIndex =0;
518 603
        mLastIndex  =0;
519 604

  
605
        mPtrID1 = INVALID_POINTER_ID;
606
        mPtrID2 = INVALID_POINTER_ID;
607

  
520 608
        mRenderer  = new RubikRenderer(this);
521 609
        mPreRender = new RubikPreRender(this);
522 610

  
......
542 630
    @Override
543 631
    public boolean onTouchEvent(MotionEvent event)
544 632
      {
545
      int action = event.getAction();
546
      float x = (event.getX() - mScreenWidth*0.5f)/mScreenMin;
547
      float y = (mScreenHeight*0.5f -event.getY())/mScreenMin;
633
      int action = event.getActionMasked();
548 634

  
549 635
      switch(action)
550 636
         {
551
         case MotionEvent.ACTION_DOWN: actionDown(x,y); break;
552
         case MotionEvent.ACTION_MOVE: actionMove(x,y); break;
553
         case MotionEvent.ACTION_UP  : actionUp()     ; break;
637
         case MotionEvent.ACTION_DOWN        : actionDown(event) ; break;
638
         case MotionEvent.ACTION_MOVE        : actionMove(event) ; break;
639
         case MotionEvent.ACTION_UP          : actionUp()        ; break;
640
         case MotionEvent.ACTION_POINTER_DOWN: actionDown2(event); break;
641
         case MotionEvent.ACTION_POINTER_UP  : actionUp2()       ; break;
554 642
         }
555 643

  
556 644
      return true;

Also available in: Unified diff