Project

General

Profile

Download (9.64 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyBandagedAbstract.java @ f925d455

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.objects;
11

    
12
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
13

    
14
import org.distorted.library.type.Static3D;
15
import org.distorted.library.type.Static4D;
16
import org.distorted.objectlib.helpers.ObjectShape;
17
import org.distorted.objectlib.helpers.ObjectSignature;
18
import org.distorted.objectlib.main.InitData;
19
import org.distorted.objectlib.scrambling.ScrambleState;
20
import org.distorted.objectlib.shape.ShapeHexahedron;
21
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
22

    
23
import java.io.InputStream;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

    
27
public abstract class TwistyBandagedAbstract extends ShapeHexahedron
28
{
29
  // the three rotation axis of a 3x3 Cube. Must be normalized.
30
  static final Static3D[] ROT_AXIS = new Static3D[]
31
         {
32
           new Static3D(1,0,0),
33
           new Static3D(0,1,0),
34
           new Static3D(0,0,1)
35
         };
36

    
37
  private int[][] mBasicAngle;
38
  private float[][] mCuts;
39
  private int[][] mSolvedQuatsAbstract;
40

    
41
  protected ObjectShape[] mTmpShapes;
42
  protected int mNumVariants;
43
  protected float[][] mPosition;
44
  protected ObjectSignature mSignature;
45

    
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

    
48
  public TwistyBandagedAbstract(InitData data, int meshState, int iconMode, float size, Static4D quat, Static3D move, float scale, InputStream stream)
49
    {
50
    super(data, meshState, iconMode, size, quat, move, scale, stream);
51
    }
52

    
53
///////////////////////////////////////////////////////////////////////////////////////////////////
54
// return 0 if cubit is 'external' (it has at least two walls which belong to two different faces
55
// of the cuboid, faces which do not both rotate along the same axis! So: it is an edge, a corner,
56
// or a bandaged cubit which 'comes out' in two different, non-opposite, faces.
57
// Otherwise, if the cubit only comes out in one face or in two faces which are opposite to each other,
58
// return the index of the first of the three quats which rotate stuff in this face (so right or left
59
// return 1 because quats 1,2,3 are the ones rotating along the X axis)
60

    
61
  private int cubitIsExternal(float[] pos, float dx, float dy, float dz)
62
    {
63
    int len = pos.length/3;
64
    int x=0, y=0, z=0;
65

    
66
    for(int i=0; i<len; i++)
67
      {
68
      float cx = pos[3*i  ];
69
      float cy = pos[3*i+1];
70
      float cz = pos[3*i+2];
71

    
72
      if( cx>dx || cx<-dx ) x=1;
73
      if( cy>dy || cy<-dy ) y=1;
74
      if( cz>dz || cz<-dz ) z=1;
75
      }
76

    
77
    if( x+y+z>=2 ) return 0;
78

    
79
    if( x==1 ) return 1;
80
    if( y==1 ) return 4;
81
    if( z==1 ) return 7;
82

    
83
    android.util.Log.e("D", "ERROR: unsupported: internal cubit! ");
84
    return 0;
85
    }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
  float[][] getPositions()
90
    {
91
    if( mPosition==null ) mPosition = getInitData().getPos();
92
    return mPosition;
93
    }
94

    
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96
// If we have a flat cuboid than retCubitSolvedStatus() wrongly reports that the internal cubits
97
// are edges (they do have two non-black faces after all!) which leads to wrong solvedQuats and
98
// mis-detection of a solved status. Correct this manually here.
99
//
100
// Note that this is still not completely good in case of bandaged cuboids - there can be a 4x4x2
101
// bandaged cuboid whose 4 'internal' cubits from the 4x4 face are fused with the other 4 internal
102
// cubits from the other 4x4 face - and those would again get mis-detected as edges...
103

    
104
  @Override
105
  public int[][] getSolvedQuats()
106
    {
107
    if( mSolvedQuatsAbstract==null )
108
      {
109
      int[] numLayers = getNumLayers();
110
      float dx = 0.5f*(numLayers[0]-1) - 0.1f;
111
      float dy = 0.5f*(numLayers[1]-1) - 0.1f;
112
      float dz = 0.5f*(numLayers[2]-1) - 0.1f;
113

    
114
      float[][] pos = getPositions();
115
      int numTotal = pos.length;
116
      boolean[] isExternal = new boolean[numTotal];
117
      int[] internalQuat = new int[numTotal];
118
      int numExternal = 0;
119
      int pointer = 0;
120

    
121
      for(int cubit=0; cubit<numTotal; cubit++)
122
        {
123
        int q = cubitIsExternal(pos[cubit],dx,dy,dz);
124

    
125
        if( q<=0 )
126
          {
127
          isExternal[cubit] = true;
128
          numExternal++;
129
          }
130
        else
131
          {
132
          isExternal[cubit] = false;
133
          internalQuat[pointer] = q;
134
          pointer++;
135
          }
136
        }
137

    
138
      int numInternal = numTotal - numExternal;
139

    
140
      mSolvedQuatsAbstract = new int[numInternal+1][];
141
      mSolvedQuatsAbstract[0] = new int[numExternal+1];
142
      mSolvedQuatsAbstract[0][0] = numExternal;
143

    
144
      for(int i=0; i<numInternal; i++)
145
        {
146
        int q = internalQuat[i];
147
        mSolvedQuatsAbstract[i+1] = new int[5];
148
        mSolvedQuatsAbstract[i+1][0] = 1;
149
        mSolvedQuatsAbstract[i+1][2] = q;
150
        mSolvedQuatsAbstract[i+1][3] = q+1;
151
        mSolvedQuatsAbstract[i+1][4] = q+2;
152
        }
153

    
154
      int pointerExternal = 1;
155
      int pointerInternal = 1;
156

    
157
      for(int cubit=0; cubit<numTotal; cubit++)
158
        {
159
        if( isExternal[cubit] ) mSolvedQuatsAbstract[0][pointerExternal++] = cubit;
160
        else                    mSolvedQuatsAbstract[pointerInternal++][1] = cubit;
161
        }
162
      }
163

    
164
    return mSolvedQuatsAbstract;
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168
// Computing scramble states of many a bandaged cubes takes way too long time and too much space.
169
// Return null here and turn to construction of scramble tables just-in-time.
170

    
171
  @Override
172
  public ScrambleState[] getScrambleStates()
173
    {
174
    return null;
175
    }
176

    
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

    
179
  @Override
180
  public int getScrambleType()
181
    {
182
    return 2;
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

    
187
  public float[][] getCuts(int[] numLayers)
188
    {
189
    if( mCuts==null )
190
      {
191
      mCuts = new float[3][];
192

    
193
      for(int axis=0; axis<3; axis++)
194
        {
195
        int len = numLayers[axis];
196
        float start = (2-len)*0.5f;
197

    
198
        if( len>=2 )
199
          {
200
          mCuts[axis] = new float[len-1];
201
          for(int i=0; i<len-1; i++) mCuts[axis][i] = start+i;
202
          }
203
        }
204
      }
205

    
206
    return mCuts;
207
    }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

    
211
  public boolean[][] getLayerRotatable(int[] numLayers)
212
    {
213
    int numAxis = ROT_AXIS.length;
214
    boolean[][] layerRotatable = new boolean[numAxis][];
215

    
216
    for(int i=0; i<numAxis; i++)
217
      {
218
      layerRotatable[i] = new boolean[numLayers[i]];
219
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
220
      }
221

    
222
    return layerRotatable;
223
    }
224

    
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226

    
227
  public int getTouchControlSplit()
228
    {
229
    return TYPE_NOT_SPLIT;
230
    }
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233

    
234
  public int[][][] getEnabled()
235
    {
236
    return new int[][][] { {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}} };
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  public float[] getDist3D(int[] numLayers)
242
    {
243
    float x = numLayers[0];
244
    float y = numLayers[1];
245
    float z = numLayers[2];
246
    float a = (x+y+z)/1.5f;
247

    
248
    return new float[] {x/a,x/a,y/a,y/a,z/a,z/a};
249
    }
250

    
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252

    
253
  public Static3D[] getFaceAxis()
254
    {
255
    return TouchControlHexahedron.FACE_AXIS;
256
    }
257

    
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259

    
260
  public float[][] getStickerAngles()
261
    {
262
    return null;
263
    }
264

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

    
267
  public float[][] getCubitPositions(int[] numLayers)
268
    {
269
    return getPositions();
270
    }
271

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

    
274
  public Static3D[] getRotationAxis()
275
    {
276
    return ROT_AXIS;
277
    }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280

    
281
  public int[][] getBasicAngles()
282
    {
283
     if( mBasicAngle==null )
284
      {
285
      int[] num = getNumLayers();
286
      int numX = num[0];
287
      int numY = num[1];
288
      int numZ = num[2];
289

    
290
      int x = numY==numZ ? 4 : 2;
291
      int y = numX==numZ ? 4 : 2;
292
      int z = numX==numY ? 4 : 2;
293

    
294
      int[] tmpX = new int[numX];
295
      for(int i=0; i<numX; i++) tmpX[i] = x;
296
      int[] tmpY = new int[numY];
297
      for(int i=0; i<numY; i++) tmpY[i] = y;
298
      int[] tmpZ = new int[numZ];
299
      for(int i=0; i<numZ; i++) tmpZ[i] = z;
300

    
301
      mBasicAngle = new int[][] { tmpX,tmpY,tmpZ };
302
      }
303

    
304
    return mBasicAngle;
305
    }
306
}
(2-2/41)