Project

General

Profile

« Previous | Next » 

Revision d0418bda

Added by Leszek Koltunski over 5 years ago

Improve the Rubik App - rotation works now.

View differences:

src/main/java/org/distorted/examples/rubik/RubikRenderer.java
46 46

  
47 47
class RubikRenderer implements GLSurfaceView.Renderer
48 48
{
49
            static final int NUM_CUBES =   3;
49
            static final int NUM_CUBES =   4;
50 50
    private static final int SIZE      = 200;
51 51
    private static final float CUBE_SCREEN_RATIO = 0.5f;
52 52

  
......
63 63
    private Static4D[][][] mQuatScramble;
64 64
    private Static3D[][][] mRotationAxis;
65 65
    private Dynamic1D[][][] mRotationAngle;
66
    private Static3D[][][] mCurrentPosition;
66 67
    private Static1D mRotationAngleStatic;
67
    private int mRotAxis;
68
    private int mRotRow;
68
    private int mRotAxis, mRotRow;
69 69

  
70 70
    private int mScreenWidth, mScreenHeight;
71 71

  
......
91 91
      mEffects = new DistortedEffects[NUM_CUBES][NUM_CUBES][NUM_CUBES];
92 92
      Static3D[][][] cubeVectors = new Static3D[NUM_CUBES][NUM_CUBES][NUM_CUBES];
93 93

  
94
      mQuatScramble = new Static4D[NUM_CUBES][NUM_CUBES][NUM_CUBES];
95
      mRotationAxis = new Static3D[NUM_CUBES][NUM_CUBES][NUM_CUBES];
96
      mRotationAngle= new Dynamic1D[NUM_CUBES][NUM_CUBES][NUM_CUBES];
94
      mQuatScramble   = new Static4D[NUM_CUBES][NUM_CUBES][NUM_CUBES];
95
      mRotationAxis   = new Static3D[NUM_CUBES][NUM_CUBES][NUM_CUBES];
96
      mRotationAngle  = new Dynamic1D[NUM_CUBES][NUM_CUBES][NUM_CUBES];
97
      mCurrentPosition= new Static3D[NUM_CUBES][NUM_CUBES][NUM_CUBES];
97 98

  
98
      float sinkDegree = 3.0f - 1.7f/NUM_CUBES; // f(1)=1.3, f(inf)=3
99
      float sinkDegree = 3.0f - 1.8f/NUM_CUBES; // f(1)=1.2, f(inf)=3
99 100

  
100 101
      VertexEffectSink sink = new VertexEffectSink( new Static1D(sinkDegree),
101 102
                                                    new Static3D(SIZE*0.5f, SIZE*0.5f, SIZE*0.5f),
......
149 150
              tmpTop   = (y== NUM_CUBES -1 ? mapTop   :mapBlack);
150 151
              tmpBottom= (y==            0 ? mapBottom:mapBlack);
151 152

  
152
              mCubes[x][y][z] = new MeshCubes(vertices,vertices,vertices, tmpFront, tmpBack, tmpLeft, tmpRight, tmpTop, tmpBottom);
153
              cubeVectors[x][y][z] = new Static3D( SIZE*(x-nc), SIZE*(y-nc), SIZE*(z-nc) );
154
              mQuatScramble[x][y][z] = new Static4D(0,0,0,1);
155
              mRotationAngle[x][y][z] = new Dynamic1D();
156
              mRotationAxis[x][y][z] = new Static3D(1,0,0);
153
              mCubes[x][y][z]           = new MeshCubes(vertices,vertices,vertices, tmpFront, tmpBack, tmpLeft, tmpRight, tmpTop, tmpBottom);
154
              cubeVectors[x][y][z]      = new Static3D( SIZE*(x-nc), SIZE*(y-nc), SIZE*(z-nc) );
155
              mQuatScramble[x][y][z]    = new Static4D(0,0,0,1);
156
              mRotationAngle[x][y][z]   = new Dynamic1D();
157
              mRotationAxis[x][y][z]    = new Static3D(1,0,0);
158
              mCurrentPosition[x][y][z] = new Static3D(x,y,z);
157 159

  
158 160
              mEffects[x][y][z] = new DistortedEffects();
159 161
              mEffects[x][y][z].apply(sink);
......
324 326

  
325 327
    void continueRotation(float angle)
326 328
      {
327
      mRotationAngleStatic.set1(120.0f*angle/mScreenMin);
329
      mRotationAngleStatic.set1(200.0f*angle/mScreenMin);
328 330
      }
329 331

  
330 332
///////////////////////////////////////////////////////////////////////////////////////////////////
......
360 362
                {
361 363
                mRotationAngle[x][y][z].removeAll();
362 364
                mQuatScramble[x][y][z].set(RubikSurfaceView.quatMultiply(quat,mQuatScramble[x][y][z]));
365
                modifyCurrentPosition(x,y,z,quat);
363 366
                }
364 367
              }
365 368
      }
