Project

General

Profile

« Previous | Next » 

Revision 8439f1dd

Added by Leszek Koltunski 9 months ago

Ghost....

View differences:

src/main/java/org/distorted/objectlib/main/TwistyObjectControllable.java
187 187
    if( mRotationState==STATE_ROTATE ) return 0;
188 188
    if( mRotationState==STATE_FINISH ) { removeRotation(); mult = -1; }
189 189

  
190
    mGhost.onAutomaticRotation();
190
    if( mGhost.ghostBlocked(-1) )
191
      {
192
      axis      = mGhost.unblockingAxis();
193
      rowBitmap = mGhost.unblockingBitmap();
194
      angle     = mGhost.unblockingAngle(angle);
195
      }
191 196

  
192 197
    mRotationState = STATE_ROTATE;
193 198
    mCurrentRotAxis= axis;
src/main/java/org/distorted/objectlib/main/TwistyObjectGhost.java
27 27
  private final TwistyObjectControllable mObject;
28 28
  private final int[][] mBasicAngles;
29 29
  private final int mNumCubits;
30
  private final int mGhostAngle;
31 30
  private final Static3D[] mAxis;
32 31
  private final Static4D[] mObjectQuats;
33 32
  private final int mNumAxis;
34 33
  private final int mNumQuats;
34
  private final int[] mNumLayers;
35
  private final int mMaxNumLayers;
36

  
37
  private final int mGhostAngle;       // defined
38
  private final int mGhostOrigAxis;    // defined
39
  private final int mGhostFirstRow;    // defined
40
  private int mGhostAxis;              // if Ghost is not blocked, those two are undefined.
41
  private boolean mGhostAxisInverted;  // Otherwise, this is the axis and its direction along which the
42
                                       // puzzle is blocked (!inverted -> axis agrees with rotAxis)
43
  private boolean mGhostBlocked;       // defined
44
  private int mGhostRowBitmap;         // defined
35 45

  
36 46
  private VertexEffectRotate mGhostEffect;
37
  private int mGhostNumRows;
38
  private int mGhostBasicDeg;
39 47
  private Static1D mGhostStatic;
40 48
  private Static3D mGhostEffectAxis;
41 49
  private int[][][] mGhostAxisJumpedTo;
42 50
  private boolean[] mGhostCubitRotated, mGhostOrigRotated;
43 51
  private Static4D mGhostQuat;
44
  private int mMaxNumLayers;
45

  
46
  private int mGhostAxis;               // the index of the axis of rotations along which the ghost
47
                                        // can always move.
48
  private int mGhostFirstRow;           // Every ghost has two kinds of rows along its mGhostAxis:
49
                                        // 'left' ones (normal) and 'right' ones (blocking). FirstRow is
50
                                        // the number of the first right row.
51
  private boolean mGhostBlocked;        // if true, all rotations along axis different than mGhostAxis
52
                                        // are blocked.
53
  private int mGhostRowBitmap;          // a bitmap; if bit[N] is 1, this means that layer N along the
54
                                        // mGhostAxis is ghostRotated (initially all layers left of
55
                                        // mGhostFirstRow are not and every ones right and including
56
                                        // mGhostFirstRow are)
57
  private boolean mGhostAxisInverted;   // we also care about the direction of the ghostAxis. It can
58
                                        // change, for example a 2x2x2 has 3 rotAxes, but its ghostAxis
59
                                        // can point in 6 directions (3 axes, each inverted or not)
60 52

  
61 53
///////////////////////////////////////////////////////////////////////////////////////////////////
62 54

  
......
69 61
    mObjectQuats= controllable.getQuats();
70 62
    mNumAxis    = mAxis.length;
71 63
    mNumQuats   = mObjectQuats.length;
64
    mNumLayers  = controllable.getNumLayers();
72 65

  
73 66
    DistortedEffects effects = controllable.getObjectEffects();
