Project

General

Profile

« Previous | Next » 

Revision 63bfcdd1

Added by Leszek Koltunski over 1 year ago

Support for shape-shifting cuboids. (except for the flat ones like the Super Floppy)

View differences:

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