Revision 0c5d8bf7
Added by Leszek Koltunski over 2 years ago
src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java | ||
---|---|---|
30 | 30 |
public class TouchControlShapeChanging extends TouchControl |
31 | 31 |
{ |
32 | 32 |
private static final float NOT_TOUCHED = 1000000.0f; |
33 |
private static final float[] mTmp = new float[4];
|
|
33 |
static final float[] mTmp = new float[4]; |
|
34 | 34 |
|
35 |
private static class FaceInfo
|
|
35 |
static class FaceInfo |
|
36 | 36 |
{ |
37 |
private final float[] vector; |
|
38 |
private final float distance; |
|
39 |
private final float[][] vertices; |
|
40 |
private final float[][] rotated; |
|
37 |
private final float[] normal; // vector normal to the surface of the face, pointing outside. |
|
38 |
private final float distance; // distance from (0,0,0) to the surface of the face |
|
39 |
private final float[][] vertices; // vertices of the face. Already rotated by the initQuat and |
|
40 |
// moved by 'position' (arithmetic average of all positions) |
|
41 |
private final float[][] rotated; // temp array to store vertices times rotation quaternion. |
|
42 |
|
|
43 |
////////////////////////////////////////////////////////// |
|
41 | 44 |
|
42 | 45 |
FaceInfo(float[][] verts, float size) |
43 | 46 |
{ |
... | ... | |
73 | 76 |
vy/=len; |
74 | 77 |
vz/=len; |
75 | 78 |
|
76 |
float dist = vx*vertices[0][0] + vy*vertices[0][1] + vz*vertices[0][2];
|
|
79 |
distance = vx*vertices[0][0] + vy*vertices[0][1] + vz*vertices[0][2];
|
|
77 | 80 |
|
78 |
if( dist<0 ) |
|
79 |
{ |
|
80 |
dist = -dist; |
|
81 |
vx = -vx; |
|
82 |
vy = -vy; |
|
83 |
vz = -vz; |
|
84 |
} |
|
81 |
normal = new float[4]; |
|
82 |
normal[0] = vx; |
|
83 |
normal[1] = vy; |
|
84 |
normal[2] = vz; |
|
85 |
normal[3] = 0.0f; |
|
86 |
} |
|
85 | 87 |
|
86 |
vector = new float[4]; |
|
87 |
vector[0] = vx; |
|
88 |
vector[1] = vy; |
|
89 |
vector[2] = vz; |
|
90 |
vector[3] = 0.0f; |
|
88 |
////////////////////////////////////////////////////////// |
|
91 | 89 |
|
92 |
distance = dist; |
|
90 |
public float[] getNormal() |
|
91 |
{ |
|
92 |
return normal; |
|
93 | 93 |
} |
94 | 94 |
} |
95 | 95 |
|
96 |
private final float[] mPoint, mCamera, mTouch; |
|
97 |
private final TwistyObject mObject; |
|
98 |
|
|
99 |
private float[][] mQuats; |
|
96 |
private final float[] mTouch; |
|
97 |
private final Static4D mTmpAxis; |
|
100 | 98 |
private int mNumCubits; |
101 | 99 |
private int[] mNumFaces; |
102 | 100 |
private boolean mPreparationDone; |
103 |
private FaceInfo[][] mInfos; |
|
104 |
private int mTouchedCubit; |
|
105 |
private int mTouchedFace; |
|
106 |
private final Static3D[] mRotAxis; |
|
107 |
private final int mNumAxis; |
|
108 |
private final Static4D mTmpAxis; |
|
101 |
|
|
102 |
final float[] mCamera, mPoint; |
|
103 |
final Static3D[] mRotAxis; |
|
104 |
final TwistyObject mObject; |
|
105 |
int mTouchedCubit, mTouchedFace, mNumAxis; |
|
106 |
FaceInfo[][] mInfos; |
|
107 |
float[][] mQuats; |
|
109 | 108 |
|
110 | 109 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
111 | 110 |
|
... | ... | |
120 | 119 |
mPreparationDone = false; |
121 | 120 |
mRotAxis = object.getRotationAxis(); |
122 | 121 |
mNumAxis = mRotAxis.length; |
123 |
|
|
124 | 122 |
mTmpAxis = new Static4D(0,0,0,0); |
125 | 123 |
} |
126 | 124 |
|
... | ... | |
381 | 379 |
// |
382 | 380 |
// output = camera + alpha*(point-camera), where alpha = [dist-normalVec*camera] / [normalVec*(point-camera)] |
383 | 381 |
|
384 |
private void castTouchPointOntoFace(float nx, float ny, float nz, float distance, float[] output)
|
|
382 |
void castTouchPointOntoFace(float nx, float ny, float nz, float distance, float[] output) |
|
385 | 383 |
{ |
386 | 384 |
float d0 = mPoint[0]-mCamera[0]; |
387 | 385 |
float d1 = mPoint[1]-mCamera[1]; |
... | ... | |
402 | 400 |
|
403 | 401 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
404 | 402 |
|
405 |
private boolean faceIsVisible(float nx, float ny, float nz, float distance)
|
|
403 |
private boolean cubitFaceIsVisible(float nx, float ny, float nz, float distance)
|
|
406 | 404 |
{ |
407 | 405 |
return mCamera[0]*nx + mCamera[1]*ny + mCamera[2]*nz > distance; |
408 | 406 |
} |
... | ... | |
416 | 414 |
// 2) else, cast the line passing through mPoint and mCamera onto this plane |
417 | 415 |
// 3) if Z of this point is further from us than the already computed closestSoFar, return NOT_TOUCHED |
418 | 416 |
// 4) else, rotate 'vertices' by quat and see if the casted point lies inside the polygon defined by them |
419 |
// 5) if yes, return its Z; otherwise, return NOT_TOUCHED
|
|
417 |
// 5) if yes, return the distance form this point to the camera; otherwise, return NOT_TOUCHED
|
|
420 | 418 |
|
421 | 419 |
private float cubitFaceTouched(FaceInfo info, float[] quat, float closestSoFar) |
422 | 420 |
{ |
423 |
QuatHelper.rotateVectorByQuat(mTmp,info.vector,quat);
|
|
421 |
QuatHelper.rotateVectorByQuat(mTmp,info.normal,quat);
|
|
424 | 422 |
float nx = mTmp[0]; |
425 | 423 |
float ny = mTmp[1]; |
426 | 424 |
float nz = mTmp[2]; |
427 | 425 |
|
428 |
if( faceIsVisible(nx,ny,nz,info.distance) )
|
|
426 |
if( cubitFaceIsVisible(nx,ny,nz,info.distance) )
|
|
429 | 427 |
{ |
430 | 428 |
castTouchPointOntoFace(nx,ny,nz,info.distance,mTouch); |
431 | 429 |
|
... | ... | |
446 | 444 |
|
447 | 445 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
448 | 446 |
|
449 |
private int computeDisabledAxis() |
|
450 |
{ |
|
451 |
float cx = mCamera[0]; |
|
452 |
float cy = mCamera[1]; |
|
453 |
float cz = mCamera[2]; |
|
454 |
|
|
455 |
float len = (float)Math.sqrt(cx*cx+cy*cy+cz*cz); |
|
456 |
|
|
457 |
cx /= len; |
|
458 |
cy /= len; |
|
459 |
cz /= len; |
|
460 |
|
|
461 |
float max = -1.0f; |
|
462 |
int maxAxis = -1; |
|
463 |
|
|
464 |
for(int axis=0; axis<mNumAxis; axis++) |
|
465 |
{ |
|
466 |
float ax = mRotAxis[axis].get0(); |
|
467 |
float ay = mRotAxis[axis].get1(); |
|
468 |
float az = mRotAxis[axis].get2(); |
|
469 |
|
|
470 |
float angle = ax*cx + ay*cy + az*cz; |
|
471 |
if( angle<0 ) angle = -angle; |
|
472 |
|
|
473 |
if( angle>max ) |
|
474 |
{ |
|
475 |
max=angle; |
|
476 |
maxAxis = axis; |
|
477 |
} |
|
478 |
} |
|
479 |
|
|
480 |
return maxAxis; |
|
481 |
} |
|
482 |
|
|
483 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
484 |
|
|
485 |
private int computeRotationIndex(int disabled, float dx, float dy, float dz) |
|
486 |
{ |
|
487 |
float min = Float.MAX_VALUE; |
|
488 |
int minAxis = -1; |
|
489 |
|
|
490 |
for(int axis=0; axis<mNumAxis; axis++) |
|
491 |
if( axis!=disabled ) |
|
492 |
{ |
|
493 |
float ax = mRotAxis[axis].get0(); |
|
494 |
float ay = mRotAxis[axis].get1(); |
|
495 |
float az = mRotAxis[axis].get2(); |
|
496 |
|
|
497 |
float angle = dx*ax + dy*ay + dz*az; |
|
498 |
if( angle<0 ) angle=-angle; |
|
499 |
|
|
500 |
if( angle<min ) |
|
501 |
{ |
|
502 |
min=angle; |
|
503 |
minAxis = axis; |
|
504 |
} |
|
505 |
} |
|
506 |
|
|
507 |
return minAxis; |
|
508 |
} |
|
509 |
|
|
510 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
511 |
|
|
512 |
private int computeRow(int cubit, int rotIndex) |
|
447 |
int computeRow(int cubit, int rotIndex) |
|
513 | 448 |
{ |
514 | 449 |
int row = mObject.getCubitRotRow(cubit,rotIndex); |
515 | 450 |
|
... | ... | |
569 | 504 |
} |
570 | 505 |
|
571 | 506 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
507 |
// really implemented in derived classes; here present only because we need to be able to |
|
508 |
// instantiate an object of this class for MODE_REPLACE. |
|
572 | 509 |
|
573 | 510 |
public void newRotation(int[] output, Static4D rotatedTouchPoint) |
574 | 511 |
{ |
575 |
if( !mPreparationDone ) prepare(); |
|
576 |
|
|
577 |
float dx = mPoint[0] - rotatedTouchPoint.get0()/mObjectRatio; |
|
578 |
float dy = mPoint[1] - rotatedTouchPoint.get1()/mObjectRatio; |
|
579 |
float dz = mPoint[2] - rotatedTouchPoint.get2()/mObjectRatio; |
|
580 |
|
|
581 |
int disabledAxis = computeDisabledAxis(); |
|
582 |
int rotIndex = computeRotationIndex(disabledAxis,dx,dy,dz); |
|
583 |
int row = computeRow(mTouchedCubit,rotIndex); |
|
584 | 512 |
|
585 |
output[0] = rotIndex; |
|
586 |
output[1] = row; |
|
587 | 513 |
} |
588 | 514 |
|
589 | 515 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
Also available in: Unified diff
FIx some issues with ShapeChanging; implement per-object TouchControlSquare and TouchControlMirror.