74
    int[] numLayers  = controllable.getNumLayers();
75 67

  
76
    for(int numLayer : numLayers)
77
      if( mMaxNumLayers<numLayer ) mMaxNumLayers = numLayer;
68
    int maxNumLayers = 0;
69
    for(int numLayer : mNumLayers)
70
      if( maxNumLayers<numLayer ) maxNumLayers = numLayer;
71
    mMaxNumLayers = maxNumLayers;
78 72

  
79
    mGhostAngle = controllable.getGhostAngle();
73
    mGhostAngle    = controllable.getGhostAngle();
74
    mGhostOrigAxis = controllable.getGhostAxis();
75
    mGhostFirstRow = controllable.getGhostFirstRow();
80 76

  
81 77
    if( mGhostAngle!=0 )
82 78
      {
83
      mGhostAxis    = controllable.getGhostAxis();
84
      mGhostFirstRow= controllable.getGhostFirstRow();
79
      mGhostAxis    = mGhostOrigAxis;
85 80
      mGhostBlocked = true;
86
      mGhostBasicDeg= 360/mBasicAngles[mGhostAxis][0];
87
      mGhostNumRows = numLayers[mGhostAxis];
88 81
      mGhostStatic  = new Static1D(mGhostAngle);
89 82

  
90 83
      Static3D currGhostAxis = mAxis[mGhostAxis];
......
103 96
      computeGhostAxisJumps();
104 97

  
105 98
      mGhostAxisInverted = false;
106
      int tmp = 1<<(mGhostNumRows-mGhostFirstRow);
99
      int tmp = 1<<(mNumLayers[mGhostAxis]-mGhostFirstRow);
107 100
      mGhostRowBitmap = (tmp-1)<<mGhostFirstRow;
108 101

  
109 102
      reinitializeGhostStuff();
......
112 105
    }
113 106

  
114 107
///////////////////////////////////////////////////////////////////////////////////////////////////
115
// We are adding an automatic rotation [i.e. stepping through a solution, backing a move, scrambling]
116
// Do various ghost-related stuff, e.g. change (axis,row,angle) to unblock the ghost if it is blocked!
108
// is the ghost currently blocked along the 'axis' ?
117 109

  
118
  void onAutomaticRotation()
119
    {
120
    if( mGhostAngle!=0 && mGhostBlocked )
121
      {
122
      /*
123
      axis = mGhostAxis;
124
      int tmp = 1<<(mGhostNumRows-mGhostFirstRow);
125
      rowBitmap = (tmp-1)<<mGhostFirstRow;
126
      angle -= mGhostAngle;
127
       */
128
      }
129
    }
110
  boolean ghostBlocked(int axis) { return mGhostBlocked && axis!=mGhostAxis; }
130 111

  
131 112
///////////////////////////////////////////////////////////////////////////////////////////////////
132 113
// Called when finishing a rotation.
133 114
// Is 'ghostRotation' (rotating a row by a ghostAngle) possible along this axis?
134 115

  
135
  boolean ghostRotationImpossible(int axis)
136
    {
137
    return (mGhostAngle==0 || axis!=mGhostAxis);
138
    }
116
  boolean ghostRotationImpossible(int axis) { return mGhostAngle==0; }
117

  
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119
// We are adding an automatic rotation [i.e. stepping through a solution, backing a move, scrambling]
120
// Return (axis,rowBitmap,angle) so that the puzzle unblocks!
121

  
122
  int unblockingAxis()           { return mGhostAxis; }
123
  int unblockingBitmap()         { return (1<<(mNumLayers[mGhostAxis]-mGhostFirstRow))-1; }
124
  int unblockingAngle(int angle) { return angle-mGhostAngle; }
