Revision 63bfcdd1
Added by Leszek Koltunski over 1 year ago
src/main/java/org/distorted/objectlib/json/JsonReader.java | ||
---|---|---|
88 | 88 |
private float[][] mCubitRowOffset; |
89 | 89 |
private ObjectStickerOverride[] mStickerOverrides; |
90 | 90 |
private float mPillowCoeff; |
91 |
private int[][] mMinimalCubitsInRow; |
|
91 | 92 |
|
92 | 93 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
93 | 94 |
|
... | ... | |
547 | 548 |
for(int j=0; j<numRota; j++) mRotationFactor[i][j] = 1.0f; |
548 | 549 |
} |
549 | 550 |
|
551 |
JSONArray jsonMinimal = jsonAx.optJSONArray("minimal"); |
|
552 |
|
|
553 |
if( jsonMinimal!=null ) |
|
554 |
{ |
|
555 |
if( mMinimalCubitsInRow==null ) mMinimalCubitsInRow = new int[numAxis][]; |
|
556 |
int numMinimal = jsonMinimal.length(); |
|
557 |
mMinimalCubitsInRow[i] = new int[numMinimal]; |
|
558 |
for(int j=0; j<numMinimal; j++) mMinimalCubitsInRow[i][j] = jsonMinimal.getInt(j); |
|
559 |
} |
|
560 |
|
|
550 | 561 |
mNumLayers[i] = numRota; |
551 | 562 |
} |
552 | 563 |
} |
... | ... | |
946 | 957 |
} |
947 | 958 |
} |
948 | 959 |
|
960 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
961 |
|
|
962 |
public int[][] getMinimalCubiesInRow() |
|
963 |
{ |
|
964 |
return mMinimalCubitsInRow; |
|
965 |
} |
|
966 |
|
|
949 | 967 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
950 | 968 |
|
951 | 969 |
public int getScrambleType() |
src/main/java/org/distorted/objectlib/json/JsonWriter.java | ||
---|---|---|
34 | 34 |
|
35 | 35 |
public class JsonWriter |
36 | 36 |
{ |
37 |
public static final int VERSION_OBJECT_APP = 13;
|
|
37 |
public static final int VERSION_OBJECT_APP = 14;
|
|
38 | 38 |
public static final int VERSION_EXTRAS_APP = 1; |
39 | 39 |
|
40 | 40 |
private static JsonWriter mThis; |
... | ... | |
479 | 479 |
float[][] cuts = object.getCuts(numLayers); |
480 | 480 |
boolean[][] rotatable = object.getLayerRotatable(numLayers); |
481 | 481 |
float[][] rotFactor = object.returnRotationFactor(); |
482 |
int[][] minimalCubits = object.getMinimalCubiesInRow(); |
|
482 | 483 |
|
483 | 484 |
for( int i=0; i<numAxis; i++ ) |
484 | 485 |
{ |
... | ... | |
502 | 503 |
for(float rotf : rotFactor[i]) factorArray.put(rotf); |
503 | 504 |
axObject.put("factor", factorArray ); |
504 | 505 |
|
506 |
if( minimalCubits!=null ) |
|
507 |
{ |
|
508 |
JSONArray minimalArray = new JSONArray(); |
|
509 |
for(int min : minimalCubits[i]) minimalArray.put(min); |
|
510 |
axObject.put("minimal", minimalArray ); |
|
511 |
} |
|
512 |
|
|
505 | 513 |
axis.put(axObject); |
506 | 514 |
} |
507 | 515 |
|
src/main/java/org/distorted/objectlib/main/ObjectControl.java | ||
---|---|---|
668 | 668 |
mPreRender.getObject().setObjectRatioNow(scale,mScalingSize ); |
669 | 669 |
} |
670 | 670 |
|
671 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
672 |
|
|
673 |
public void multQuatNow(Static4D quat) |
|
674 |
{ |
|
675 |
Static4D q = QuatHelper.quatMultiply(mQuat,quat); |
|
676 |
mQuat.set(q); |
|
677 |
} |
|
678 |
|
|
679 | 671 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
680 | 672 |
|
681 | 673 |
public void setQuat() |
src/main/java/org/distorted/objectlib/main/ObjectPreRender.java | ||
---|---|---|
484 | 484 |
mScale = scale; |
485 | 485 |
} |
486 | 486 |
|
487 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
488 |
|
|
489 |
void ghostAngleCompensation(Static4D quat) |
|
490 |
{ |
|
491 |
mController.multQuatNow(quat); |
|
492 |
} |
|
493 |
|
|
494 | 487 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
495 | 488 |
// INTERNAL API |
496 | 489 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
src/main/java/org/distorted/objectlib/main/TwistyLayerRotations.java | ||
---|---|---|
15 | 15 |
import org.distorted.library.type.Dynamic1D; |
16 | 16 |
import org.distorted.library.type.Static1D; |
17 | 17 |
import org.distorted.library.type.Static3D; |
18 |
import org.distorted.library.type.Static4D; |
|
19 | 18 |
|
20 | 19 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
21 | 20 |
|
... | ... | |
42 | 41 |
private final int mGhostAngle; |
43 | 42 |
private final Static3D[] mAxis; |
44 | 43 |
private final int[] mNumLayers; |
45 |
|
|
44 |
private int mSolvedBitmap; |
|
46 | 45 |
private int mGhostEffectBitmap; |
47 | 46 |
private VertexEffectRotate mGhostEffect1; |
48 |
private int mRotCompensation, mAccumulatedCompensation; |
|
49 | 47 |
private boolean mCanGhost; |
50 | 48 |
private Static3D mEffectAx; |
51 | 49 |
private int mAxNum; |
50 |
private int mGhostRot; |
|
52 | 51 |
|
53 | 52 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
54 | 53 |
|
... | ... | |
80 | 79 |
int nL = mNumLayers[mAxNum]; |
81 | 80 |
mEffectAx = mAxis[mAxNum]; |
82 | 81 |
int numRightRows = nL - nL/2; |
83 |
mGhostEffectBitmap = ((1<<numRightRows)-1)<<(nL/2); |
|
82 |
mSolvedBitmap = ((1<<numRightRows)-1)<<(nL/2); |
|
83 |
mGhostEffectBitmap = mSolvedBitmap; |
|
84 | 84 |
mParent.enableGhostAxis(mAxNum,false); |
85 | 85 |
Static1D ghostAngle1= new Static1D(mGhostAngle); |
86 | 86 |
mGhostEffect1 = new VertexEffectRotate(ghostAngle1, mEffectAx, CENTER); |
... | ... | |
95 | 95 |
|
96 | 96 |
private int computeGhostAngle(int row, int basicAngle, float angle, float speed) |
97 | 97 |
{ |
98 |
int a = (int)((2*(angle<0 ? -angle : angle) - mGhostAngle)*basicAngle/360) + 1; |
|
98 |
boolean ghosted = rowIsGhosted(row); |
|
99 |
int basic = 360/basicAngle; |
|
100 |
int nearest = computeNearest( ghosted ? basic-mGhostAngle : mGhostAngle, basic, angle ); |
|
101 |
if( (nearest%basic)!=0 ) |
|
102 |
{ |
|
103 |
changeRow(row); |
|
104 |
mGhostRot = (ghosted ? 1:-1)*mGhostAngle; |
|
105 |
} |
|
99 | 106 |
|
100 |
android.util.Log.e("D","angle="+angle+" a="+a+" ghost: "+((a%2)==1) );
|
|
107 |
int ret= computeNoGhostAngle(basicAngle,angle,speed);
|
|
101 | 108 |
|
102 |
return computeNoGhostAngle(basicAngle,angle,speed); |
|
109 |
android.util.Log.e("D", "computeGhostAngle: "+ret+" ghostRot="+mGhostRot+" angle>0: "+(angle>0)+" ghosted="+ghosted); |
|
110 |
|
|
111 |
return ret; |
|
103 | 112 |
} |
104 | 113 |
|
105 | 114 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
111 | 120 |
|
112 | 121 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
113 | 122 |
|
114 |
private void changeCompensationAngle(int diff)
|
|
123 |
private int computeNearest(int ghostAngle, int basicAngle, float angle)
|
|
115 | 124 |
{ |
116 |
mAccumulatedCompensation = diff; |
|
125 |
float A = (2*angle-ghostAngle)/basicAngle; |
|
126 |
int k = A>=0 ? (int)A : (int)A-1; |
|
127 |
return (k%2)==0 ? (k/2)*basicAngle+ghostAngle : ((k+1)/2)*basicAngle; |
|
117 | 128 |
} |
118 | 129 |
|
119 | 130 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
120 | 131 |
|
121 | 132 |
private void changeRow(int row) |
122 | 133 |
{ |
123 |
if( mGhostEffectBitmap==0 ) mParent.enableGhostAxis(mAxNum,false); |
|
134 |
android.util.Log.e("D", "changing row "+row); |
|
135 |
int nL = mNumLayers[mAxNum]; |
|
136 |
if( mGhostEffectBitmap==0 || mGhostEffectBitmap==((1<<nL)-1) ) mParent.enableGhostAxis(mAxNum,false); |
|
124 | 137 |
mGhostEffectBitmap ^= (1<<row); |
125 |
if( mGhostEffectBitmap==0 ) mParent.enableGhostAxis(mAxNum,true); |
|
126 |
|
|
138 |
if( mGhostEffectBitmap==0 || mGhostEffectBitmap==((1<<nL)-1) ) mParent.enableGhostAxis(mAxNum,true); |
|
127 | 139 |
mGhostEffect1.setMeshAssociation( mGhostEffectBitmap, -1); |
128 | 140 |
} |
129 | 141 |
|
... | ... | |
144 | 156 |
|
145 | 157 |
private int computeNearestAngle(int axisIndex, int row, int basicAngle, float angle, float speed) |
146 | 158 |
{ |
147 |
if( mGhostAngle==0 || axisIndex!=0 || !mCanGhost )
|
|
159 |
if( mGhostAngle==0 || axisIndex!=0 /*|| !mCanGhost*/ )
|
|
148 | 160 |
{ |
149 | 161 |
return computeNoGhostAngle(basicAngle,angle,speed); |
150 | 162 |
} |
... | ... | |
184 | 196 |
|
185 | 197 |
long finishRotation(ObjectPreRender pre, int axisIndex, int row, int basicAngle, float finishAngle, float avgSpeed) |
186 | 198 |
{ |
187 |
mRotCompensation = 0; |
|
188 |
mAccumulatedCompensation = 0; |
|
189 |
|
|
199 |
mGhostRot = 0; |
|
190 | 200 |
int nearestAngleInDegrees = computeNearestAngle(axisIndex,row,basicAngle,finishAngle,avgSpeed); |
191 | 201 |
|
192 | 202 |
mRotationState = STATE_FINISH; |
193 |
float angle = getAngle() + mRotCompensation; // ghosts: we 'hide' the GhostAngle inside the |
|
194 |
// mGhostEffect1; here we must compensate. |
|
203 |
float angle = getAngle() + mGhostRot; |
|
195 | 204 |
mRotationAngleStatic.set0(angle); |
196 | 205 |
mRotationAngleFinal.set0(nearestAngleInDegrees); |
197 | 206 |
mRotationAngleMiddle.set0( nearestAngleInDegrees + (nearestAngleInDegrees-angle)*0.2f ); |
... | ... | |
203 | 212 |
mRotationAngle.add(mRotationAngleFinal); |
204 | 213 |
mRotateEffect.notifyWhenFinished(pre); |
205 | 214 |
|
206 |
if( mAccumulatedCompensation!=0 ) |
|
207 |
{ |
|
208 |
float half = (float)((Math.PI*mAccumulatedCompensation*mGhostAngle)/360); |
|
209 |
float cos = (float)(Math.cos(half)); |
|
210 |
float sin = (float)(Math.sin(half)); |
|
211 |
Static3D ax = mAxis[0]; |
|
212 |
float x = ax.get0(); |
|
213 |
float y = ax.get1(); |
|
214 |
float z = ax.get2(); |
|
215 |
Static4D quat = new Static4D(x*sin,y*sin,z*sin,cos); |
|
216 |
pre.ghostAngleCompensation(quat); |
|
217 |
} |
|
218 |
|
|
219 | 215 |
return mRotateEffect.getID(); |
220 | 216 |
} |
221 | 217 |
|
... | ... | |
230 | 226 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
231 | 227 |
// this is 'programmatic' rotation - i.e. for example the one induced by the 'backMove' button. |
232 | 228 |
|
233 |
synchronized long addRotation(EffectListener listener, Static3D axis, int axisIndex, int rowBitmap, int angle, long durationMillis )
|
|
229 |
synchronized long addRotation(EffectListener listener, int axisIndex, int rowBitmap, int angle, long durationMillis ) |
|
234 | 230 |
{ |
235 | 231 |
int mult = 1; |
236 | 232 |
|
... | ... | |
241 | 237 |
mCurrentRotAxis= axisIndex; |
242 | 238 |
mRotRowBitmap = mParent.computeBandagedBitmap(rowBitmap,axisIndex); |
243 | 239 |
mRotationAngleStatic.set0(0.0f); |
244 |
mRotationAxis.set(axis);
|
|
240 |
mRotationAxis.set(mAxis[axisIndex]);
|
|
245 | 241 |
mRotationAngle.setDuration(durationMillis); |
246 | 242 |
mRotationAngle.resetToBeginning(); |
247 | 243 |
mRotationAngle.add(new Static1D(0)); |
... | ... | |
256 | 252 |
// i.e. we just touched the screen, moved it a little bit and the TouchControl has figured out |
257 | 253 |
// along which axis we are going to rotate. |
258 | 254 |
|
259 |
synchronized boolean beginRotation(Static3D axis, int axisIndex, int row )
|
|
255 |
synchronized boolean beginRotation(int axisIndex, int row ) |
|
260 | 256 |
{ |
261 | 257 |
if( mRotationState==STATE_ROTATE ) return false; |
262 | 258 |
if( mRotationState==STATE_FINISH ) removeRotation(); |
... | ... | |
265 | 261 |
mCurrentRotAxis= axisIndex; |
266 | 262 |
mRotRowBitmap = mParent.computeBandagedBitmap( (1<<row),axisIndex ); |
267 | 263 |
mRotationAngleStatic.set0(0.0f); |
268 |
mRotationAxis.set(axis);
|
|
264 |
mRotationAxis.set( mAxis[axisIndex] );
|
|
269 | 265 |
mRotationAngle.add(mRotationAngleStatic); |
270 | 266 |
mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axisIndex*mMaxNumLayers) , -1); |
271 | 267 |
|
... | ... | |
277 | 273 |
boolean isSolved(boolean solved) |
278 | 274 |
{ |
279 | 275 |
mCanGhost = solved; |
280 |
return (solved && (mGhostAngle==0 || mGhostEffectBitmap==0) );
|
|
276 |
return (solved && (mGhostAngle==0 || mGhostEffectBitmap==mSolvedBitmap) );
|
|
281 | 277 |
} |
282 | 278 |
} |
src/main/java/org/distorted/objectlib/main/TwistyObject.java | ||
---|---|---|
103 | 103 |
private int mNumCubitFaces, mNumStickerTypes; |
104 | 104 |
private Static3D[] mAxis; |
105 | 105 |
private float[][] mCuts; |
106 |
private int[][] mMinimalCubiesInRow; |
|
106 | 107 |
private int[] mNumCuts; |
107 | 108 |
private float[][] mOrigPos; |
108 | 109 |
private Static4D[] mOrigQuat; |
... | ... | |
224 | 225 |
mNumCuts[i] = (mCuts==null || mCuts[i]==null ? 0 : mCuts[i].length); |
225 | 226 |
} |
226 | 227 |
|
228 |
mMinimalCubiesInRow = getMinimalCubiesInRow(); |
|
227 | 229 |
mNumCubits = mOrigPos.length; |
228 | 230 |
mNumFaceColors = getNumFaceColors(); |
229 | 231 |
mBelongs = new boolean[mNumCubits]; |
... | ... | |
968 | 970 |
return ObjectScrambler.SCRAMBLING_ALGORITHMS; |
969 | 971 |
} |
970 | 972 |
|
973 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
974 |
|
|
975 |
public int[][] getMinimalCubiesInRow() |
|
976 |
{ |
|
977 |
return null; |
|
978 |
} |
|
979 |
|
|
971 | 980 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
972 | 981 |
|
973 | 982 |
int computeBandagedBitmap(int rowBitmap, int axis) |
... | ... | |
988 | 997 |
} |
989 | 998 |
} |
990 | 999 |
|
1000 |
if( mMinimalCubiesInRow!=null ) |
|
1001 |
{ |
|
1002 |
int[] minC = mMinimalCubiesInRow[axis]; |
|
1003 |
int numL = minC.length; |
|
1004 |
int[] numC = new int[numL]; |
|
1005 |
|
|
1006 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
1007 |
{ |
|
1008 |
int bitmap = mCubits[cubit].getRotRow(axis); |
|
1009 |
|
|
1010 |
for(int i=0; i<numL; i++) |
|
1011 |
{ |
|
1012 |
if( (bitmap&0x1)!=0 ) numC[i]++; |
|
1013 |
bitmap>>=1; |
|
1014 |
} |
|
1015 |
} |
|
1016 |
|
|
1017 |
int bitmap,initBitmap = 0; |
|
1018 |
|
|
1019 |
while( initBitmap!=rowBitmap ) |
|
1020 |
{ |
|
1021 |
initBitmap = rowBitmap; |
|
1022 |
bitmap = rowBitmap; |
|
1023 |
int last = 0; |
|
1024 |
|
|
1025 |
for(int i=0; i<numL; i++) |
|
1026 |
{ |
|
1027 |
if( numC[i]<minC[i] && numC[i]>0 ) |
|
1028 |
{ |
|
1029 |
if( (bitmap&0x1)!=0 ) |
|
1030 |
{ |
|
1031 |
if( i>0 ) rowBitmap |= (1<<(i-1)); |
|
1032 |
if( i<numL-1) rowBitmap |= (1<<(i+1)); |
|
1033 |
} |
|
1034 |
else if( (bitmap&0x2)!=0 || last>0 ) // we are not rotating this row, but |
|
1035 |
// we are rotating the next or the prev |
|
1036 |
{ |
|
1037 |
rowBitmap |= (1<<i); |
|
1038 |
} |
|
1039 |
} |
|
1040 |
|
|
1041 |
last = (bitmap&0x1); |
|
1042 |
bitmap>>=1; |
|
1043 |
} |
|
1044 |
} |
|
1045 |
} |
|
1046 |
|
|
991 | 1047 |
return rowBitmap; |
992 | 1048 |
} |
993 | 1049 |
|
... | ... | |
1124 | 1180 |
|
1125 | 1181 |
synchronized long addRotation(EffectListener listener, int axis, int rowBitmap, int angle, long durationMillis ) |
1126 | 1182 |
{ |
1127 |
return mRotation.addRotation(listener,mAxis[axis],axis,rowBitmap,angle,durationMillis);
|
|
1183 |
return mRotation.addRotation(listener,axis,rowBitmap,angle,durationMillis); |
|
1128 | 1184 |
} |
1129 | 1185 |
|
1130 | 1186 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
1143 | 1199 |
android.util.Log.e("object", "invalid rotation axis: "+axis); |
1144 | 1200 |
return false; |
1145 | 1201 |
} |
1146 |
if( row<0 || row>=mNumLayers[axis] ) |
|
1147 |
{ |
|
1148 |
android.util.Log.e("object", "invalid rotation row: "+row); |
|
1149 |
return false; |
|
1150 |
} |
|
1151 | 1202 |
|
1152 |
return mRotation.beginRotation(mAxis[axis],axis,row);
|
|
1203 |
return mRotation.beginRotation(axis,row); |
|
1153 | 1204 |
} |
1154 | 1205 |
|
1155 | 1206 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
src/main/java/org/distorted/objectlib/touchcontrol/TouchControlBall.java | ||
---|---|---|
366 | 366 |
|
367 | 367 |
public void enableGhostAxis(int axNum, boolean enable) |
368 | 368 |
{ |
369 |
mGhostAxisEnabled = enable ? axNum : -1;
|
|
369 |
mGhostAxisEnabled = enable ? -1 : axNum;
|
|
370 | 370 |
} |
371 | 371 |
} |
src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeChanging.java | ||
---|---|---|
622 | 622 |
|
623 | 623 |
public void enableGhostAxis(int axNum, boolean enable) |
624 | 624 |
{ |
625 |
mGhostAxisEnabled = enable ? axNum : -1;
|
|
625 |
mGhostAxisEnabled = enable ? -1 : axNum;
|
|
626 | 626 |
} |
627 | 627 |
} |
src/main/java/org/distorted/objectlib/touchcontrol/TouchControlShapeConstant.java | ||
---|---|---|
468 | 468 |
|
469 | 469 |
public void enableGhostAxis(int axNum, boolean enable) |
470 | 470 |
{ |
471 |
mGhostAxisEnabled = enable ? axNum : -1;
|
|
471 |
mGhostAxisEnabled = enable ? -1 : axNum;
|
|
472 | 472 |
} |
473 | 473 |
} |
Also available in: Unified diff
Support for shape-shifting cuboids. (except for the flat ones like the Super Floppy)