......
370 373
      {
371 374
      switch(vector)
372 375
        {
373
        case RubikSurfaceView.VECTX: return x==row;
374
        case RubikSurfaceView.VECTY: return y==row;
375
        case RubikSurfaceView.VECTZ: return z==row;
376
        case RubikSurfaceView.VECTX: return mCurrentPosition[x][y][z].get1()==row;
377
        case RubikSurfaceView.VECTY: return mCurrentPosition[x][y][z].get2()==row;
378
        case RubikSurfaceView.VECTZ: return mCurrentPosition[x][y][z].get3()==row;
376 379
        }
377 380

  
378 381
      return false;
379 382
      }
380 383

  
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385

  
386
    private void modifyCurrentPosition(int x, int y, int z, Static4D quat)
387
      {
388
      Static3D current = mCurrentPosition[x][y][z];
389
      float beforeX = current.get1();
390
      float beforeY = current.get2();
391
      float beforeZ = current.get3();
392

  
393
      float diff = 0.5f*(NUM_CUBES-1);
394

  
395
      float cubitCenterX = beforeX - diff;
396
      float cubitCenterY = beforeY - diff;
397
      float cubitCenterZ = beforeZ - diff;
398

  
399
      Static4D cubitCenter =  new Static4D(cubitCenterX, cubitCenterY, cubitCenterZ, 0);
400
      Static4D rotatedCenter = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat);
401

  
402
      float rotatedX = rotatedCenter.get1() + diff;
403
      float rotatedY = rotatedCenter.get2() + diff;
404
      float rotatedZ = rotatedCenter.get3() + diff;
405

  
406
      int roundedX = (int)(rotatedX+0.1f);
407
      int roundedY = (int)(rotatedY+0.1f);
408
      int roundedZ = (int)(rotatedZ+0.1f);
409

  
410
      //android.util.Log.e("rubik", "before: ("+((int)beforeX)+","+((int)beforeY)+","+((int)beforeZ)+") after: ("+roundedX+","+roundedY+","+roundedZ+")");
411

  
412
      mCurrentPosition[x][y][z].set1(roundedX);
413
      mCurrentPosition[x][y][z].set2(roundedY);
414
      mCurrentPosition[x][y][z].set3(roundedZ);
415
      }
416

  
381 417
///////////////////////////////////////////////////////////////////////////////////////////////////
382 418

  
383 419
    float getScreenWidth()
src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
100 100
         {
101 101
         case MotionEvent.ACTION_DOWN: mX = x;
102 102
                                       mY = y;
103

  
104 103
                                       mLastTouchedFace = faceTouched(x,y);
105 104

  
106
                                       if( mLastTouchedFace != NONE )
107
                                         {
108
                                         mRotating = true;
109
                                         }
110
                                       else
111
                                         {
112
                                         mDragging = true;
113
                                         }
105
                                       if( mLastTouchedFace != NONE ) mRotating = true;
106
                                       else                           mDragging = true;
107

  
114 108
                                       break;
115 109
         case MotionEvent.ACTION_MOVE: if( mDragging )
116 110
                                         {
......
297 291
      return new Static4D(tx,ty,tz,tw);
298 292
      }
299 293

  
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295
// rotate 'vector' by quat^(-1)  ( i.e. return (quat^-1)*vector*quat )
296

  
297
    static Static4D rotateVectorByInvertedQuat(Static4D vector, Static4D quat)
298
      {
299
      float qx = quat.get1();
300
      float qy = quat.get2();
301
      float qz = quat.get3();
302
      float qw = quat.get4();
303

  
304
      Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw);
305
      Static4D tmp = quatMultiply(quatInverted,vector);
306

  
307
      return quatMultiply(tmp,quat);
308
      }
309

  
310

  
311
///////////////////////////////////////////////////////////////////////////////////////////////////
312
// rotate 'vector' by quat  ( i.e. return quat*vector*(quat^-1) )
313

  
314
    static Static4D rotateVectorByQuat(Static4D vector, Static4D quat)