139 125

  
140 126
///////////////////////////////////////////////////////////////////////////////////////////////////
141 127
// ghostRotation is possible, so return an rotAngle nearest to 'angle' taking into account
......
172 158
    {
173 159
    int nonGhostAngle = (int)angle;
174 160

  
175
    if( mGhostAngle!=0 )
161
    if( mGhostAngle!=0 && (axis==mGhostAxis || !mGhostBlocked) )
176 162
      {
177
      if( (nonGhostAngle%mGhostBasicDeg)!=0 )
163
      int basicDeg = 360/mBasicAngles[mGhostAxis][0];
164

  
165
      if( (nonGhostAngle%basicDeg)!=0 )
178 166
        {
179
             if( ((nonGhostAngle-mGhostAngle)%mGhostBasicDeg == 0) ) nonGhostAngle -= mGhostAngle;
180
        else if( ((nonGhostAngle+mGhostAngle)%mGhostBasicDeg == 0) ) nonGhostAngle += mGhostAngle;
181
        else android.util.Log.e("D", "error in ghost remove rotation");
167
             if( ((nonGhostAngle-mGhostAngle)%basicDeg == 0) ) nonGhostAngle -= mGhostAngle;
168
        else if( ((nonGhostAngle+mGhostAngle)%basicDeg == 0) ) nonGhostAngle += mGhostAngle;
169
        else android.util.Log.e("D", "error in ghost onRemoveRotation");
182 170
        }
183
      if( angle!=0 ) doGhostStuff(axis,rowBitmap,angle);
171

  
172
      accountForGhostAngleOnRemoveRotation(axis,rowBitmap,angle);
184 173
      }
185 174

  
186 175
    return nonGhostAngle;
......
189 178
///////////////////////////////////////////////////////////////////////////////////////////////////
190 179
// Called when removing a rotation, after all cubits have been rotated.
191 180

  
192
  void onPostRemoveRotation()
193
    {
194
    computeGhostCubitRotated();
195
    }
196

  
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198
// solve the ghost part of the puzzle
199

  
200
  void solve()
201
    {
202
    if( mGhostAngle!=0 )
203
      {
204
      mGhostAxis = mObject.getGhostAxis();
205
      mGhostAxisInverted = false;
206
      int tmp = 1<<(mGhostNumRows-mGhostFirstRow);
207
      mGhostRowBitmap = (tmp-1)<<mGhostFirstRow;
208
      reinitializeGhostStuff();
209
      }
210
    }
181
  void onPostRemoveRotation() { computeGhostCubitRotated(); }
211 182

  
212 183
///////////////////////////////////////////////////////////////////////////////////////////////////
213 184
// Is the ghost part of the puzzle currently in a solved state?
......
225 196
    }
226 197

  
227 198
///////////////////////////////////////////////////////////////////////////////////////////////////
228
// is the ghost currently blocked, i.e. it can only move along the ghostAxis?
199
// solve the ghost part of the puzzle
229 200

  
230
  boolean ghostBlocked(int axis) { return mGhostBlocked && axis!=mGhostAxis; }
201
  void solve()
202
    {
203
    if( mGhostAngle!=0 )
204
      {
205
      mGhostAxis = mGhostOrigAxis;
206
      mGhostAxisInverted = false;
207
      int tmp = 1<<(mNumLayers[mGhostAxis]-mGhostFirstRow);
208
      mGhostRowBitmap = (tmp-1)<<mGhostFirstRow;
209
      reinitializeGhostStuff();
210
      }
211
    }
231 212

  
232 213
///////////////////////////////////////////////////////////////////////////////////////////////////
233 214
// read up from storage and restore the state of a ghost part of the puzzle.
......
279 260

  
280 261
///////////////////////////////////////////////////////////////////////////////////////////////////
281 262
// PRIVATE
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264

  
265
  private void accountForGhostAngleOnRemoveRotation(int axis, int rowBitmap, float angle)
