Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / bandaged / FactoryBandagedMegaminx.java @ 45aedaa7

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 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.bandaged;
11

    
12
import static org.distorted.objectlib.bandaged.BandagedObjectMegaminx.MEGA_D;
13
import static org.distorted.objectlib.bandaged.BandagedObjectMegaminx.SIN18;
14
import static org.distorted.objectlib.main.TwistyObject.SQ5;
15
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.C2;
16
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.LEN;
17
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.SIN54;
18

    
19
import org.distorted.library.type.Static3D;
20
import org.distorted.objectlib.objects.TwistyDodecahedron;
21
import org.distorted.objectlib.touchcontrol.TouchControlDodecahedron;
22

    
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

    
25
public class FactoryBandagedMegaminx extends FactoryBandaged
26
  {
27
  private static FactoryBandagedMegaminx mThis;
28

    
29
  private int[][] mEdgeMap;
30
  private float[][] mCorners;
31

    
32
///////////////////////////////////////////////////////////////////////////////////////////////////
33

    
34
  private FactoryBandagedMegaminx()
35
    {
36

    
37
    }
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

    
41
  private float[][] genericGetCuts(int numLayers, float dist)
42
    {
43
    float[][] cuts = new float[6][numLayers-1];
44
    float D = numLayers* TouchControlDodecahedron.DIST3D;
45
    float X = 2*D/(2+SIN18);  // height of the 'upper' part of a dodecahedron, i.e. put it on a table,
46
                              // its height is then 2D, it has one 'lower' part of height X, one
47
                              // 'middle' part of height Y and one upper part of height X again.
48
    int num = (numLayers-1)/2;
49
    float G = X*dist/num;     // height of one Layer
50

    
51
    for(int i=0; i<num; i++)
52
      {
53
      float cut = -D + (i+0.85f)*G;  // 0.85? not fully correct; attempt to make it
54
                                     // easier to rotate the outer layers
55
      int j = 2*num-1-i;
56
      cuts[0][i] =  cut;
57
      cuts[0][j] = -cut;
58
      cuts[1][i] =  cut;
59
      cuts[1][j] = -cut;
60
      cuts[2][i] =  cut;
61
      cuts[2][j] = -cut;
62
      cuts[3][i] =  cut;
63
      cuts[3][j] = -cut;
64
      cuts[4][i] =  cut;
65
      cuts[4][j] = -cut;
66
      cuts[5][i] =  cut;
67
      cuts[5][j] = -cut;
68
      }
69

    
70
    return cuts;
71
    }
72

    
73
///////////////////////////////////////////////////////////////////////////////////////////////////
74

    
75
  public static FactoryBandagedMegaminx getInstance()
76
    {
77
    if( mThis==null ) mThis = new FactoryBandagedMegaminx();
78
    return mThis;
79
    }
80

    
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

    
83
  public float[][] getVertices(int variant)
84
    {
85
    return null;
86
    }
87

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89

    
90
  public int[][] getIndices(int variant)
91
    {
92
    return null;
93
    }
94

    
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96
// return:
97
// 0: (x,y,z) does not belong to edge corner0->corner1
98
// 1: it belongs and is closer to corner0
99
// 2: it belongs and is closer to corner1
100

    
101
  private int belongsToEdge(float[] corner0, float[] corner1, float x, float y, float z)
102
    {
103
    float MAXERR = 0.01f;
104

    
105
    float v0x = corner0[0] - x;
106
    float v0y = corner0[1] - y;
107
    float v0z = corner0[2] - z;
108
    float v1x = corner1[0] - x;
109
    float v1y = corner1[1] - y;
110
    float v1z = corner1[2] - z;
111

    
112
    float len0 = v0x*v0x + v0y*v0y + v0z*v0z;
113
    float len1 = v1x*v1x + v1y*v1y + v1z*v1z;
114

    
115
    if( v0x != 0 )
116
      {
117
      float A = v1x/v0x;
118
      float errY = v1y - A*v0y;
119
      float errZ = v1z - A*v0z;
120
      if( errY>-MAXERR && errY<MAXERR && errZ>-MAXERR && errZ<MAXERR ) return len0<len1 ? 1:2;
121
      else return 0;
122
      }
123
    else if( v0y != 0 )
124
      {
125
      float A = v1y/v0y;
126
      float errX = v1x - A*v0x;
127
      float errZ = v1z - A*v0z;
128
      if( errX>-MAXERR && errX<MAXERR && errZ>-MAXERR && errZ<MAXERR ) return len0<len1 ? 1:2;
129
      else return 0;
130
      }
131
    else if( v0z != 0 )
132
      {
133
      float A = v1z/v0z;
134
      float errX = v1x - A*v0x;
135
      float errY = v1y - A*v0y;
136
      if( errX>-MAXERR && errX<MAXERR && errY>-MAXERR && errY<MAXERR ) return len0<len1 ? 1:2;
137
      else return 0;
138
      }
139

    
140
    return 0;
141
    }
142

    
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

    
145
  public int getElementVariant(float x, float y, float z)
146
    {
147
    int size = mNumLayers[0];
148

    
149
    float CENT_DIST_SQ = TouchControlDodecahedron.DIST3D;
150
    float CORN_DIST_SQ = (18+6*SQ5)/16;
151
    float EDGE_DIST_SQ = (14+6*SQ5)/16;
152
    float EDHA_DIST_SQ = (15+6*SQ5)/16;
153

    
154
    float d = x*x + y*y + z*z;
155
    float MAXERR = 0.01f;
156

    
157
    switch(size)
158
      {
159
      case 2: return 0;
160
      case 3: float d3c = d/9 - CORN_DIST_SQ;
161
              float d3e = d/9 - EDGE_DIST_SQ;
162
              if( d3c<MAXERR && d3c>-MAXERR ) return 0;
163
              if( d3e<MAXERR && d3e>-MAXERR ) return 1;
164
              return 2;
165
      case 4: if( mCorners==null ) mCorners = TwistyDodecahedron.initializeCorners();
166
              if( mEdgeMap==null ) mEdgeMap = TwistyDodecahedron.initializeEdgeMap();
167

    
168
              float d4c = d/25 - CORN_DIST_SQ;
169
              float d4h = d/25 - EDHA_DIST_SQ;
170
              if( d4c<MAXERR && d4c>-MAXERR ) return 0;
171
              if( d4h<MAXERR && d4h>-MAXERR )
172
                {
173
                float xCorr = 9*x/25;  // mCorners has the coords assuming edge length is 3
174
                float yCorr = 9*y/25;  // here we have edge length = 5 - so correct for that
175
                float zCorr = 9*z/25;
176

    
177
                for(int[] edge : mEdgeMap)
178
                  {
179
                  float[] c0 = mCorners[edge[0]];
180
                  float[] c1 = mCorners[edge[1]];
181

    
182
                  int loc = belongsToEdge(c0, c1, xCorr, yCorr, zCorr);
183
                  if( loc!=0 ) return loc;
184
                  }
185

    
186
                return 1;
187
                }
188
              return 3;
189
      case 5: float dist = d/25;
190

    
191
              if( dist< CENT_DIST_SQ + MAXERR ) return 3;
192
              if( dist< EDGE_DIST_SQ - MAXERR ) return 2;
193
              if( dist< EDGE_DIST_SQ + MAXERR ) return 1;
194
              return 0;
195
      }
196

    
197
    return 0;
198
    }
199

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

    
202
  public float[][] getCuts(int[] numLayers)
203
    {
204
    int size = numLayers[0];
205

    
206
    if( (size%2)==1 ) return genericGetCuts(size  ,0.5f-MEGA_D);
207
    else              return genericGetCuts(size+1,0.5f);
208
    }
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

    
212
  public Static3D[] getNormals()
213
    {
214
    return TouchControlDodecahedron.FACE_AXIS;
215
    }
216

    
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218

    
219
  public float[][] getRotAxis()
220
    {
221
    return new float[][]
222
            {
223
                    {    C2/LEN, SIN54/LEN,    0      },
224
                    {   -C2/LEN, SIN54/LEN,    0      },
225
                    { 0        ,    C2/LEN, SIN54/LEN },
226
                    { 0        ,   -C2/LEN, SIN54/LEN },
227
                    { SIN54/LEN,    0     ,    C2/LEN },
228
                    { SIN54/LEN,    0     ,   -C2/LEN }
229
            };
230
    }
231

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

    
234
  public float[] getDist3D()
235
    {
236
    final float d = TouchControlDodecahedron.DIST3D*mNumLayers[0];
237
    return new float[] {d,d,d,d,d,d};
238
    }
239

    
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241
// all the 10 *distinct* edges of the dodecahedron
242

    
243
  public float[][] getDiameterAxis()
244
    {
245
    float A = (SQ5+1)/4;
246
    float B = (SQ5-1)/4;
247
    float C = 0.5f;
248

    
249
    return new float[][]
250
            {
251
              { A, B, C},
252
              { A, B,-C},
253
              { A,-B, C},
254
              { A,-B,-C},
255
              { B, C, A},
256
              { B, C,-A},
257
              { B,-C, A},
258
              { B,-C,-A},
259
              { C, A, B},
260
              { C, A,-B},
261
              { C,-A, B},
262
              { C,-A,-B},
263
            };
264
    }
265

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267

    
268
  public int diameterMap(float diameter)
269
    {
270
    if( diameter>=5.49f ) return 11;
271
    if( diameter>1.1f && diameter<1.9f ) return 3;
272
    return (int)(2*diameter+0.01f);
273
    }
274

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276

    
277
  public float[][] getBands(boolean iconMode)
278
    {
279
    float height= iconMode ? 0.001f : 0.04f;
280
    int[] angle = {68,56,50,43,39,35,32,30,28,26,25};
281
    float R     = 0.3f;
282
    float S     = 0.5f;
283
    int extraI  = 0;
284
    int extraV  = 0;
285
    int numVertA= mNumLayers[0]>=4 ? 4 : 5;
286
    int numVertI= mNumLayers[0]>=4 ? 2 : 3;
287

    
288
    return new float[][] { {  0.001f    ,angle[ 0],R,S,numVertI,extraV,extraI},
289
                           {height      ,angle[ 1],R,S,numVertA,extraV,extraI},
290
                           {height      ,angle[ 1],R,S,numVertA,extraV,extraI},
291
                           {height/ 1.5f,angle[ 2],R,S,numVertA,extraV,extraI},
292
                           {height/ 2.0f,angle[ 3],R,S,numVertA,extraV,extraI},
293
                           {height/ 2.5f,angle[ 4],R,S,numVertA,extraV,extraI},
294
                           {height/ 3.0f,angle[ 5],R,S,numVertA,extraV,extraI},
295
                           {height/ 3.5f,angle[ 6],R,S,numVertA,extraV,extraI},
296
                           {height/ 4.0f,angle[ 7],R,S,numVertA,extraV,extraI},
297
                           {height/ 4.5f,angle[ 8],R,S,numVertA,extraV,extraI},
298
                           {height/ 5.0f,angle[ 9],R,S,numVertA,extraV,extraI},
299
                           {height/ 5.5f,angle[10],R,S,numVertA,extraV,extraI}
300
                          };
301
    }
302
  }
(9-9/11)