Revision ef56782c
Added by Leszek Koltunski 9 months ago
src/main/java/org/distorted/objectlib/main/TwistyObjectControllable.java | ||
---|---|---|
18 | 18 |
import org.distorted.library.type.Static1D; |
19 | 19 |
import org.distorted.library.type.Static3D; |
20 | 20 |
import org.distorted.library.type.Static4D; |
21 |
import org.distorted.objectlib.helpers.OperatingSystemInterface; |
|
21 | 22 |
import org.distorted.objectlib.touchcontrol.*; |
22 | 23 |
|
23 | 24 |
import java.util.Random; |
... | ... | |
54 | 55 |
private Static1D mGhostStatic; |
55 | 56 |
private Static3D mGhostEffectAxis; |
56 | 57 |
private int[][][] mGhostAxisJumpedTo; |
57 |
private boolean[] mGhostCubitRotated; |
|
58 |
private boolean[] mGhostCubitRotated, mGhostOrigRotated;
|
|
58 | 59 |
private Static4D mGhostQuat; |
59 | 60 |
|
61 |
private int mGhostAxis; // the index of the axis of rotations along which the ghost |
|
62 |
// can always move. |
|
63 |
private int mGhostAngle; // in degrees! |
|
64 |
private int mGhostFirstRow; // Every ghost has two kinds of rows along its mGhostAxis: |
|
65 |
// 'left' ones (normal) and 'right' ones (blocking). FirstRow is |
|
66 |
// the number of the first right row. |
|
67 |
private boolean mGhostBlocked; // if true, all rotations along axis different than mGhostAxis |
|
68 |
// are blocked. |
|
69 |
private int mGhostRowBitmap; // a bitmap; if bit[N] is 1, this means that layer N along the |
|
70 |
// mGhostAxis is ghostRotated (initially all layers left of |
|
71 |
// mGhostFirstRow are not and every ones right and including |
|
72 |
// mGhostFirstRow are) |
|
73 |
private boolean mGhostAxisInverted; // we also care about the direction of the ghostAxis. It can |
|
74 |
// change, for example a 2x2x2 has 3 rotAxes, but its ghostAxis |
|
75 |
// can point in 6 directions (3 axes, each inverted or not) |
|
76 |
|
|
60 | 77 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
61 | 78 |
|
62 | 79 |
public abstract int getTouchControlType(); |
... | ... | |
76 | 93 |
|
77 | 94 |
mQuat = quat; |
78 | 95 |
mRotationState = STATE_NOTHING; |
96 |
mGhostAngle = getGhostAngle(); |
|
79 | 97 |
|
80 | 98 |
if( mGhostAngle!=0 ) |
81 | 99 |
{ |
82 |
mGhostBasicDeg = 360/mBasicAngles[mGhostAxis][0]; |
|
100 |
mGhostAxis = getGhostAxis(); |
|
101 |
mGhostFirstRow= getGhostFirstRow(); |
|
102 |
mGhostBlocked = true; |
|
103 |
mGhostBasicDeg= 360/mBasicAngles[mGhostAxis][0]; |
|
83 | 104 |
mGhostNumRows = mNumLayers[mGhostAxis]; |
84 |
mGhostStatic = new Static1D(mGhostAngle); |
|
105 |
mGhostStatic = new Static1D(mGhostAngle);
|
|
85 | 106 |
|
86 | 107 |
Static3D currGhostAxis = mAxis[mGhostAxis]; |
87 | 108 |
float x = currGhostAxis.get0(); |
... | ... | |
93 | 114 |
mEffects.apply(mGhostEffect); |
94 | 115 |
|
95 | 116 |
mGhostCubitRotated = new boolean[mNumCubits]; |
117 |
mGhostOrigRotated = new boolean[mNumCubits]; |
|
118 |
|
|
96 | 119 |
mGhostQuat = new Static4D(0,0,0,1); |
97 | 120 |
computeGhostAxisJumps(); |
98 | 121 |
|
... | ... | |
102 | 125 |
mGhostRowBitmap = (tmp-1)<<mGhostFirstRow; |
103 | 126 |
|
104 | 127 |
reinitializeGhostStuff(); |
128 |
for(int c=0; c<mNumCubits; c++) mGhostOrigRotated[c] = mGhostCubitRotated[c]; |
|
105 | 129 |
} |
106 | 130 |
|
107 | 131 |
mRotationAngleStatic = new Static1D(0); |
... | ... | |
139 | 163 |
} |
140 | 164 |
} |
141 | 165 |
|
166 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
167 |
|
|
168 |
public int getGhostAxis() { return 0; } |
|
169 |
public int getGhostAngle() { return 0; } |
|
170 |
public int getGhostFirstRow() { return 0; } |
|
171 |
|
|
172 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
173 |
|
|
174 |
void restoreGhostStuff(String key, OperatingSystemInterface os) |
|
175 |
{ |
|
176 |
if( mGhostAngle!=0 ) |
|
177 |
{ |
|
178 |
int defAxis=getGhostAxis(); |
|
179 |
int defNumRows=mBasicAngles[defAxis].length; |
|
180 |
int tmp=1<<(defNumRows - mGhostFirstRow); |
|
181 |
int defBitmap=(tmp - 1)<<mGhostFirstRow; |
|
182 |
|
|
183 |
mGhostAxis=os.getInt(key + "_ghostAxis", defAxis); |
|
184 |
mGhostRowBitmap=os.getInt(key + "_ghostBitmap", defBitmap); |
|
185 |
int inverted=os.getInt(key + "_ghostAxisInverted", 0); |
|
186 |
|
|
187 |
mGhostAxisInverted=(inverted == 1); |
|
188 |
|
|
189 |
reinitializeGhostStuff(); |
|
190 |
} |
|
191 |
} |
|
192 |
|
|
193 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
194 |
|
|
195 |
void saveGhostStuff(String key, OperatingSystemInterface os) |
|
196 |
{ |
|
197 |
if( mGhostAngle!=0 ) |
|
198 |
{ |
|
199 |
os.putInt(key + "_ghostAxis", mGhostAxis); |
|
200 |
os.putInt(key + "_ghostBitmap", mGhostRowBitmap); |
|
201 |
os.putInt(key + "_ghostAxisInverted", mGhostAxisInverted ? 1 : 0); |
|
202 |
} |
|
203 |
} |
|
204 |
|
|
205 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
206 |
|
|
207 |
void removeGhostStuff(String key, OperatingSystemInterface os) |
|
208 |
{ |
|
209 |
if( mGhostAngle!=0 ) |
|
210 |
{ |
|
211 |
os.remove(key + "_ghostAxis"); |
|
212 |
os.remove(key + "_ghostBitmap"); |
|
213 |
os.remove(key + "_ghostAxisInverted"); |
|
214 |
} |
|
215 |
} |
|
216 |
|
|
217 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
218 |
|
|
219 |
boolean ghostBlocked(int axis) { return mGhostBlocked && axis!=mGhostAxis; } |
|
220 |
|
|
221 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
222 |
// all pairs have to be the same or all pairs have to be different |
|
223 |
|
|
224 |
boolean ghostNotSolved() |
|
225 |
{ |
|
226 |
boolean first = mGhostOrigRotated[0]^mGhostCubitRotated[0]; |
|
227 |
|
|
228 |
for(int c=1; c<mNumCubits; c++) |
|
229 |
if( mGhostCubitRotated[c]^mGhostOrigRotated[c] != first ) return true; |
|
230 |
|
|
231 |
return false; |
|
232 |
} |
|
233 |
|
|
142 | 234 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
143 | 235 |
// needed for TouchControl |
144 | 236 |
|
... | ... | |
157 | 249 |
mGhostEffect.setMeshAssociation(mGhostRowBitmap<<(mGhostAxis*mMaxNumLayers),-1); |
158 | 250 |
|
159 | 251 |
int fullOnes = (1<<(mGhostNumRows))-1; |
160 |
int leftOnes = (1<<(mGhostNumRows-mGhostFirstRow))-1; |
|
161 |
int rightOnes = ((1<<mGhostFirstRow)-1)<<(mGhostNumRows-mGhostFirstRow); |
|
162 |
|
|
163 |
mGhostBlocked = ( mGhostRowBitmap!=0 && mGhostRowBitmap!=fullOnes ); |
|
164 |
mGhostOuterShapeOk= ( (mGhostRowBitmap==rightOnes && !mGhostAxisInverted) || (mGhostRowBitmap==leftOnes && mGhostAxisInverted) ); |
|
252 |
mGhostBlocked = ( mGhostRowBitmap!=0 && mGhostRowBitmap!=fullOnes ); |
|
165 | 253 |
|
166 | 254 |
mGhostStatic.set0(mGhostAxisInverted ? -mGhostAngle : mGhostAngle); |
167 | 255 |
|
... | ... | |
527 | 615 |
} |
528 | 616 |
|
529 | 617 |
int fullOnes = (1<<(mGhostNumRows))-1; |
530 |
int leftOnes = (1<<(mGhostNumRows-mGhostFirstRow))-1; |
|
531 |
int rightOnes = ((1<<mGhostFirstRow)-1)<<(mGhostNumRows-mGhostFirstRow); |
|
532 |
|
|
533 |
mGhostBlocked = ( mGhostRowBitmap!=0 && mGhostRowBitmap!=fullOnes ); |
|
534 |
mGhostOuterShapeOk= ( (mGhostRowBitmap==rightOnes && !mGhostAxisInverted) || (mGhostRowBitmap==leftOnes && mGhostAxisInverted) ); |
|
618 |
mGhostBlocked = ( mGhostRowBitmap!=0 && mGhostRowBitmap!=fullOnes ); |
|
535 | 619 |
|
536 | 620 |
if( mGhostRowBitmap==fullOnes ) |
537 | 621 |
{ |
src/main/java/org/distorted/objectlib/main/TwistyObjectSolved.java | ||
---|---|---|
44 | 44 |
|
45 | 45 |
public abstract int[] getColorTable(); |
46 | 46 |
public abstract int getNumPuzzleFaces(); |
47 |
abstract boolean ghostNotSolved(); |
|
47 | 48 |
|
48 | 49 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
49 | 50 |
|
... | ... | |
147 | 148 |
|
148 | 149 |
boolean isSolved() |
149 | 150 |
{ |
150 |
if( mGhostAngle!=0 && !mGhostOuterShapeOk ) return false;
|
|
151 |
if( ghostNotSolved() ) return false;
|
|
151 | 152 |
|
152 | 153 |
for(int c=0; c<mNumCubits; c++) mCubitQuats[c] = getCubitQuatIndex(c); |
153 | 154 |
|
src/main/java/org/distorted/objectlib/main/TwistyObjectTheoretical.java | ||
---|---|---|
43 | 43 |
private int[] mCubitType; |
44 | 44 |
private float[][] mCubitOffset; |
45 | 45 |
|
46 |
// only for Ghosts |
|
47 |
protected int mGhostAxis; // the index of the axis of rotations along which the ghost |
|
48 |
// can always move. |
|
49 |
protected int mGhostAngle; // in degrees! |
|
50 |
protected int mGhostFirstRow; // Every ghost has two kinds of rows along its mGhostAxis: |
|
51 |
// 'left' ones (normal) and 'right' ones (blocking). FirstRow is |
|
52 |
// the number of the first right row. |
|
53 |
protected boolean mGhostBlocked; // if true, all rotations along axis different than mGhostAxis |
|
54 |
// are blocked. |
|
55 |
protected boolean mGhostOuterShapeOk; // is the outer shape of the ghost puzzle currently 'ok' i.e. |
|
56 |
// the same like in the beginning? then we are solved! |
|
57 |
protected int mGhostRowBitmap; // a bitmap; if bit[N] is 1, this means that layer N along the |
|
58 |
// mGhostAxis is ghostRotated (initially all layers left of |
|
59 |
// mGhostFirstRow are not and every ones right and including |
|
60 |
// mGhostFirstRow are) |
|
61 |
protected boolean mGhostAxisInverted; // we also care about the direction of the ghostAxis. It can |
|
62 |
// change, for example a 2x2x2 has 3 rotAxes, but its ghostAxis |
|
63 |
// can point in 6 directions (3 axes, each inverted or not) |
|
64 |
|
|
65 | 46 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
66 | 47 |
|
67 | 48 |
public abstract Static3D[] getFaceAxis(); |
... | ... | |
70 | 51 |
public abstract Static4D getCubitOrigQuat(int cubit); |
71 | 52 |
public abstract Static3D[] getRotationAxis(); |
72 | 53 |
public abstract int[][] getBasicAngles(); |
73 |
abstract void reinitializeGhostStuff(); |
|
74 | 54 |
|
75 | 55 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
76 | 56 |
|
... | ... | |
92 | 72 |
mCubitOffset = new float[mNumCubits][]; |
93 | 73 |
mCubitType = new int[mNumCubits]; |
94 | 74 |
|
95 |
mGhostAxis = getGhostAxis(); |
|
96 |
mGhostAngle = getGhostAngle(); |
|
97 |
mGhostFirstRow= getGhostFirstRow(); |
|
98 |
mGhostBlocked = mGhostAngle!=0; |
|
99 |
|
|
100 | 75 |
for(int c=0; c<mNumCubits; c++) |
101 | 76 |
{ |
102 | 77 |
mCubitOffset[c] = getCubitRowOffset(c); |
... | ... | |
127 | 102 |
public int getCubitQuatIndex(int cubit) { return (cubit>=0 && cubit<mNumCubits) ? mCubits[cubit].mQuatIndex : 0; } |
128 | 103 |
public int getCubitRotRow(int cubit, int axis) { return mCubits[cubit].getRotRow(axis); } |
129 | 104 |
public int getNumCubits() { return mNumCubits; } |
130 |
public int getGhostAngle() { return 0; } |
|
131 |
public int getGhostFirstRow() { return 0; } |
|
132 |
public int getGhostAxis() { return 0; } |
|
133 | 105 |
|
134 | 106 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
135 | 107 |
|
... | ... | |
338 | 310 |
|
339 | 311 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
340 | 312 |
|
341 |
int computeBandagedBitmap(int rowBitmap, int axisIndex) |
|
313 |
boolean ghostBlocked(int axis) { return false; } |
|
314 |
|
|
315 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
316 |
|
|
317 |
int computeBandagedBitmap(int rowBitmap, int axis) |
|
342 | 318 |
{ |
343 |
if( mGhostBlocked && axisIndex!=mGhostAxis ) |
|
344 |
{ |
|
345 |
return 0xffffffff; // all rows blocked! |
|
346 |
} |
|
319 |
if( ghostBlocked(axis) ) return 0xffffffff; |
|
347 | 320 |
|
348 | 321 |
if( mIsBandaged ) |
349 | 322 |
{ |
... | ... | |
355 | 328 |
|
356 | 329 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
357 | 330 |
{ |
358 |
bitmap = mCubits[cubit].getRotRow(axisIndex);
|
|
331 |
bitmap = mCubits[cubit].getRotRow(axis); |
|
359 | 332 |
if( (rowBitmap & bitmap) != 0 ) rowBitmap |= bitmap; |
360 | 333 |
} |
361 | 334 |
} |
... | ... | |
363 | 336 |
|
364 | 337 |
if( mMinimalCubiesInRow!=null ) |
365 | 338 |
{ |
366 |
int[] minC = mMinimalCubiesInRow[axisIndex];
|
|
339 |
int[] minC = mMinimalCubiesInRow[axis]; |
|
367 | 340 |
int numL = minC.length; |
368 | 341 |
int[] numC = new int[numL]; |
369 | 342 |
|
370 | 343 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
371 | 344 |
{ |
372 |
int bitmap = mCubits[cubit].getRotRow(axisIndex);
|
|
345 |
int bitmap = mCubits[cubit].getRotRow(axis); |
|
373 | 346 |
|
374 | 347 |
for(int i=0; i<numL; i++) |
375 | 348 |
{ |
... | ... | |
554 | 527 |
else { error = true; break; } |
555 | 528 |
} |
556 | 529 |
|
557 |
if( mGhostAngle!=0 ) restoreGhostStuff(key,os);
|
|
530 |
restoreGhostStuff(key,os); |
|
558 | 531 |
} |
559 | 532 |
|
560 | 533 |
if( error ) |
... | ... | |
570 | 543 |
void savePreferences(String key, OperatingSystemInterface os) |
571 | 544 |
{ |
572 | 545 |
for(int i=0; i<mNumCubits; i++) mCubits[i].savePreferences(key,os); |
573 |
if( mGhostAngle!=0 ) saveGhostStuff(key,os);
|
|
546 |
saveGhostStuff(key,os); |
|
574 | 547 |
} |
575 | 548 |
|
576 | 549 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
578 | 551 |
void removePreferences(String key, OperatingSystemInterface os) |
579 | 552 |
{ |
580 | 553 |
for(int i=0; i<mNumCubits; i++) mCubits[i].removePreferences(key,os); |
581 |
if( mGhostAngle!=0 ) removeGhostStuff(key,os); |
|
582 |
} |
|
583 |
|
|
584 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
585 |
|
|
586 |
private void restoreGhostStuff(String key, OperatingSystemInterface os) |
|
587 |
{ |
|
588 |
int defAxis = getGhostAxis(); |
|
589 |
int defNumRows = mBasicAngles[defAxis].length; |
|
590 |
int tmp = 1<<(defNumRows-mGhostFirstRow); |
|
591 |
int defBitmap = (tmp-1)<<mGhostFirstRow; |
|
592 |
|
|
593 |
mGhostAxis = os.getInt(key+"_ghostAxis" , defAxis ); |
|
594 |
mGhostRowBitmap = os.getInt(key+"_ghostBitmap" , defBitmap); |
|
595 |
int inverted = os.getInt(key+"_ghostAxisInverted", 0 ); |
|
596 |
|
|
597 |
mGhostAxisInverted = (inverted==1); |
|
598 |
|
|
599 |
reinitializeGhostStuff(); |
|
554 |
removeGhostStuff(key,os); |
|
600 | 555 |
} |
601 | 556 |
|
602 | 557 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
603 | 558 |
|
604 |
private void saveGhostStuff(String key, OperatingSystemInterface os) |
|
605 |
{ |
|
606 |
os.putInt(key+"_ghostAxis" , mGhostAxis ); |
|
607 |
os.putInt(key+"_ghostBitmap" , mGhostRowBitmap ); |
|
608 |
os.putInt(key+"_ghostAxisInverted", mGhostAxisInverted ? 1:0 ); |
|
609 |
} |
|
610 |
|
|
611 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
612 |
|
|
613 |
private void removeGhostStuff(String key, OperatingSystemInterface os) |
|
614 |
{ |
|
615 |
os.remove(key+"_ghostAxis" ); |
|
616 |
os.remove(key+"_ghostBitmap" ); |
|
617 |
os.remove(key+"_ghostAxisInverted"); |
|
618 |
} |
|
559 |
void restoreGhostStuff(String key, OperatingSystemInterface os) {} |
|
560 |
void saveGhostStuff(String key, OperatingSystemInterface os) {} |
|
561 |
void removeGhostStuff(String key, OperatingSystemInterface os) {} |
|
619 | 562 |
|
620 | 563 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
621 | 564 |
// Because of quatMultiplication, errors can accumulate - so to avoid this, we |
src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java | ||
---|---|---|
586 | 586 |
private float cubitFaceTouched(FaceInfo info, float[] quat, float closestSoFar) |
587 | 587 |
{ |
588 | 588 |
QuatHelper.rotateVectorByQuat(mTmp,info.normal,quat); |
589 |
|
|
590 | 589 |
float nx = mTmp[0]; |
591 | 590 |
float ny = mTmp[1]; |
592 | 591 |
float nz = mTmp[2]; |
Also available in: Unified diff
move alll ghostStuff to TwistyObjectControllable