315
      {
316
      float qx = quat.get1();
317
      float qy = quat.get2();
318
      float qz = quat.get3();
319
      float qw = quat.get4();
320

  
321
      Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw);
322
      Static4D tmp = quatMultiply(quat,vector);
323

  
324
      return quatMultiply(tmp,quatInverted);
325
      }
326

  
300 327
///////////////////////////////////////////////////////////////////////////////////////////////////
301 328

  
302 329
    private Static4D quatFromDrag(float dragX, float dragY)
303 330
      {
304 331
      float axisX = dragY;  // inverted X and Y - rotation axis is
305
      float axisY = dragX;  // perpendicular to (dragX,dragY)
332
      float axisY = dragX;  // perpendicular to (dragX,dragY)   Why not (-dragY, dragX) ? because Y axis is also inverted!
306 333
      float axisZ = 0;
307 334
      float axisL = (float)Math.sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);
308 335

  
......
321 348
      return new Static4D(0f, 0f, 0f, 1f);
322 349
      }
323 350

  
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325

  
326
    private int returnFrontFace()
327
      {
328
      Static4D rotated = rotateVector(new Static4D(0,0,1,0));
329

  
330
      float rotatedX = rotated.get1();
331
      float rotatedY = rotated.get2();
332
      float rotatedZ = rotated.get3();
333

  
334
      float absX = rotatedX>0 ? rotatedX : -rotatedX;
335
      float absY = rotatedY>0 ? rotatedY : -rotatedY;
336
      float absZ = rotatedZ>0 ? rotatedZ : -rotatedZ;
337

  
338
      if( absX>absY && absX>absZ ) return rotatedX>0 ? RIGHT:LEFT;
339
      if( absY>absX && absY>absZ ) return rotatedY>0 ? TOP:BOTTOM;
340
      if( absZ>absX && absZ>absY ) return rotatedZ>0 ? FRONT:BACK;
341

  
342
      return NONE;
343
      }
344

  
345 351
///////////////////////////////////////////////////////////////////////////////////////////////////
346 352

  
347 353
    private boolean faceIsVisible(int face)
......
349 355
      float cameraDistance = mRenderer.returnCameraDistance();
350 356
      float cubeHalfSize   = mRenderer.returnCubeSize()*0.5f;
351 357

  
352
      Static4D rotated = rotateVector(new Static4D(0,0,cameraDistance,0));
358
      Static4D rotated = rotateVectorByInvertedQuat(new Static4D(0,0,cameraDistance,0), mQuatAccumulated);
353 359

  
354 360
      switch(face)
355 361
        {
......
364 370
      return false;
365 371
      }
366 372

  
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368
// rotate 'vector' by quaternion q=mQuatAccumulated^(-1)  ( i.e. return (q^-1)*vector*q )
369

  
370
    private Static4D rotateVector(Static4D vector)
371
      {
372
      float qx = mQuatAccumulated.get1();
373
      float qy = mQuatAccumulated.get2();
374
      float qz = mQuatAccumulated.get3();
375
      float qw = mQuatAccumulated.get4();
376

  
377
      Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw);
378
      Static4D tmp = quatMultiply(quatInverted,vector);
379

  
380
      return quatMultiply(tmp,mQuatAccumulated);
381
      }
382

  
383 373
///////////////////////////////////////////////////////////////////////////////////////////////////
384 374

  
385 375
    private int faceTouched(int xTouch, int yTouch)
......
417 407
      float halfScrWidth  = mRenderer.getScreenWidth() *0.5f;
418 408
      float halfScrHeight = mRenderer.getScreenHeight()*0.5f;
419 409
      Static4D touchPoint = new Static4D(x-halfScrWidth, halfScrHeight-y, 0, 0);
420
      Static4D rotatedTouchPoint= rotateVector(touchPoint);
410
      Static4D rotatedTouchPoint= rotateVectorByInvertedQuat(touchPoint, mQuatAccumulated);
421 411

  
422 412
      mPoiX = rotatedTouchPoint.get1();
423 413
      mPoiY = rotatedTouchPoint.get2();
......
431 421
      float cameraDistance = mRenderer.returnCameraDistance();
432 422

  
433 423
      Static4D cameraPoint = new Static4D(0, 0, cameraDistance, 0);
434
      Static4D rotatedCamera= rotateVector(cameraPoint);
424
      Static4D rotatedCamera= rotateVectorByInvertedQuat(cameraPoint, mQuatAccumulated);
435 425

  
436 426
      mCamX = rotatedCamera.get1();
437 427
      mCamY = rotatedCamera.get2();

Also available in: Unified diff