Revision d0418bda
Added by Leszek Koltunski over 6 years ago
| 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
Improve the Rubik App - rotation works now.