Project

General

Profile

Download (11.9 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / objects / TwistyKilominx.java @ ead91342

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objects;
21

    
22
import android.content.res.Resources;
23
import android.graphics.Canvas;
24
import android.graphics.Paint;
25

    
26
import org.distorted.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.main.DistortedEffects;
28
import org.distorted.library.main.DistortedTexture;
29
import org.distorted.library.mesh.MeshBase;
30
import org.distorted.library.mesh.MeshSquare;
31
import org.distorted.library.type.Static3D;
32
import org.distorted.library.type.Static4D;
33
import org.distorted.main.R;
34
import org.distorted.main.RubikSurfaceView;
35

    
36
import static org.distorted.objects.FactoryCubit.COS18;
37
import static org.distorted.objects.FactoryCubit.COS54;
38

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

    
41
public class TwistyKilominx extends TwistyMinx
42
{
43
  private static MeshBase mMesh;
44

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

    
47
  TwistyKilominx(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
48
                 DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
49
    {
50
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.KILO, res, scrWidth);
51
    }
52

    
53
///////////////////////////////////////////////////////////////////////////////////////////////////
54

    
55
  private int numCubitsPerCorner(int numLayers)
56
    {
57
    return 3*((numLayers-3)/2)*((numLayers-5)/2) + (numLayers<5 ? 0:1);
58
    }
59

    
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61

    
62
  private int numCubitsPerEdge(int numLayers)
63
    {
64
    return numLayers<5 ? 0 : 2*(numLayers-4);
65
    }
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

    
69
  int getNumStickerTypes(int numLayers)
70
    {
71
    return numLayers<5 ? 1 : numLayers/2 + 1;
72
    }
73

    
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75

    
76
  float getScreenRatio()
77
    {
78
    return 1.00f;
79
    }
80

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

    
83
  float[] getCuts(int numLayers)
84
    {
85
    float[] cuts = new float[numLayers-1];
86
    float D = numLayers*MovementMinx.DIST3D;
87
    float E = 2*C1;           // 2*cos(36 deg)
88
    float X = 2*D*E/(1+2*E);  // height of the 'upper' part of a dodecahedron, i.e. put it on a table,
89
                              // its height is then D*2*DIST3D, it has one 'lower' part of height X, one
90
                              // 'middle' part of height Y and one upper part of height X again.
91
                              // It's edge length = numLayers/3.0f.
92
    int num = (numLayers-1)/2;
93
    float G = X*0.5f/num;     // height of one Layer
94

    
95
    for(int i=0; i<num; i++)
96
      {
97
      cuts[        i] = -D + (i+0.5f)*G;
98
      cuts[2*num-1-i] = -cuts[i];
99
      }
100

    
101
    return cuts;
102
    }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105
// Fill out mCurrCorner{X,Y,Z} by applying appropriate Quat to mBasicCorner{X,Y,Z}
106
// Appropriate one: QUATS[QUAT_INDICES[corner]].
107

    
108
  private void computeBasicCornerVectors(int corner)
109
    {
110
    Static4D quat = QUATS[QUAT_CORNER_INDICES[corner]];
111

    
112
    mCurrCornerV[0] = RubikSurfaceView.rotateVectorByQuat(mBasicCornerV[0],quat);
113
    mCurrCornerV[1] = RubikSurfaceView.rotateVectorByQuat(mBasicCornerV[1],quat);
114
    mCurrCornerV[2] = RubikSurfaceView.rotateVectorByQuat(mBasicCornerV[2],quat);
115
    }
116

    
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118

    
119
  private float[] computeCorner(int numCubitsPerCorner, int numLayers, int corner, int part)
120
    {
121
    float D = numLayers/3.0f;
122
    float[] corn = CORNERS[corner];
123

    
124
    if( part==0 )
125
      {
126
      return new float[] { corn[0]*D, corn[1]*D, corn[2]*D };
127
      }
128
    else
129
      {
130
      float E = D/(0.5f*(numLayers-1));   // ?? maybe 0.5*
131
      int N = (numCubitsPerCorner-1)/3;
132
      int block = (part-1) % N;
133
      int index = (part-1) / N;
134
      Static4D pri = mCurrCornerV[index];
135
      Static4D sec = mCurrCornerV[(index+2)%3];
136

    
137
      int layers= (numLayers-5)/2;
138
      int multP = (block % layers) + 1;
139
      int multS = (block / layers);
140

    
141
      return new float[] {
142
                          corn[0]*D + (pri.get0()*multP + sec.get0()*multS)*E,
143
                          corn[1]*D + (pri.get1()*multP + sec.get1()*multS)*E,
144
                          corn[2]*D + (pri.get2()*multP + sec.get2()*multS)*E
145
                         };
146
      }
147
    }
148

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150

    
151
  private float[] computeCenter(int numLayers, int center, int part)
152
    {
153
    int corner = mCenterMap[center][part];
154
    float[] cent = mCenterCoords[center];
155
    float[] corn = CORNERS[corner];
156
    float D = numLayers/3.0f;
157
    float F = 1.0f - (2.0f*numLayers-6.0f)/(numLayers-1)*COS54*COS54;
158

    
159
    return new float[]
160
      {
161
        D * ( cent[0] + (corn[0]-cent[0])*F),
162
        D * ( cent[1] + (corn[1]-cent[1])*F),
163
        D * ( cent[2] + (corn[2]-cent[2])*F)
164
      };
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  private int computeEdgeType(int cubit, int numCubitsPerCorner, int numCubitsPerEdge)
170
    {
171
    int part = (cubit - NUM_CORNERS*numCubitsPerCorner) % numCubitsPerEdge;
172
    return (part+1)/2;
173
    }
174

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

    
177
  private float[] computeEdge(int numLayers, int edge, int part)
178
    {
179
    float D = numLayers/3.0f;
180

    
181
    float[] c1 = CORNERS[ mEdgeMap[edge][0] ];
182
    float[] c2 = CORNERS[ mEdgeMap[edge][1] ];
183
    float x = D * (c1[0]+c2[0]) / 2;
184
    float y = D * (c1[1]+c2[1]) / 2;
185
    float z = D * (c1[2]+c2[2]) / 2;
186

    
187
    part /= 2;
188

    
189
    if( part==0 )
190
      {
191
      return new float[] { x, y, z };
192
      }
193
    else
194
      {
195
      int mult = (part+1)/2;
196
      int dir  = (part+1)%2;
197
      float[] center = mCenterCoords[ mEdgeMap[edge][dir+2] ];
198

    
199
      float vX = D*center[0] - x;
200
      float vY = D*center[1] - y;
201
      float vZ = D*center[2] - z;
202

    
203
      float A = mult*D*COS18/(numLayers-1);
204
      A /= (float)Math.sqrt(vX*vX+vY*vY+vZ*vZ);
205

    
206
      return new float[] { x+A*vX, y+A*vY, z+A*vZ };
207
      }
208
    }
209

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

    
212
  float[][] getCubitPositions(int numLayers)
213
    {
214
    if( numLayers<5 ) return CORNERS;
215

    
216
    int numCubitsPerCorner = numCubitsPerCorner(numLayers);
217
    int numCubitsPerEdge   = numCubitsPerEdge(numLayers);
218
    int numCubitsPerCenter = 5;
219
    int numCubits = NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge + NUM_CENTERS*numCubitsPerCenter;
220
    int index=0;
221

    
222
    final float[][] CENTERS = new float[numCubits][];
223

    
224
    for(int corner=0; corner<NUM_CORNERS; corner++)
225
      {
226
      computeBasicCornerVectors(corner);
227

    
228
      for(int part=0; part<numCubitsPerCorner; part++, index++)
229
        {
230
        CENTERS[index] = computeCorner(numCubitsPerCorner,numLayers,corner,part);
231
        }
232
      }
233

    
234
    for(int edge=0; edge<NUM_EDGES; edge++)
235
      {
236
      for(int part=0; part<numCubitsPerEdge; part++, index++)
237
        {
238
        CENTERS[index] = computeEdge(numLayers, edge, part );
239
        }
240
      }
241

    
242
    for(int center=0; center<NUM_CENTERS; center++, index++)
243
      {
244
      for(int part=0; part<numCubitsPerCenter; part++, index++)
245
        {
246
        CENTERS[index] = computeCenter(numLayers,center, part);
247
        }
248
      }
249

    
250
    return CENTERS;
251
    }
252

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254
// TODO
255

    
256
  private int getQuat(int cubit)
257
    {
258
    return ( cubit>=0 && cubit<20 ) ? QUAT_CORNER_INDICES[cubit] : 0;
259
    }
260

    
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262
// TODO
263

    
264
  MeshBase createCubitMesh(int cubit, int numLayers)
265
    {
266
    if( mMesh==null ) mMesh = FactoryCubit.getInstance().createKilominxCornerMesh();
267
    MeshBase mesh = mMesh.copy(true);
268

    
269
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[getQuat(cubit)], new Static3D(0,0,0) );
270
    mesh.apply(quat,0xffffffff,0);
271

    
272
    return mesh;
273
    }
274

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276
// TODO
277

    
278
  int getFaceColor(int cubit, int cubitface, int numLayers)
279
    {
280
    return cubitface>=0 && cubitface<3 ? mCornerFaceMap[cubit][cubitface] : NUM_TEXTURES*NUM_FACES;
281
    }
282

    
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284
// TODO
285

    
286
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
287
    {
288
    float S = 0.07f;
289
    float R = 0.09f;
290

    
291
    float A = 0.86f;
292
    float X1= (SQ5+1)/8;
293
    float Y1= (float)(Math.sqrt(2+0.4f*SQ5)/4);
294
    float Y2= Y1 - (float)(Math.sqrt(10-2*SQ5)/8);
295

    
296
    float[] vertices = { -X1, Y2, 0, -A*Y1, X1, Y2, 0, Y1 };
297

    
298
    FactorySticker factory = FactorySticker.getInstance();
299
    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face], R);
300

    
301
    float MID = TEXTURE_HEIGHT*0.5f;
302
    float WID = TEXTURE_HEIGHT*0.1f;
303
    float HEI = TEXTURE_HEIGHT*(0.47f+Y1);
304
    canvas.drawLine(left+MID-WID,top+HEI,left+MID+WID,top+HEI,paint);
305
    }
306

    
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308
// PUBLIC API
309

    
310
  public boolean isSolved()
311
    {
312
    int index = CUBITS[0].mQuatIndex;
313

    
314
    for(int i=1; i<NUM_CUBITS; i++)
315
      {
316
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
317
      }
318

    
319
    return true;
320
    }
321

    
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

    
324
  public int getObjectName(int numLayers)
325
    {
326
    if( numLayers==3 ) return R.string.minx2;
327
    if( numLayers==5 ) return R.string.minx4;
328

    
329
    return 0;
330
    }
331

    
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333

    
334
  public int getInventor(int numLayers)
335
    {
336
    if( numLayers==3 ) return R.string.minx2_inventor;
337
    if( numLayers==5 ) return R.string.minx4_inventor;
338

    
339
    return 0;
340
    }
341

    
342
///////////////////////////////////////////////////////////////////////////////////////////////////
343

    
344
  public int getComplexity(int numLayers)
345
    {
346
    return 3;
347
    }
348
}
(28-28/35)