266
    {
267
    int basicDeg = 360/mBasicAngles[axis][0];
268
    if( (angle%basicDeg)!=0 ) mGhostRowBitmap ^= rowBitmap;
269

  
270
    if( mGhostBlocked && axis!=mGhostAxis ) computeNewGhostAxisAndBitmap(axis,angle);
271

  
272
    int fullOnes  = (1<<(mNumLayers[mGhostAxis]))-1;
273
    mGhostBlocked = ( mGhostRowBitmap!=0 && mGhostRowBitmap!=fullOnes );
274

  
275
    if( mGhostRowBitmap==fullOnes )
276
      {
277
      mGhostRowBitmap=0;
278
      computeGhostQuaternion();
279
      mObject.rotateCameraQuat(mGhostQuat);
280
      }
281

  
282
    mGhostEffect.setMeshAssociation(mGhostRowBitmap<<(mGhostAxis*mMaxNumLayers),-1);
283
    }
284

  
282 285
///////////////////////////////////////////////////////////////////////////////////////////////////
283 286

  
284 287
  private void reinitializeGhostStuff()
......
291 294

  
292 295
    mGhostEffect.setMeshAssociation(mGhostRowBitmap<<(mGhostAxis*mMaxNumLayers),-1);
293 296

  
294
    int fullOnes  = (1<<(mGhostNumRows))-1;
297
    int fullOnes  = (1<<(mNumLayers[mGhostAxis]))-1;
295 298
    mGhostBlocked = ( mGhostRowBitmap!=0 && mGhostRowBitmap!=fullOnes );
296 299

  
297 300
    mGhostStatic.set0(mGhostAxisInverted ? -mGhostAngle : mGhostAngle);
......
437 440
    return -1;
438 441
    }
439 442

  
440
///////////////////////////////////////////////////////////////////////////////////////////////////
441

  
442
  private void doGhostStuff(int axis, int rowBitmap, float angle)
443
    {
444
    if( axis==mGhostAxis && (angle%mGhostBasicDeg)!=0 ) mGhostRowBitmap ^= rowBitmap;
445

  
446
    if( mGhostBlocked && axis!=mGhostAxis )
447
      {
448
      computeNewGhostAxisAndBitmap(axis,angle);
449
      mGhostEffect.setMeshAssociation(mGhostRowBitmap<<(mGhostAxis*mMaxNumLayers),-1);
450
      }
451

  
452
    int fullOnes  = (1<<(mGhostNumRows))-1;
453
    mGhostBlocked = ( mGhostRowBitmap!=0 && mGhostRowBitmap!=fullOnes );
454

  
455
    if( mGhostRowBitmap==fullOnes )
456
      {
457
      mGhostRowBitmap=0;
458
      computeGhostQuaternion();
459
      mObject.rotateCameraQuat(mGhostQuat);
460
      }
461

  
462
    mGhostEffect.setMeshAssociation(mGhostRowBitmap<<(mGhostAxis*mMaxNumLayers),-1);
463
    }
464

  
465 443
///////////////////////////////////////////////////////////////////////////////////////////////////
466 444
// We have just rotated the whole blocked Ghost by 'angle' along 'axis'.
467 445
//
......
492 470
    mGhostEffectAxis.set(x,y,z);
493 471

  
494 472
    if( (inverted==1)^mGhostAxisInverted ) invertGhostRotBitmap();
473

  
474

  
495 475
    }
496 476

  
497 477
///////////////////////////////////////////////////////////////////////////////////////////////////
......
503 483

  
504 484
    int inve = 0;
505 485
    int mask = 1;
486
    int numr = mNumLayers[mGhostAxis];
506 487

  
507
    for(int i=0; i<mGhostNumRows; i++)
488
    for(int i=0; i<numr; i++)
508 489
      {
509
      if( (mGhostRowBitmap&mask) !=0 ) inve += (1<<(mGhostNumRows-i-1));
490
      if( (mGhostRowBitmap&mask) !=0 ) inve += (1<<(numr-i-1));
510 491
      mask *=2;
511 492
      }
512 493

  

Also available in: Unified diff