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
|
}
|