Project

General

Profile

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

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

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.shape.ShapeHexahedron;
20
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
21

    
22
import java.io.InputStream;
23

    
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25

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

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

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

    
45
///////////////////////////////////////////////////////////////////////////////////////////////////
46

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

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

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

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

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

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

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

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

    
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87

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

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

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

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

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

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

    
137
      int numInternal = numTotal - numExternal;
138

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

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

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

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

    
163
    return mSolvedQuatsAbstract;
164
    }
165

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

    
170
  public int[][] getScrambleEdges()
171
    {
172
    return null;
173
    }
174

    
175
///////////////////////////////////////////////////////////////////////////////////////////////////
176

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

    
183
///////////////////////////////////////////////////////////////////////////////////////////////////
184

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

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

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

    
204
    return mCuts;
205
    }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

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

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

    
220
    return layerRotatable;
221
    }
222

    
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224

    
225
  public int getTouchControlSplit()
226
    {
227
    return TYPE_NOT_SPLIT;
228
    }
229

    
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231

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

    
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238

    
239
  public Static3D[] getFaceAxis()
240
    {
241
    return TouchControlHexahedron.FACE_AXIS;
242
    }
243

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245

    
246
  public float[][] getStickerAngles()
247
    {
248
    return null;
249
    }
250

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

    
253
  public float[][] getCubitPositions(int[] numLayers)
254
    {
255
    return getPositions();
256
    }
257

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

    
260
  public Static3D[] getRotationAxis()
261
    {
262
    return ROT_AXIS;
263
    }
264

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

    
267
  public int[][] getBasicAngles()
268
    {
269
     if( mBasicAngle==null )
270
      {
271
      int[] num = getNumLayers();
272
      int numX = num[0];
273
      int numY = num[1];
274
      int numZ = num[2];
275

    
276
      int x = numY==numZ ? 4 : 2;
277
      int y = numX==numZ ? 4 : 2;
278
      int z = numX==numY ? 4 : 2;
279

    
280
      int[] tmpX = new int[numX];
281
      for(int i=0; i<numX; i++) tmpX[i] = x;
282
      int[] tmpY = new int[numY];
283
      for(int i=0; i<numY; i++) tmpY[i] = y;
284
      int[] tmpZ = new int[numZ];
285
      for(int i=0; i<numZ; i++) tmpZ[i] = z;
286

    
287
      mBasicAngle = new int[][] { tmpX,tmpY,tmpZ };
288
      }
289

    
290
    return mBasicAngle;
291
    }
292
}
(2-2/41)